Merge "Modify emergency number detection"
diff --git a/api/current.xml b/api/current.xml
index f02ec65..2624b64 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -20161,17 +20161,6 @@
  visibility="public"
 >
 </method>
-<method name="getGetter"
- return="java.lang.reflect.Method"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
 <method name="getPropertyName"
  return="java.lang.String"
  abstract="false"
@@ -20183,17 +20172,6 @@
  visibility="public"
 >
 </method>
-<method name="getSetter"
- return="java.lang.reflect.Method"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
 <method name="ofFloat"
  return="android.animation.PropertyValuesHolder"
  abstract="false"
@@ -20282,19 +20260,6 @@
 <parameter name="values" type="float...">
 </parameter>
 </method>
-<method name="setGetter"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="getter" type="java.lang.reflect.Method">
-</parameter>
-</method>
 <method name="setIntValues"
  return="void"
  abstract="false"
@@ -20347,19 +20312,6 @@
 <parameter name="propertyName" type="java.lang.String">
 </parameter>
 </method>
-<method name="setSetter"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="setter" type="java.lang.reflect.Method">
-</parameter>
-</method>
 </class>
 <class name="RGBEvaluator"
  extends="java.lang.Object"
@@ -75748,6 +75700,16 @@
  visibility="public"
 >
 </field>
+<field name="inPreferQualityOverSpeed"
+ type="boolean"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="inPreferredConfig"
  type="android.graphics.Bitmap.Config"
  transient="false"
@@ -184371,6 +184333,19 @@
 <parameter name="gmtoff" type="long">
 </parameter>
 </method>
+<method name="getJulianMondayFromWeeksSinceEpoch"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="week" type="int">
+</parameter>
+</method>
 <method name="getWeekNumber"
  return="int"
  abstract="false"
@@ -184382,6 +184357,21 @@
  visibility="public"
 >
 </method>
+<method name="getWeeksSinceEpochFromJulianDay"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="julianDay" type="int">
+</parameter>
+<parameter name="firstDayOfWeek" type="int">
+</parameter>
+</method>
 <method name="isEpoch"
  return="boolean"
  abstract="false"
@@ -184605,6 +184595,17 @@
  visibility="public"
 >
 </field>
+<field name="MONDAY_BEFORE_JULIAN_EPOCH"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2440585"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="MONTH"
  type="int"
  transient="false"
@@ -198462,6 +198463,17 @@
  visibility="public"
 >
 </field>
+<field name="FLAG_FALLBACK"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1024"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="FLAG_FROM_SYSTEM"
  type="int"
  transient="false"
@@ -198693,6 +198705,17 @@
  visibility="public"
 >
 </field>
+<field name="KEYCODE_APP_SWITCH"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="187"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="KEYCODE_AT"
  type="int"
  transient="false"
@@ -227733,6 +227756,28 @@
 <parameter name="newFocus" type="android.view.View">
 </parameter>
 </method>
+<method name="onPause"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="onResume"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="overlayHorizontalScrollbar"
  return="boolean"
  abstract="false"
@@ -227831,6 +227876,19 @@
  visibility="public"
 >
 </method>
+<method name="removeJavascriptInterface"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="interfaceName" type="java.lang.String">
+</parameter>
+</method>
 <method name="requestFocusNodeHref"
  return="void"
  abstract="false"
@@ -234517,7 +234575,7 @@
 >
 <parameter name="year" type="int">
 </parameter>
-<parameter name="monthOfYear" type="int">
+<parameter name="month" type="int">
 </parameter>
 <parameter name="dayOfMonth" type="int">
 </parameter>
@@ -234569,6 +234627,172 @@
 </parameter>
 </method>
 </interface>
+<class name="DayPicker"
+ extends="android.widget.FrameLayout"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="DayPicker"
+ type="android.widget.DayPicker"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+</constructor>
+<constructor name="DayPicker"
+ type="android.widget.DayPicker"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="attrs" type="android.util.AttributeSet">
+</parameter>
+</constructor>
+<constructor name="DayPicker"
+ type="android.widget.DayPicker"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="attrs" type="android.util.AttributeSet">
+</parameter>
+<parameter name="defStyle" type="int">
+</parameter>
+</constructor>
+<method name="getSelectedDay"
+ return="java.util.Calendar"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="goTo"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="year" type="int">
+</parameter>
+<parameter name="month" type="int">
+</parameter>
+<parameter name="dayOfMonth" type="int">
+</parameter>
+<parameter name="animate" type="boolean">
+</parameter>
+<parameter name="setSelected" type="boolean">
+</parameter>
+<parameter name="forceScroll" type="boolean">
+</parameter>
+</method>
+<method name="goTo"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="date" type="java.util.Calendar">
+</parameter>
+<parameter name="animate" type="boolean">
+</parameter>
+<parameter name="setSelected" type="boolean">
+</parameter>
+<parameter name="forceScroll" type="boolean">
+</parameter>
+</method>
+<method name="setOnDateChangeListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="listener" type="android.widget.DayPicker.OnSelectedDayChangeListener">
+</parameter>
+</method>
+<method name="setRange"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="startRangeDate" type="java.util.Calendar">
+</parameter>
+<parameter name="endRangeDate" type="java.util.Calendar">
+</parameter>
+</method>
+<method name="setSelectedDay"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="selectedDay" type="java.util.Calendar">
+</parameter>
+</method>
+</class>
+<interface name="DayPicker.OnSelectedDayChangeListener"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="onSelectedDayChange"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="view" type="android.widget.DayPicker">
+</parameter>
+<parameter name="year" type="int">
+</parameter>
+<parameter name="month" type="int">
+</parameter>
+<parameter name="dayOfMonth" type="int">
+</parameter>
+</method>
+</interface>
 <class name="DialerFilter"
  extends="android.widget.RelativeLayout"
  abstract="false"
@@ -239727,6 +239951,325 @@
 </parameter>
 </method>
 </interface>
+<class name="NumberPicker"
+ extends="android.widget.LinearLayout"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="NumberPicker"
+ type="android.widget.NumberPicker"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+</constructor>
+<constructor name="NumberPicker"
+ type="android.widget.NumberPicker"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="attrs" type="android.util.AttributeSet">
+</parameter>
+</constructor>
+<constructor name="NumberPicker"
+ type="android.widget.NumberPicker"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="attrs" type="android.util.AttributeSet">
+</parameter>
+<parameter name="defStyle" type="int">
+</parameter>
+</constructor>
+<method name="getCurrent"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getRangeEnd"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getRangeStart"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="setCurrent"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="current" type="int">
+</parameter>
+</method>
+<method name="setFormatter"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="formatter" type="android.widget.NumberPicker.Formatter">
+</parameter>
+</method>
+<method name="setOnChangeListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="onChangeListener" type="android.widget.NumberPicker.OnChangeListener">
+</parameter>
+</method>
+<method name="setOnLongPressUpdateInterval"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="intervalMillis" type="long">
+</parameter>
+</method>
+<method name="setOnScrollListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="onScrollListener" type="android.widget.NumberPicker.OnScrollListener">
+</parameter>
+</method>
+<method name="setRange"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="start" type="int">
+</parameter>
+<parameter name="end" type="int">
+</parameter>
+</method>
+<method name="setRange"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="start" type="int">
+</parameter>
+<parameter name="end" type="int">
+</parameter>
+<parameter name="displayedValues" type="java.lang.String[]">
+</parameter>
+</method>
+<method name="setRange"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="start" type="int">
+</parameter>
+<parameter name="end" type="int">
+</parameter>
+<parameter name="displayedValues" type="java.lang.String[]">
+</parameter>
+<parameter name="wrapSelectorWheel" type="boolean">
+</parameter>
+</method>
+<method name="setWrapSelectorWheel"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="wrapSelector" type="boolean">
+</parameter>
+</method>
+<field name="TWO_DIGIT_FORMATTER"
+ type="android.widget.NumberPicker.Formatter"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<interface name="NumberPicker.Formatter"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="toString"
+ return="java.lang.String"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="int">
+</parameter>
+</method>
+</interface>
+<interface name="NumberPicker.OnChangeListener"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="onChange"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="picker" type="android.widget.NumberPicker">
+</parameter>
+<parameter name="oldVal" type="int">
+</parameter>
+<parameter name="newVal" type="int">
+</parameter>
+</method>
+</interface>
+<interface name="NumberPicker.OnScrollListener"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="onScrollStateChange"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="view" type="android.widget.NumberPicker">
+</parameter>
+<parameter name="scrollState" type="int">
+</parameter>
+</method>
+<field name="SCROLL_STATE_FLING"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SCROLL_STATE_IDLE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SCROLL_STATE_TOUCH_SCROLL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</interface>
 <class name="OverScroller"
  extends="java.lang.Object"
  abstract="false"
@@ -250407,7 +250950,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="arg0" type="T">
+<parameter name="t" type="T">
 </parameter>
 </method>
 </interface>
diff --git a/cmds/stagefright/stream.cpp b/cmds/stagefright/stream.cpp
index f2b5638..a3d7a6e 100644
--- a/cmds/stagefright/stream.cpp
+++ b/cmds/stagefright/stream.cpp
@@ -3,6 +3,7 @@
 #include <media/IStreamSource.h>
 #include <media/mediaplayer.h>
 #include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
 
 #include <binder/IServiceManager.h>
 #include <media/IMediaPlayerService.h>
@@ -56,7 +57,7 @@
 
     ssize_t n = read(mFd, mem->pointer(), mem->size());
     if (n <= 0) {
-        mListener->queueCommand(IStreamListener::EOS);
+        mListener->issueCommand(IStreamListener::EOS, false /* synchronous */);
     } else {
         mListener->queueBuffer(index, n);
     }
diff --git a/core/java/android/accounts/AccountManagerService.java b/core/java/android/accounts/AccountManagerService.java
index 61ef8f2..a815b3a 100644
--- a/core/java/android/accounts/AccountManagerService.java
+++ b/core/java/android/accounts/AccountManagerService.java
@@ -838,6 +838,44 @@
         }
     }
 
+    void getAuthTokenLabel(final IAccountManagerResponse response,
+            final Account account, final String authTokenType) {
+        if (account == null) throw new IllegalArgumentException("account is null");
+        if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null");
+
+        checkBinderPermission(Manifest.permission.USE_CREDENTIALS);
+
+        long identityToken = clearCallingIdentity();
+        try {
+            new Session(response, account.type, false,
+                    false /* stripAuthTokenFromResult */) {
+                protected String toDebugString(long now) {
+                    return super.toDebugString(now) + ", getAuthTokenLabel"
+                            + ", " + account
+                            + ", authTokenType " + authTokenType;
+                }
+
+                public void run() throws RemoteException {
+                    mAuthenticator.getAuthTokenLabel(this, authTokenType);
+                }
+
+                public void onResult(Bundle result) {
+                    if (result != null) {
+                        String label = result.getString(AccountManager.KEY_AUTH_TOKEN_LABEL);
+                        Bundle bundle = new Bundle();
+                        bundle.putString(AccountManager.KEY_AUTH_TOKEN_LABEL, label);
+                        super.onResult(bundle);
+                        return;
+                    } else {
+                        super.onResult(result);
+                    }
+                }
+            }.bind();
+        } finally {
+            restoreCallingIdentity(identityToken);
+        }
+    }
+
     public void getAuthToken(IAccountManagerResponse response, final Account account,
             final String authTokenType, final boolean notifyOnAuthFailure,
             final boolean expectActivityLaunch, final Bundle loginOptions) {
@@ -956,36 +994,36 @@
         installNotification(getCredentialPermissionNotificationId(account, authTokenType, uid), n);
     }
 
-    private Intent newGrantCredentialsPermissionIntent(Account account, int uid,
-            AccountAuthenticatorResponse response, String authTokenType, String authTokenLabel) {
+    String getAccountLabel(String accountType) {
         RegisteredServicesCache.ServiceInfo<AuthenticatorDescription> serviceInfo =
-                mAuthenticatorCache.getServiceInfo(
-                        AuthenticatorDescription.newKey(account.type));
+            mAuthenticatorCache.getServiceInfo(
+                    AuthenticatorDescription.newKey(accountType));
         if (serviceInfo == null) {
-            throw new IllegalArgumentException("unknown account type: " + account.type);
+            throw new IllegalArgumentException("unknown account type: " + accountType);
         }
 
         final Context authContext;
         try {
             authContext = mContext.createPackageContext(
-                serviceInfo.type.packageName, 0);
+                    serviceInfo.type.packageName, 0);
         } catch (PackageManager.NameNotFoundException e) {
-            throw new IllegalArgumentException("unknown account type: " + account.type);
+            throw new IllegalArgumentException("unknown account type: " + accountType);
         }
+        return authContext.getString(serviceInfo.type.labelId);
+    }
+
+    private Intent newGrantCredentialsPermissionIntent(Account account, int uid,
+            AccountAuthenticatorResponse response, String authTokenType, String authTokenLabel) {
 
         Intent intent = new Intent(mContext, GrantCredentialsPermissionActivity.class);
-        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
         intent.addCategory(
                 String.valueOf(getCredentialPermissionNotificationId(account, authTokenType, uid)));
+
         intent.putExtra(GrantCredentialsPermissionActivity.EXTRAS_ACCOUNT, account);
-        intent.putExtra(GrantCredentialsPermissionActivity.EXTRAS_AUTH_TOKEN_LABEL, authTokenLabel);
         intent.putExtra(GrantCredentialsPermissionActivity.EXTRAS_AUTH_TOKEN_TYPE, authTokenType);
         intent.putExtra(GrantCredentialsPermissionActivity.EXTRAS_RESPONSE, response);
-        intent.putExtra(GrantCredentialsPermissionActivity.EXTRAS_ACCOUNT_TYPE_LABEL,
-                        authContext.getString(serviceInfo.type.labelId));
-        intent.putExtra(GrantCredentialsPermissionActivity.EXTRAS_PACKAGES,
-                        mPackageManager.getPackagesForUid(uid));
         intent.putExtra(GrantCredentialsPermissionActivity.EXTRAS_REQUESTING_UID, uid);
+
         return intent;
     }
 
diff --git a/core/java/android/accounts/GrantCredentialsPermissionActivity.java b/core/java/android/accounts/GrantCredentialsPermissionActivity.java
index fd340cbe..83e4fd9 100644
--- a/core/java/android/accounts/GrantCredentialsPermissionActivity.java
+++ b/core/java/android/accounts/GrantCredentialsPermissionActivity.java
@@ -17,6 +17,7 @@
 
 import android.app.Activity;
 import android.os.Bundle;
+import android.os.RemoteException;
 import android.widget.TextView;
 import android.widget.LinearLayout;
 import android.widget.ImageView;
@@ -26,6 +27,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
+import android.content.pm.RegisteredServicesCache;
 import android.text.TextUtils;
 import android.graphics.drawable.Drawable;
 import com.android.internal.R;
@@ -46,6 +48,7 @@
     private int mUid;
     private Bundle mResultBundle = null;
     protected LayoutInflater mInflater;
+    private final AccountManagerService accountManagerService = AccountManagerService.getSingleton();
 
     protected void onCreate(Bundle savedInstanceState) {
         requestWindowFeature(Window.FEATURE_NO_TITLE);
@@ -55,27 +58,56 @@
         mInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
 
         final Bundle extras = getIntent().getExtras();
+
+        // Grant 'account'/'type' to mUID
         mAccount = extras.getParcelable(EXTRAS_ACCOUNT);
         mAuthTokenType = extras.getString(EXTRAS_AUTH_TOKEN_TYPE);
+        mUid = extras.getInt(EXTRAS_REQUESTING_UID);
+        final PackageManager pm = getPackageManager();
+        final String[] packages = pm.getPackagesForUid(mUid);
 
-        if (mAccount == null || mAuthTokenType == null) {
+        if (mAccount == null || mAuthTokenType == null || packages == null) {
             // we were somehow started with bad parameters. abort the activity.
             setResult(Activity.RESULT_CANCELED);
             finish();
             return;
         }
 
-        mUid = extras.getInt(EXTRAS_REQUESTING_UID);
-        final String accountTypeLabel = extras.getString(EXTRAS_ACCOUNT_TYPE_LABEL);
-        final String[] packages = extras.getStringArray(EXTRAS_PACKAGES);
-        final String authTokenLabel = extras.getString(EXTRAS_AUTH_TOKEN_LABEL);
+        final String accountTypeLabel = accountManagerService.getAccountLabel(mAccount.type);
+
+
+        final TextView authTokenTypeView = (TextView) findViewById(R.id.authtoken_type);
+        authTokenTypeView.setVisibility(View.GONE);
+
+        /** Handles the responses from the AccountManager */
+        IAccountManagerResponse response = new IAccountManagerResponse.Stub() {
+            public void onResult(Bundle bundle) {
+                final String authTokenLabel =
+                    bundle.getString(AccountManager.KEY_AUTH_TOKEN_LABEL);
+                if (!TextUtils.isEmpty(authTokenLabel)) {
+                    runOnUiThread(new Runnable() {
+                        public void run() {
+                            if (!isFinishing()) {
+                                authTokenTypeView.setText(authTokenLabel);
+                                authTokenTypeView.setVisibility(View.VISIBLE);
+                            }
+                        }
+                    });
+                }
+            }
+
+            public void onError(int code, String message) {
+            }
+        };
+
+        accountManagerService.getAuthTokenLabel(
+                response, mAccount, mAuthTokenType);
 
         findViewById(R.id.allow_button).setOnClickListener(this);
         findViewById(R.id.deny_button).setOnClickListener(this);
 
         LinearLayout packagesListView = (LinearLayout) findViewById(R.id.packages_list);
 
-        final PackageManager pm = getPackageManager();
         for (String pkg : packages) {
             String packageLabel;
             try {
@@ -88,12 +120,6 @@
 
         ((TextView) findViewById(R.id.account_name)).setText(mAccount.name);
         ((TextView) findViewById(R.id.account_type)).setText(accountTypeLabel);
-        TextView authTokenTypeView = (TextView) findViewById(R.id.authtoken_type);
-        if (TextUtils.isEmpty(authTokenLabel)) {
-            authTokenTypeView.setVisibility(View.GONE);
-        } else {
-            authTokenTypeView.setText(authTokenLabel);
-        }
     }
 
     private View newPackageView(String packageLabel) {
@@ -103,7 +129,6 @@
     }
 
     public void onClick(View v) {
-        final AccountManagerService accountManagerService = AccountManagerService.getSingleton();
         switch (v.getId()) {
             case R.id.allow_button:
                 accountManagerService.grantAppPermission(mAccount, mAuthTokenType, mUid);
diff --git a/core/java/android/animation/Animator.java b/core/java/android/animation/Animator.java
index 22e04a7..5fe3644 100644
--- a/core/java/android/animation/Animator.java
+++ b/core/java/android/animation/Animator.java
@@ -36,22 +36,36 @@
      * this call, because all animation events are posted to a central timing loop so that animation
      * times are all synchronized on a single timing pulse on the UI thread. So the animation will
      * start the next time that event handler processes events.
+     *
+     * <p>The animation started by calling this method will be run on the thread that called
+     * this method. This thread should have a Looper on it (a runtime exception will be thrown if
+     * this is not the case). Also, if the animation will animate
+     * properties of objects in the view hierarchy, then the calling thread should be the UI
+     * thread for that view hierarchy.</p>
+     *
      */
     public void start() {
     }
 
     /**
      * Cancels the animation. Unlike {@link #end()}, <code>cancel()</code> causes the animation to
-     * stop in its tracks, sending an {@link android.animation.Animator.AnimatorListener#onAnimationCancel(Animator)} to
-     * its listeners, followed by an {@link android.animation.Animator.AnimatorListener#onAnimationEnd(Animator)} message.
+     * stop in its tracks, sending an
+     * {@link android.animation.Animator.AnimatorListener#onAnimationCancel(Animator)} to
+     * its listeners, followed by an
+     * {@link android.animation.Animator.AnimatorListener#onAnimationEnd(Animator)} message.
+     *
+     * <p>This method must be called on the thread that is running the animation.</p>
      */
     public void cancel() {
     }
 
     /**
      * Ends the animation. This causes the animation to assign the end value of the property being
-     * animated, then calling the {@link android.animation.Animator.AnimatorListener#onAnimationEnd(Animator)} method on
+     * animated, then calling the
+     * {@link android.animation.Animator.AnimatorListener#onAnimationEnd(Animator)} method on
      * its listeners.
+     *
+     * <p>This method must be called on the thread that is running the animation.</p>
      */
     public void end() {
     }
diff --git a/core/java/android/animation/AnimatorSet.java b/core/java/android/animation/AnimatorSet.java
index 154e084..d77dbdc 100644
--- a/core/java/android/animation/AnimatorSet.java
+++ b/core/java/android/animation/AnimatorSet.java
@@ -96,6 +96,9 @@
     // The amount of time in ms to delay starting the animation after start() is called
     private long mStartDelay = 0;
 
+    // Animator used for a nonzero startDelay
+    private ValueAnimator mDelayAnim = null;
+
 
     // How long the child animations should last in ms. The default value is negative, which
     // simply means that there is no duration set on the AnimatorSet. When a real duration is
@@ -276,6 +279,19 @@
                 listener.onAnimationCancel(this);
             }
         }
+        if (mDelayAnim != null && mDelayAnim.isRunning()) {
+            // If we're currently in the startDelay period, just cancel that animator and
+            // send out the end event to all listeners
+            mDelayAnim.cancel();
+            if (mListeners != null) {
+                ArrayList<AnimatorListener> tmpListeners =
+                        (ArrayList<AnimatorListener>) mListeners.clone();
+                for (AnimatorListener listener : tmpListeners) {
+                    listener.onAnimationEnd(this);
+                }
+            }
+            return;
+        }
         if (mSortedNodes.size() > 0) {
             for (Node node : mSortedNodes) {
                 node.animation.cancel();
@@ -302,6 +318,9 @@
                 node.animation.addListener(mSetListener);
             }
         }
+        if (mDelayAnim != null) {
+            mDelayAnim.cancel();
+        }
         if (mSortedNodes.size() > 0) {
             for (Node node : mSortedNodes) {
                 node.animation.end();
@@ -411,12 +430,25 @@
         // contains the animation nodes in the correct order.
         sortNodes();
 
+        int numSortedNodes = mSortedNodes.size();
+        for (int i = 0; i < numSortedNodes; ++i) {
+            Node node = mSortedNodes.get(i);
+            // First, clear out the old listeners
+            ArrayList<AnimatorListener> oldListeners = node.animation.getListeners();
+            if (oldListeners != null && oldListeners.size() > 0) {
+                for (AnimatorListener listener : oldListeners) {
+                    if (listener instanceof DependencyListener) {
+                        node.animation.removeListener(listener);
+                    }
+                }
+            }
+        }
+
         // nodesToStart holds the list of nodes to be started immediately. We don't want to
         // start the animations in the loop directly because we first need to set up
         // dependencies on all of the nodes. For example, we don't want to start an animation
         // when some other animation also wants to start when the first animation begins.
         final ArrayList<Node> nodesToStart = new ArrayList<Node>();
-        int numSortedNodes = mSortedNodes.size();
         for (int i = 0; i < numSortedNodes; ++i) {
             Node node = mSortedNodes.get(i);
             if (mSetListener == null) {
@@ -443,19 +475,25 @@
             }
         } else {
             // TODO: Need to cancel out of the delay appropriately
-            ValueAnimator delayAnim = ValueAnimator.ofFloat(0f, 1f);
-            delayAnim.setDuration(mStartDelay);
-            delayAnim.addListener(new AnimatorListenerAdapter() {
+            mDelayAnim = ValueAnimator.ofFloat(0f, 1f);
+            mDelayAnim.setDuration(mStartDelay);
+            mDelayAnim.addListener(new AnimatorListenerAdapter() {
+                boolean canceled = false;
+                public void onAnimationCancel(Animator anim) {
+                    canceled = true;
+                }
                 public void onAnimationEnd(Animator anim) {
-                    int numNodes = nodesToStart.size();
-                    for (int i = 0; i < numNodes; ++i) {
-                        Node node = nodesToStart.get(i);
-                        node.animation.start();
-                        mPlayingSet.add(node.animation);
+                    if (!canceled) {
+                        int numNodes = nodesToStart.size();
+                        for (int i = 0; i < numNodes; ++i) {
+                            Node node = nodesToStart.get(i);
+                            node.animation.start();
+                            mPlayingSet.add(node.animation);
+                        }
                     }
                 }
             });
-            delayAnim.start();
+            mDelayAnim.start();
         }
         if (mListeners != null) {
             ArrayList<AnimatorListener> tmpListeners =
diff --git a/core/java/android/animation/ObjectAnimator.java b/core/java/android/animation/ObjectAnimator.java
index 7c2e70d..7f11871 100644
--- a/core/java/android/animation/ObjectAnimator.java
+++ b/core/java/android/animation/ObjectAnimator.java
@@ -19,6 +19,7 @@
 import android.util.Log;
 
 import java.lang.reflect.Method;
+import java.util.ArrayList;
 
 /**
  * This subclass of {@link ValueAnimator} provides support for animating properties on target objects.
@@ -31,6 +32,7 @@
  *
  */
 public final class ObjectAnimator extends ValueAnimator {
+    private static final boolean DBG = false;
 
     // The target object on which the property exists, set in the constructor
     private Object mTarget;
@@ -265,6 +267,21 @@
         }
     }
 
+    @Override
+    public void start() {
+        if (DBG) {
+            Log.d("ObjectAnimator", "Anim target, duration" + mTarget + ", " + getDuration());
+            for (int i = 0; i < mValues.length; ++i) {
+                PropertyValuesHolder pvh = mValues[i];
+                ArrayList<Keyframe> keyframes = pvh.mKeyframeSet.mKeyframes;
+                Log.d("ObjectAnimator", "   Values[" + i + "]: " +
+                    pvh.getPropertyName() + ", " + keyframes.get(0).getValue() + ", " +
+                    keyframes.get(pvh.mKeyframeSet.mNumKeyframes - 1).getValue());
+            }
+        }
+        super.start();
+    }
+
     /**
      * This function is called immediately before processing the first animation
      * frame of an animation. If there is a nonzero <code>startDelay</code>, the
diff --git a/core/java/android/animation/PropertyValuesHolder.java b/core/java/android/animation/PropertyValuesHolder.java
index 97aa5a1..1412f38 100644
--- a/core/java/android/animation/PropertyValuesHolder.java
+++ b/core/java/android/animation/PropertyValuesHolder.java
@@ -178,9 +178,8 @@
      * on the object. Also, if any value is null, the value will be filled in when the animation
      * starts in the same way. This mechanism of automatically getting null values only works
      * if the PropertyValuesHolder object is used in conjunction
-     * {@link ObjectAnimator}, and with a getter function either
-     * derived automatically from <code>propertyName</code> or set explicitly via
-     * {@link #setGetter(java.lang.reflect.Method)}, since otherwise PropertyValuesHolder has
+     * {@link ObjectAnimator}, and with a getter function
+     * derived automatically from <code>propertyName</code>, since otherwise PropertyValuesHolder has
      * no way of determining what the value should be.
      * @param propertyName The name of the property associated with this set of values. This
      * can be the actual property name to be used when using a ObjectAnimator object, or
@@ -210,9 +209,8 @@
      * on the object. Also, if any value is null, the value will be filled in when the animation
      * starts in the same way. This mechanism of automatically getting null values only works
      * if the PropertyValuesHolder object is used in conjunction
-     * {@link ObjectAnimator}, and with a getter function either
-     * derived automatically from <code>propertyName</code> or set explicitly via
-     * {@link #setGetter(java.lang.reflect.Method)}, since otherwise PropertyValuesHolder has
+     * {@link ObjectAnimator}, and with a getter function
+     * derived automatically from <code>propertyName</code>, since otherwise PropertyValuesHolder has
      * no way of determining what the value should be.
      *
      * @param values One or more values that the animation will animate between.
@@ -229,9 +227,8 @@
      * on the object. Also, if any value is null, the value will be filled in when the animation
      * starts in the same way. This mechanism of automatically getting null values only works
      * if the PropertyValuesHolder object is used in conjunction
-     * {@link ObjectAnimator}, and with a getter function either
-     * derived automatically from <code>propertyName</code> or set explicitly via
-     * {@link #setGetter(java.lang.reflect.Method)}, since otherwise PropertyValuesHolder has
+     * {@link ObjectAnimator}, and with a getter function
+     * derived automatically from <code>propertyName</code>, since otherwise PropertyValuesHolder has
      * no way of determining what the value should be.
      *
      * @param values One or more values that the animation will animate between.
@@ -263,9 +260,8 @@
      * on the object. Also, if any value is null, the value will be filled in when the animation
      * starts in the same way. This mechanism of automatically getting null values only works
      * if the PropertyValuesHolder object is used in conjunction
-     * {@link ObjectAnimator}, and with a getter function either
-     * derived automatically from <code>propertyName</code> or set explicitly via
-     * {@link #setGetter(java.lang.reflect.Method)}, since otherwise PropertyValuesHolder has
+     * {@link ObjectAnimator}, and with a getter function
+     * derived automatically from <code>propertyName</code>, since otherwise PropertyValuesHolder has
      * no way of determining what the value should be.
      * 
      * @param values One or more values that the animation will animate between.
@@ -329,7 +325,7 @@
             // If we got here, then no appropriate function was found
             Log.e("PropertyValuesHolder",
                     "Couldn't find setter/getter for property " + mPropertyName +
-                            "with value type "+ mValueType);
+                            " with value type "+ mValueType);
         }
 
         return returnVal;
@@ -544,67 +540,6 @@
     }
 
     /**
-     * Sets the <code>Method</code> that is called with the animated values calculated
-     * during the animation. Setting the setter method is an alternative to supplying a
-     * {@link #setPropertyName(String) propertyName} from which the method is derived. This
-     * approach is more direct, and is especially useful when a function must be called that does
-     * not correspond to the convention of <code>setName()</code>. For example, if a function
-     * called <code>offset()</code> is to be called with the animated values, there is no way
-     * to tell <code>ObjectAnimator</code> how to call that function simply through a property
-     * name, so a setter method should be supplied instead.
-     *
-     * <p>Note that the setter function must take the same parameter type as the
-     * <code>valueFrom</code> and <code>valueTo</code> properties, otherwise the call to
-     * the setter function will fail.</p>
-     *
-     * @param setter The setter method that should be called with the animated values.
-     */
-    public void setSetter(Method setter) {
-        mSetter = setter;
-    }
-
-    /**
-     * Gets the <code>Method</code> that is called with the animated values calculated
-     * during the animation.
-     */
-    public Method getSetter() {
-        return mSetter;
-    }
-
-    /**
-     * Sets the <code>Method</code> that is called to get unsupplied <code>valueFrom</code> or
-     * <code>valueTo</code> properties. Setting the getter method is an alternative to supplying a
-     * {@link #setPropertyName(String) propertyName} from which the method is derived. This
-     * approach is more direct, and is especially useful when a function must be called that does
-     * not correspond to the convention of <code>setName()</code>. For example, if a function
-     * called <code>offset()</code> is to be called to get an initial value, there is no way
-     * to tell <code>ObjectAnimator</code> how to call that function simply through a property
-     * name, so a getter method should be supplied instead.
-     *
-     * <p>Note that the getter method is only called whether supplied here or derived
-     * from the property name, if one of <code>valueFrom</code> or <code>valueTo</code> are
-     * null. If both of those values are non-null, then there is no need to get one of the
-     * values and the getter is not called.
-     *
-     * <p>Note that the getter function must return the same parameter type as the
-     * <code>valueFrom</code> and <code>valueTo</code> properties (whichever of them are
-     * non-null), otherwise the call to the getter function will fail.</p>
-     *
-     * @param getter The getter method that should be called to get initial animation values.
-     */
-    public void setGetter(Method getter) {
-        mGetter = getter;
-    }
-
-    /**
-     * Gets the <code>Method</code> that is called to get unsupplied <code>valueFrom</code> or
-     * <code>valueTo</code> properties.
-     */
-    public Method getGetter() {
-        return mGetter;
-    }
-
-    /**
      * Sets the name of the property that will be animated. This name is used to derive
      * a setter function that will be called to set animated values.
      * For example, a property name of <code>foo</code> will result
diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java
index 8e541c2..1542c49 100755
--- a/core/java/android/animation/ValueAnimator.java
+++ b/core/java/android/animation/ValueAnimator.java
@@ -62,9 +62,7 @@
      */
     private static final int STOPPED    = 0; // Not yet playing
     private static final int RUNNING    = 1; // Playing normally
-    private static final int CANCELED   = 2; // cancel() called - need to end it
-    private static final int ENDED      = 3; // end() called - need to end it
-    private static final int SEEKED     = 4; // Seeked to some time value
+    private static final int SEEKED     = 2; // Seeked to some time value
 
     /**
      * Internal variables
@@ -178,7 +176,7 @@
      * Flag that represents the current state of the animation. Used to figure out when to start
      * an animation (if state == STOPPED). Also used to end an animation that
      * has been cancel()'d or end()'d since the last animation frame. Possible values are
-     * STOPPED, RUNNING, ENDED, CANCELED.
+     * STOPPED, RUNNING, SEEKED.
      */
     private int mPlayingState = STOPPED;
 
@@ -581,8 +579,7 @@
                         for (int i = 0; i < count; ++i) {
                             ValueAnimator anim = pendingCopy.get(i);
                             // If the animation has a startDelay, place it on the delayed list
-                            if (anim.mStartDelay == 0 || anim.mPlayingState == ENDED ||
-                                    anim.mPlayingState == CANCELED) {
+                            if (anim.mStartDelay == 0) {
                                 anim.startAnimation();
                             } else {
                                 delayedAnims.add(anim);
@@ -619,14 +616,28 @@
                     // Now process all active animations. The return value from animationFrame()
                     // tells the handler whether it should now be ended
                     int numAnims = animations.size();
-                    for (int i = 0; i < numAnims; ++i) {
+                    int i = 0;
+                    while (i < numAnims) {
                         ValueAnimator anim = animations.get(i);
                         if (anim.animationFrame(currentTime)) {
                             endingAnims.add(anim);
                         }
+                        if (animations.size() == numAnims) {
+                            ++i;
+                        } else {
+                            // An animation might be canceled or ended by client code
+                            // during the animation frame. Check to see if this happened by
+                            // seeing whether the current index is the same as it was before
+                            // calling animationFrame(). Another approach would be to copy
+                            // animations to a temporary list and process that list instead,
+                            // but that entails garbage and processing overhead that would
+                            // be nice to avoid.
+                            --numAnims;
+                            endingAnims.remove(anim);
+                        }
                     }
                     if (endingAnims.size() > 0) {
-                        for (int i = 0; i < endingAnims.size(); ++i) {
+                        for (i = 0; i < endingAnims.size(); ++i) {
                             endingAnims.get(i).endAnimation();
                         }
                         endingAnims.clear();
@@ -918,9 +929,7 @@
         // to run
         if (mPlayingState != STOPPED || sPendingAnimations.get().contains(this) ||
                 sDelayedAnims.get().contains(this)) {
-            // Just set the CANCELED flag - this causes the animation to end the next time a frame
-            // is processed.
-            mPlayingState = CANCELED;
+            endAnimation();
         }
     }
 
@@ -929,23 +938,21 @@
         if (!sAnimations.get().contains(this) && !sPendingAnimations.get().contains(this)) {
             // Special case if the animation has not yet started; get it ready for ending
             mStartedDelay = false;
-            sPendingAnimations.get().add(this);
-            AnimationHandler animationHandler = sAnimationHandler.get();
-            if (animationHandler == null) {
-                animationHandler = new AnimationHandler();
-                sAnimationHandler.set(animationHandler);
-            }
-            animationHandler.sendEmptyMessage(ANIMATION_START);
+            startAnimation();
         }
-        // Just set the ENDED flag - this causes the animation to end the next time a frame
-        // is processed.
-        mPlayingState = ENDED;
+        // The final value set on the target varies, depending on whether the animation
+        // was supposed to repeat an odd number of times
+        if (mRepeatCount > 0 && (mRepeatCount & 0x01) == 1) {
+            animateValue(0f);
+        } else {
+            animateValue(1f);
+        }
+        endAnimation();
     }
 
     @Override
     public boolean isRunning() {
-        // ENDED or CANCELED indicate that it has been ended or canceled, but not processed yet
-        return (mPlayingState == RUNNING || mPlayingState == ENDED || mPlayingState == CANCELED);
+        return (mPlayingState == RUNNING);
     }
 
     /**
@@ -973,6 +980,8 @@
      */
     private void endAnimation() {
         sAnimations.get().remove(this);
+        sPendingAnimations.get().remove(this);
+        sDelayedAnims.get().remove(this);
         mPlayingState = STOPPED;
         if (mListeners != null) {
             ArrayList<AnimatorListener> tmpListeners =
@@ -1014,10 +1023,6 @@
      * should be added to the set of active animations.
      */
     private boolean delayedAnimationFrame(long currentTime) {
-        if (mPlayingState == CANCELED || mPlayingState == ENDED) {
-            // end the delay, process an animation frame to actually cancel it
-            return true;
-        }
         if (!mStartedDelay) {
             mStartedDelay = true;
             mDelayStartTime = currentTime;
@@ -1088,19 +1093,6 @@
             }
             animateValue(fraction);
             break;
-        case ENDED:
-            // The final value set on the target varies, depending on whether the animation
-            // was supposed to repeat an odd number of times
-            if (mRepeatCount > 0 && (mRepeatCount & 0x01) == 1) {
-                animateValue(0f);
-            } else {
-                animateValue(1f);
-            }
-            // Fall through to set done flag
-        case CANCELED:
-            done = true;
-            mPlayingState = STOPPED;
-            break;
         }
 
         return done;
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index d2de382..f1842c6 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -532,10 +532,6 @@
         throw new RuntimeException("Not supported in system context");
     }
 
-    static File makeBackupFile(File prefsFile) {
-        return new File(prefsFile.getPath() + ".bak");
-    }
-
     public File getSharedPrefsFile(String name) {
         return makeFilename(getPreferencesDir(), name + ".xml");
     }
@@ -543,54 +539,19 @@
     @Override
     public SharedPreferences getSharedPreferences(String name, int mode) {
         SharedPreferencesImpl sp;
-        File prefsFile;
-        boolean needInitialLoad = false;
         synchronized (sSharedPrefs) {
             sp = sSharedPrefs.get(name);
-            if (sp != null && !sp.hasFileChangedUnexpectedly()) {
-                return sp;
-            }
-            prefsFile = getSharedPrefsFile(name);
             if (sp == null) {
-                sp = new SharedPreferencesImpl(prefsFile, mode, null);
+                File prefsFile = getSharedPrefsFile(name);
+                sp = new SharedPreferencesImpl(prefsFile, mode);
                 sSharedPrefs.put(name, sp);
-                needInitialLoad = true;
-            }
-        }
-
-        synchronized (sp) {
-            if (needInitialLoad && sp.isLoaded()) {
-                // lost the race to load; another thread handled it
                 return sp;
             }
-            File backup = makeBackupFile(prefsFile);
-            if (backup.exists()) {
-                prefsFile.delete();
-                backup.renameTo(prefsFile);
-            }
-
-            // Debugging
-            if (prefsFile.exists() && !prefsFile.canRead()) {
-                Log.w(TAG, "Attempt to read preferences file " + prefsFile + " without permission");
-            }
-
-            Map map = null;
-            FileStatus stat = new FileStatus();
-            if (FileUtils.getFileStatus(prefsFile.getPath(), stat) && prefsFile.canRead()) {
-                try {
-                    FileInputStream str = new FileInputStream(prefsFile);
-                    map = XmlUtils.readMapXml(str);
-                    str.close();
-                } catch (XmlPullParserException e) {
-                    Log.w(TAG, "getSharedPreferences", e);
-                } catch (FileNotFoundException e) {
-                    Log.w(TAG, "getSharedPreferences", e);
-                } catch (IOException e) {
-                    Log.w(TAG, "getSharedPreferences", e);
-                }
-            }
-            sp.replace(map, stat);
         }
+        // If somebody else (some other process) changed the prefs
+        // file behind our back, we reload it.  This has been the
+        // historical (if undocumented) behavior.
+        sp.startReloadIfChangedUnexpectedly();
         return sp;
     }
 
diff --git a/core/java/android/app/DatePickerDialog.java b/core/java/android/app/DatePickerDialog.java
index 37f8738..efe527f 100644
--- a/core/java/android/app/DatePickerDialog.java
+++ b/core/java/android/app/DatePickerDialog.java
@@ -16,23 +16,18 @@
 
 package android.app;
 
+import com.android.internal.R;
+
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.DialogInterface.OnClickListener;
 import android.os.Build;
 import android.os.Bundle;
-import android.text.TextUtils.TruncateAt;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.widget.DatePicker;
-import android.widget.TextView;
 import android.widget.DatePicker.OnDateChangedListener;
 
-import com.android.internal.R;
-
-import java.text.DateFormatSymbols;
-import java.util.Calendar;
-
 /**
  * A simple dialog containing an {@link android.widget.DatePicker}.
  *
@@ -48,13 +43,6 @@
 
     private final DatePicker mDatePicker;
     private final OnDateSetListener mCallBack;
-    private final Calendar mCalendar;
-    private final java.text.DateFormat mTitleDateFormat;
-    private final String[] mWeekDays;
-
-    private int mInitialYear;
-    private int mInitialMonth;
-    private int mInitialDay;
 
     /**
      * The callback used to indicate the user is done filling in the date.
@@ -106,40 +94,18 @@
         super(context, theme);
 
         mCallBack = callBack;
-        mInitialYear = year;
-        mInitialMonth = monthOfYear;
-        mInitialDay = dayOfMonth;
-        DateFormatSymbols symbols = new DateFormatSymbols();
-        mWeekDays = symbols.getShortWeekdays();
-
-        mTitleDateFormat = java.text.DateFormat.
-                                getDateInstance(java.text.DateFormat.FULL);
-        mCalendar = Calendar.getInstance();
-        updateTitle(mInitialYear, mInitialMonth, mInitialDay);
 
         setButton(BUTTON_POSITIVE, context.getText(R.string.date_time_set), this);
         setButton(BUTTON_NEGATIVE, context.getText(R.string.cancel), (OnClickListener) null);
-        setIcon(R.drawable.ic_dialog_time);
+        setIcon(0);
+        setTitle(R.string.date_picker_dialog_title);
 
         LayoutInflater inflater =
                 (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
         View view = inflater.inflate(R.layout.date_picker_dialog, null);
         setView(view);
         mDatePicker = (DatePicker) view.findViewById(R.id.datePicker);
-        mDatePicker.init(mInitialYear, mInitialMonth, mInitialDay, this);
-    }
-
-    @Override
-    public void show() {
-        super.show();
-
-        /* Sometimes the full month is displayed causing the title
-         * to be very long, in those cases ensure it doesn't wrap to
-         * 2 lines (as that looks jumpy) and ensure we ellipsize the end.
-         */
-        TextView title = (TextView) findViewById(R.id.alertTitle);
-        title.setSingleLine();
-        title.setEllipsize(TruncateAt.END);
+        mDatePicker.init(year, monthOfYear, dayOfMonth, this);
     }
 
     public void onClick(DialogInterface dialog, int which) {
@@ -152,23 +118,13 @@
 
     public void onDateChanged(DatePicker view, int year,
             int month, int day) {
-        updateTitle(year, month, day);
+        mDatePicker.init(year, month, day, null);
     }
 
     public void updateDate(int year, int monthOfYear, int dayOfMonth) {
-        mInitialYear = year;
-        mInitialMonth = monthOfYear;
-        mInitialDay = dayOfMonth;
         mDatePicker.updateDate(year, monthOfYear, dayOfMonth);
     }
 
-    private void updateTitle(int year, int month, int day) {
-        mCalendar.set(Calendar.YEAR, year);
-        mCalendar.set(Calendar.MONTH, month);
-        mCalendar.set(Calendar.DAY_OF_MONTH, day);
-        setTitle(mTitleDateFormat.format(mCalendar.getTime()));
-    }
-
     @Override
     public Bundle onSaveInstanceState() {
         Bundle state = super.onSaveInstanceState();
@@ -185,6 +141,5 @@
         int month = savedInstanceState.getInt(MONTH);
         int day = savedInstanceState.getInt(DAY);
         mDatePicker.init(year, month, day, this);
-        updateTitle(year, month, day);
     }
 }
diff --git a/core/java/android/app/SharedPreferencesImpl.java b/core/java/android/app/SharedPreferencesImpl.java
index a807d3b..8aee65c 100644
--- a/core/java/android/app/SharedPreferencesImpl.java
+++ b/core/java/android/app/SharedPreferencesImpl.java
@@ -25,9 +25,12 @@
 import com.google.android.collect.Maps;
 import com.android.internal.util.XmlUtils;
 
+import dalvik.system.BlockGuard;
+
 import org.xmlpull.v1.XmlPullParserException;
 
 import java.io.File;
+import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
@@ -61,32 +64,88 @@
 
     private final Object mWritingToDiskLock = new Object();
     private static final Object mContent = new Object();
-    private final WeakHashMap<OnSharedPreferenceChangeListener, Object> mListeners;
+    private final WeakHashMap<OnSharedPreferenceChangeListener, Object> mListeners =
+            new WeakHashMap<OnSharedPreferenceChangeListener, Object>();
 
-    SharedPreferencesImpl(
-        File file, int mode, Map initialContents) {
+    SharedPreferencesImpl(File file, int mode) {
         mFile = file;
-        mBackupFile = ContextImpl.makeBackupFile(file);
+        mBackupFile = makeBackupFile(file);
         mMode = mode;
-        mLoaded = initialContents != null;
-        mMap = initialContents != null ? initialContents : new HashMap<String, Object>();
-        FileStatus stat = new FileStatus();
-        if (FileUtils.getFileStatus(file.getPath(), stat)) {
-            mStatTimestamp = stat.mtime;
-        }
-        mListeners = new WeakHashMap<OnSharedPreferenceChangeListener, Object>();
+        mLoaded = false;
+        mMap = null;
+        startLoadFromDisk();
     }
 
-    // Has this SharedPreferences ever had values assigned to it?
-    boolean isLoaded() {
+    private void startLoadFromDisk() {
         synchronized (this) {
-            return mLoaded;
+            mLoaded = false;
+        }
+        new Thread("SharedPreferencesImpl-load") {
+            public void run() {
+                synchronized (SharedPreferencesImpl.this) {
+                    loadFromDiskLocked();
+                }
+            }
+        }.start();
+    }
+
+    private void loadFromDiskLocked() {
+        if (mLoaded) {
+            return;
+        }
+        if (mBackupFile.exists()) {
+            mFile.delete();
+            mBackupFile.renameTo(mFile);
+        }
+
+        // Debugging
+        if (mFile.exists() && !mFile.canRead()) {
+            Log.w(TAG, "Attempt to read preferences file " + mFile + " without permission");
+        }
+
+        Map map = null;
+        FileStatus stat = new FileStatus();
+        if (FileUtils.getFileStatus(mFile.getPath(), stat) && mFile.canRead()) {
+            try {
+                FileInputStream str = new FileInputStream(mFile);
+                map = XmlUtils.readMapXml(str);
+                str.close();
+            } catch (XmlPullParserException e) {
+                Log.w(TAG, "getSharedPreferences", e);
+            } catch (FileNotFoundException e) {
+                Log.w(TAG, "getSharedPreferences", e);
+            } catch (IOException e) {
+                Log.w(TAG, "getSharedPreferences", e);
+            }
+        }
+        mLoaded = true;
+        if (map != null) {
+            mMap = map;
+            mStatTimestamp = stat.mtime;
+            mStatSize = stat.size;
+        } else {
+            mMap = new HashMap<String, Object>();
+        }
+        notifyAll();
+    }
+
+    private static File makeBackupFile(File prefsFile) {
+        return new File(prefsFile.getPath() + ".bak");
+    }
+
+    void startReloadIfChangedUnexpectedly() {
+        synchronized (this) {
+            // TODO: wait for any pending writes to disk?
+            if (!hasFileChangedUnexpectedly()) {
+                return;
+            }
+            startLoadFromDisk();
         }
     }
 
     // Has the file changed out from under us?  i.e. writes that
     // we didn't instigate.
-    public boolean hasFileChangedUnexpectedly() {
+    private boolean hasFileChangedUnexpectedly() {
         synchronized (this) {
             if (mDiskWritesInFlight > 0) {
                 // If we know we caused it, it's not unexpected.
@@ -103,19 +162,6 @@
         }
     }
 
-    /*package*/ void replace(Map newContents, FileStatus stat) {
-        synchronized (this) {
-            mLoaded = true;
-            if (newContents != null) {
-                mMap = newContents;
-            }
-            if (stat != null) {
-                mStatTimestamp = stat.mtime;
-                mStatSize = stat.size;
-            }
-        }
-    }
-
     public void registerOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) {
         synchronized(this) {
             mListeners.put(listener, mContent);
@@ -128,8 +174,24 @@
         }
     }
 
+    private void awaitLoadedLocked() {
+        if (!mLoaded) {
+            // Raise an explicit StrictMode onReadFromDisk for this
+            // thread, since the real read will be in a different
+            // thread and otherwise ignored by StrictMode.
+            BlockGuard.getThreadPolicy().onReadFromDisk();
+        }
+        while (!mLoaded) {
+            try {
+                wait();
+            } catch (InterruptedException unused) {
+            }
+        }
+    }
+
     public Map<String, ?> getAll() {
-        synchronized(this) {
+        synchronized (this) {
+            awaitLoadedLocked();
             //noinspection unchecked
             return new HashMap<String, Object>(mMap);
         }
@@ -137,6 +199,7 @@
 
     public String getString(String key, String defValue) {
         synchronized (this) {
+            awaitLoadedLocked();
             String v = (String)mMap.get(key);
             return v != null ? v : defValue;
         }
@@ -144,6 +207,7 @@
 
     public Set<String> getStringSet(String key, Set<String> defValues) {
         synchronized (this) {
+            awaitLoadedLocked();
             Set<String> v = (Set<String>) mMap.get(key);
             return v != null ? v : defValues;
         }
@@ -151,24 +215,28 @@
 
     public int getInt(String key, int defValue) {
         synchronized (this) {
+            awaitLoadedLocked();
             Integer v = (Integer)mMap.get(key);
             return v != null ? v : defValue;
         }
     }
     public long getLong(String key, long defValue) {
         synchronized (this) {
+            awaitLoadedLocked();
             Long v = (Long)mMap.get(key);
             return v != null ? v : defValue;
         }
     }
     public float getFloat(String key, float defValue) {
         synchronized (this) {
+            awaitLoadedLocked();
             Float v = (Float)mMap.get(key);
             return v != null ? v : defValue;
         }
     }
     public boolean getBoolean(String key, boolean defValue) {
         synchronized (this) {
+            awaitLoadedLocked();
             Boolean v = (Boolean)mMap.get(key);
             return v != null ? v : defValue;
         }
@@ -176,11 +244,23 @@
 
     public boolean contains(String key) {
         synchronized (this) {
+            awaitLoadedLocked();
             return mMap.containsKey(key);
         }
     }
 
     public Editor edit() {
+        // TODO: remove the need to call awaitLoadedLocked() when
+        // requesting an editor.  will require some work on the
+        // Editor, but then we should be able to do:
+        //
+        //      context.getSharedPreferences(..).edit().putString(..).apply()
+        //
+        // ... all without blocking.
+        synchronized (this) {
+            awaitLoadedLocked();
+        }
+
         return new EditorImpl();
     }
 
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 27be51a..b27f4cf 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -803,7 +803,7 @@
      *
      * @param intent The Intent to broadcast; all receivers matching this
      *               Intent will receive the broadcast.
-     * @param receiverPermission (optional) String naming a permissions that
+     * @param receiverPermission (optional) String naming a permission that
      *               a receiver must hold in order to receive your broadcast.
      *               If null, no permission is required.
      *
diff --git a/core/java/android/net/DummyDataStateTracker.java b/core/java/android/net/DummyDataStateTracker.java
index a759865..daa1c09 100644
--- a/core/java/android/net/DummyDataStateTracker.java
+++ b/core/java/android/net/DummyDataStateTracker.java
@@ -189,6 +189,9 @@
         return -1;
     }
 
+    public void setDataEnable(boolean enabled) {
+    }
+
     @Override
     public String toString() {
         StringBuffer sb = new StringBuffer("Dummy data state: none, dummy!");
diff --git a/core/java/android/net/MobileDataStateTracker.java b/core/java/android/net/MobileDataStateTracker.java
index 4df8db5..b3a354f 100644
--- a/core/java/android/net/MobileDataStateTracker.java
+++ b/core/java/android/net/MobileDataStateTracker.java
@@ -20,14 +20,21 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.os.Messenger;
 import android.os.RemoteException;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Message;
 import android.os.ServiceManager;
+
+import com.android.internal.telephony.DataConnectionTracker;
 import com.android.internal.telephony.ITelephony;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.TelephonyIntents;
+import com.android.internal.util.AsyncChannel;
+
 import android.net.NetworkInfo.DetailedState;
 import android.net.NetworkInfo;
 import android.net.LinkProperties;
@@ -67,6 +74,10 @@
     // the other is also disconnected before we reset sockets
     private boolean mIsDefaultOrHipri = false;
 
+    private Handler mHandler;
+    private AsyncChannel mDataConnectionTrackerAc;
+    private Messenger mMessenger;
+
     /**
      * Create a new MobileDataStateTracker
      * @param netType the ConnectivityManager network type
@@ -107,14 +118,54 @@
         mTarget = target;
         mContext = context;
 
+        HandlerThread handlerThread = new HandlerThread("ConnectivityServiceThread");
+        handlerThread.start();
+        mHandler = new MdstHandler(handlerThread.getLooper(), this);
+
         IntentFilter filter = new IntentFilter();
         filter.addAction(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED);
         filter.addAction(TelephonyIntents.ACTION_DATA_CONNECTION_FAILED);
+        filter.addAction(DataConnectionTracker.ACTION_DATA_CONNECTION_TRACKER_MESSENGER);
 
         mContext.registerReceiver(new MobileDataStateReceiver(), filter);
         mMobileDataState = Phone.DataState.DISCONNECTED;
     }
 
+    static class MdstHandler extends Handler {
+        private MobileDataStateTracker mMdst;
+
+        MdstHandler(Looper looper, MobileDataStateTracker mdst) {
+            super(looper);
+            mMdst = mdst;
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
+                    if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
+                        if (DBG) {
+                            mMdst.log("MdstHandler connected");
+                        }
+                        mMdst.mDataConnectionTrackerAc = (AsyncChannel) msg.obj;
+                    } else {
+                        if (DBG) {
+                            mMdst.log("MdstHandler %s NOT connected error=" + msg.arg1);
+                        }
+                    }
+                    break;
+                case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
+                    mMdst.log("Disconnected from DataStateTracker");
+                    mMdst.mDataConnectionTrackerAc = null;
+                    break;
+                default: {
+                    mMdst.log("Ignorning unknown message=" + msg);
+                    break;
+                }
+            }
+        }
+    }
+
     /**
      * Return the IP addresses of the DNS servers available for the mobile data
      * network interface.
@@ -179,7 +230,7 @@
                         false));
 
                 if (DBG) {
-                    log(mApnType + " Received state=" + state + ", old=" + mMobileDataState +
+                    log("Received state=" + state + ", old=" + mMobileDataState +
                         ", reason=" + (reason == null ? "(unspecified)" : reason));
                 }
                 if (mMobileDataState != state) {
@@ -265,10 +316,16 @@
                 String reason = intent.getStringExtra(Phone.FAILURE_REASON_KEY);
                 String apnName = intent.getStringExtra(Phone.DATA_APN_KEY);
                 if (DBG) {
-                    log(mApnType + "Received " + intent.getAction() +
+                    log("Received " + intent.getAction() +
                                 " broadcast" + reason == null ? "" : "(" + reason + ")");
                 }
                 setDetailedState(DetailedState.FAILED, reason, apnName);
+            } else if (intent.getAction().
+                    equals(DataConnectionTracker.ACTION_DATA_CONNECTION_TRACKER_MESSENGER)) {
+                if (DBG) log(mApnType + " got ACTION_DATA_CONNECTION_TRACKER_MESSENGER");
+                mMessenger = intent.getParcelableExtra(DataConnectionTracker.EXTRA_MESSENGER);
+                AsyncChannel ac = new AsyncChannel();
+                ac.connect(mContext, MobileDataStateTracker.this.mHandler, mMessenger);
             } else {
                 if (DBG) log("Broadcast received: ignore " + intent.getAction());
             }
@@ -488,6 +545,20 @@
         return -1;
     }
 
+    /**
+     * @param enabled
+     */
+    public void setDataEnable(boolean enabled) {
+        try {
+            log("setDataEnable: E enabled=" + enabled);
+            mDataConnectionTrackerAc.sendMessage(DataConnectionTracker.CMD_SET_DATA_ENABLE,
+                    enabled ? DataConnectionTracker.ENABLED : DataConnectionTracker.DISABLED);
+            log("setDataEnable: X enabled=" + enabled);
+        } catch (Exception e) {
+            log("setDataEnable: X mAc was null" + e);
+        }
+    }
+
     @Override
     public String toString() {
         StringBuffer sb = new StringBuffer("Mobile data state: ");
@@ -543,7 +614,7 @@
             case ConnectivityManager.TYPE_MOBILE_HIPRI:
                 return Phone.APN_TYPE_HIPRI;
             default:
-                loge("Error mapping networkType " + netType + " to apnType.");
+                sloge("Error mapping networkType " + netType + " to apnType.");
                 return null;
         }
     }
@@ -562,11 +633,15 @@
         return new LinkCapabilities(mLinkCapabilities);
     }
 
-    static private void log(String s) {
-        Slog.d(TAG, s);
+    private void log(String s) {
+        Slog.d(TAG, mApnType + ": " + s);
     }
 
-    static private void loge(String s) {
+    private void loge(String s) {
+        Slog.e(TAG, mApnType + ": " + s);
+    }
+
+    static private void sloge(String s) {
         Slog.e(TAG, s);
     }
 }
diff --git a/core/java/android/net/NetworkStateTracker.java b/core/java/android/net/NetworkStateTracker.java
index 8afdcee..e378506 100644
--- a/core/java/android/net/NetworkStateTracker.java
+++ b/core/java/android/net/NetworkStateTracker.java
@@ -169,6 +169,11 @@
     public int stopUsingNetworkFeature(String feature, int callingPid, int callingUid);
 
     /**
+     * @param enabled
+     */
+    public void setDataEnable(boolean enabled);
+
+    /**
      * -------------------------------------------------------------
      * Storage API used by ConnectivityService for saving
      * Network specific information.
@@ -204,5 +209,4 @@
      * Indicate tear down requested from connectivity
      */
     public void setTeardownRequested(boolean isRequested);
-
 }
diff --git a/core/java/android/nfc/INfcTag.aidl b/core/java/android/nfc/INfcTag.aidl
index ad3c1bb..f5c79e7 100644
--- a/core/java/android/nfc/INfcTag.aidl
+++ b/core/java/android/nfc/INfcTag.aidl
@@ -37,4 +37,5 @@
     int write(int nativeHandle, in NdefMessage msg);
     int makeReadOnly(int nativeHandle);
     int getModeHint(int nativeHandle);
-}
\ No newline at end of file
+    int formatNdef(int nativeHandle, in byte[] key);
+}
diff --git a/core/java/android/nfc/Tag.java b/core/java/android/nfc/Tag.java
index ad05496..36de915 100644
--- a/core/java/android/nfc/Tag.java
+++ b/core/java/android/nfc/Tag.java
@@ -21,6 +21,7 @@
 import android.nfc.technology.MifareUltralight;
 import android.nfc.technology.NfcV;
 import android.nfc.technology.Ndef;
+import android.nfc.technology.NdefFormatable;
 import android.nfc.technology.NfcA;
 import android.nfc.technology.NfcB;
 import android.nfc.technology.NfcF;
@@ -154,13 +155,12 @@
                 case TagTechnology.NFC_V: {
                     return new NfcV(adapter, this, extras);
                 }
-                case TagTechnology.MIFARE_CLASSIC_NDEF:
-                case TagTechnology.TYPE_1:
-                case TagTechnology.TYPE_2:
-                case TagTechnology.TYPE_3:
-                case TagTechnology.TYPE_4: {
+                case TagTechnology.NDEF: {
                     return new Ndef(adapter, this, tech, extras);
                 }
+                case TagTechnology.NDEF_FORMATABLE: {
+                    return new NdefFormatable(adapter, this, tech, extras);
+                }
                 case TagTechnology.NFC_F: {
                     return new NfcF(adapter, this, extras);
                 }
diff --git a/core/java/android/nfc/technology/Ndef.java b/core/java/android/nfc/technology/Ndef.java
index 22460cf..c856646 100644
--- a/core/java/android/nfc/technology/Ndef.java
+++ b/core/java/android/nfc/technology/Ndef.java
@@ -44,12 +44,25 @@
     public static final int NDEF_MODE_WRITE_MANY = 4;
     public static final int NDEF_MODE_UNKNOWN = 5;
 
+    /** @hide */
+    public static final String EXTRA_NDEF_MSG = "ndefmsg";
+
+    /** @hide */
+    public static final String EXTRA_NDEF_MAXLENGTH = "ndefmaxlength";
+
+    private final int maxNdefSize;
+
     /**
      * Internal constructor, to be used by NfcAdapter
      * @hide
      */
     public Ndef(NfcAdapter adapter, Tag tag, int tech, Bundle extras) throws RemoteException {
         super(adapter, tag, tech);
+        if (extras != null) {
+            maxNdefSize = extras.getInt(EXTRA_NDEF_MAXLENGTH);
+        } else {
+            maxNdefSize = 0;  //TODO: throw exception
+        }
     }
 
     /**
@@ -92,7 +105,7 @@
      * Get maximum NDEF message size in bytes
      */
     public int getSize() {
-        throw new UnsupportedOperationException();
+        return maxNdefSize;
     }
 
     /**
diff --git a/core/java/android/nfc/technology/NdefFormatable.java b/core/java/android/nfc/technology/NdefFormatable.java
index 7c4f9ab..3ed37a5 100644
--- a/core/java/android/nfc/technology/NdefFormatable.java
+++ b/core/java/android/nfc/technology/NdefFormatable.java
@@ -56,7 +56,37 @@
      * Formats a tag as NDEF, if possible. You may supply a first
      * NdefMessage to be written on the tag.
      */
-    public void format(NdefMessage firstMessage) throws IOException {
-      throw new UnsupportedOperationException();
+    public void format(NdefMessage firstMessage) throws IOException, FormatException {
+        try {
+            byte[] DEFAULT_KEY = {(byte)0xFF,(byte)0xFF,(byte)0xFF,
+                                  (byte)0xFF,(byte)0xFF,(byte)0xFF};
+            int serviceHandle = mTag.getServiceHandle();
+            int errorCode = mTagService.formatNdef(serviceHandle, DEFAULT_KEY);
+            switch (errorCode) {
+                case ErrorCodes.SUCCESS:
+                    break;
+                case ErrorCodes.ERROR_IO:
+                    throw new IOException();
+                case ErrorCodes.ERROR_INVALID_PARAM:
+                    throw new FormatException();
+                default:
+                    // Should not happen
+                    throw new IOException();
+            }
+            errorCode = mTagService.write(serviceHandle, firstMessage);
+            switch (errorCode) {
+                case ErrorCodes.SUCCESS:
+                    break;
+                case ErrorCodes.ERROR_IO:
+                    throw new IOException();
+                case ErrorCodes.ERROR_INVALID_PARAM:
+                    throw new FormatException();
+                default:
+                    // Should not happen
+                    throw new IOException();
+            }
+        } catch (RemoteException e) {
+            attemptDeadServiceRecovery(e);
+        }
     }
 }
diff --git a/core/java/android/nfc/technology/TagTechnology.java b/core/java/android/nfc/technology/TagTechnology.java
index 9dfb297..4704f2b 100644
--- a/core/java/android/nfc/technology/TagTechnology.java
+++ b/core/java/android/nfc/technology/TagTechnology.java
@@ -49,22 +49,7 @@
     /**
      * This object is an instance of {@link Ndef}
      */
-    public static final int TYPE_1 = 101;
-
-    /**
-     * This object is an instance of {@link Ndef}
-     */
-    public static final int TYPE_2 = 102;
-
-    /**
-     * This object is an instance of {@link Ndef}
-     */
-    public static final int TYPE_3 = 103;
-
-    /**
-     * This object is an instance of {@link Ndef}
-     */
-    public static final int TYPE_4 = 104;
+    public static final int NDEF = 101;
 
     /**
      * This object is an instance of {@link NdefFormatable}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index ed71da2..1e80da7 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -977,6 +977,9 @@
         public static float getFloat(ContentResolver cr, String name)
                 throws SettingNotFoundException {
             String v = getString(cr, name);
+            if (v == null) {
+                throw new SettingNotFoundException(name);
+            }
             try {
                 return Float.parseFloat(v);
             } catch (NumberFormatException e) {
@@ -1577,7 +1580,7 @@
          * Default screen rotation when no other policy applies.
          * When {@link #ACCELEROMETER_ROTATION} is zero and no on-screen Activity expresses a
          * preference, this rotation value will be used. Must be one of the
-         * {@link android.view.Surface#ROTATION_0 Surface rotation constants}. 
+         * {@link android.view.Surface#ROTATION_0 Surface rotation constants}.
          *
          * @see Display#getRotation
          */
@@ -2296,6 +2299,9 @@
         public static float getFloat(ContentResolver cr, String name)
                 throws SettingNotFoundException {
             String v = getString(cr, name);
+            if (v == null) {
+                throw new SettingNotFoundException(name);
+            }
             try {
                 return Float.parseFloat(v);
             } catch (NumberFormatException e) {
diff --git a/core/java/android/text/format/Time.java b/core/java/android/text/format/Time.java
index c05a8fe..c6ffe58 100644
--- a/core/java/android/text/format/Time.java
+++ b/core/java/android/text/format/Time.java
@@ -42,6 +42,12 @@
     public static final int EPOCH_JULIAN_DAY = 2440588;
 
     /**
+     * The Julian day of the Monday in the week of the epoch, December 29, 1969
+     * on the Gregorian calendar.
+     */
+    public static final int MONDAY_BEFORE_JULIAN_EPOCH = EPOCH_JULIAN_DAY - 3;
+
+    /**
      * True if this is an allDay event. The hour, minute, second fields are
      * all zero, and the date is displayed the same in all time zones.
      */
@@ -770,4 +776,39 @@
         millis = normalize(true);
         return millis;
     }
+
+    /**
+     * Returns the week since {@link #EPOCH_JULIAN_DAY} (Jan 1, 1970) adjusted
+     * for first day of week. This takes a julian day and the week start day and
+     * calculates which week since {@link #EPOCH_JULIAN_DAY} that day occurs in,
+     * starting at 0. *Do not* use this to compute the ISO week number for the
+     * year.
+     *
+     * @param julianDay The julian day to calculate the week number for
+     * @param firstDayOfWeek Which week day is the first day of the week, see
+     *            {@link #SUNDAY}
+     * @return Weeks since the epoch
+     */
+    public static int getWeeksSinceEpochFromJulianDay(int julianDay, int firstDayOfWeek) {
+        int diff = THURSDAY - firstDayOfWeek;
+        if (diff < 0) {
+            diff += 7;
+        }
+        int refDay = EPOCH_JULIAN_DAY - diff;
+        return (julianDay - refDay) / 7;
+    }
+
+    /**
+     * Takes a number of weeks since the epoch and calculates the Julian day of
+     * the Monday for that week. This assumes that the week containing the
+     * {@link #EPOCH_JULIAN_DAY} is considered week 0. It returns the Julian day
+     * for the Monday week weeks after the Monday of the week containing the
+     * epoch.
+     *
+     * @param week Number of weeks since the epoch
+     * @return The julian day for the Monday of the given week since the epoch
+     */
+    public static int getJulianMondayFromWeeksSinceEpoch(int week) {
+        return MONDAY_BEFORE_JULIAN_EPOCH + week * 7;
+    }
 }
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index 24a9f87..0e294f71 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -50,7 +50,7 @@
     private boolean mRequested = true;
 
     /**
-     * Indicates that the current process cannot use hardware rendering.
+     * Invoke this method to disable hardware rendering in the current process.
      * 
      * @hide
      */
@@ -207,7 +207,7 @@
         EGLSurface mEglSurface;
         
         GL mGl;
-        GLES20Canvas mCanvas;
+        HardwareCanvas mCanvas;
 
         final int mGlVersion;
         final boolean mTranslucent;
@@ -279,12 +279,15 @@
                     if (error != EGL11.EGL_CONTEXT_LOST) {
                         // we'll try again if it was context lost
                         setRequested(false);
+                    } else {
+                        Log.w(LOG_TAG, "Mountain View, we've had a problem here. " 
+                                + "Switching back to software rendering.");
                     }
                     Log.w(LOG_TAG, "EGL error: " + getEGLErrorString(error));
                 }
             }
         }
-        
+
         @Override
         boolean initialize(SurfaceHolder holder) {
             if (isRequested() && !isEnabled()) {
@@ -654,6 +657,14 @@
         }
 
         @Override
+        void destroy(boolean full) {
+            super.destroy(full);
+            if (full && mGlCanvas != null) {
+                mGlCanvas = null;
+            }
+        }
+
+        @Override
         DisplayList createDisplayList() {
             return new GLES20DisplayList();
         }
diff --git a/core/java/android/view/KeyCharacterMap.java b/core/java/android/view/KeyCharacterMap.java
index 97bd8dd..5c4abd5 100644
--- a/core/java/android/view/KeyCharacterMap.java
+++ b/core/java/android/view/KeyCharacterMap.java
@@ -144,6 +144,8 @@
     private static native void nativeDispose(int ptr);
 
     private static native char nativeGetCharacter(int ptr, int keyCode, int metaState);
+    private static native boolean nativeGetFallbackAction(int ptr, int keyCode, int metaState,
+            FallbackAction outFallbackAction);
     private static native char nativeGetNumber(int ptr, int keyCode);
     private static native char nativeGetMatch(int ptr, int keyCode, char[] chars, int metaState);
     private static native char nativeGetDisplayLabel(int ptr, int keyCode);
@@ -206,14 +208,9 @@
      * @return The associated character or combining accent, or 0 if none.
      */
     public int get(int keyCode, int metaState) {
-        if ((metaState & MetaKeyKeyListener.META_CAP_LOCKED) != 0) {
-            metaState |= KeyEvent.META_CAPS_LOCK_ON;
-        }
-        if ((metaState & MetaKeyKeyListener.META_ALT_LOCKED) != 0) {
-            metaState |= KeyEvent.META_ALT_ON;
-        }
-
+        metaState = applyLockedModifiers(metaState);
         char ch = nativeGetCharacter(mPtr, keyCode, metaState);
+
         int map = COMBINING.get(ch);
         if (map != 0) {
             return map;
@@ -223,6 +220,34 @@
     }
 
     /**
+     * Gets the fallback action to perform if the application does not
+     * handle the specified key.
+     * <p>
+     * When an application does not handle a particular key, the system may
+     * translate the key to an alternate fallback key (specified in the
+     * fallback action) and dispatch it to the application.
+     * The event containing the fallback key is flagged
+     * with {@link KeyEvent#FLAG_FALLBACK}.
+     * </p>
+     *
+     * @param keyCode The key code.
+     * @param metaState The meta key modifier state.
+     * @param outFallbackAction The fallback action object to populate.
+     * @return True if a fallback action was found, false otherwise.
+     *
+     * @hide
+     */
+    public boolean getFallbackAction(int keyCode, int metaState,
+            FallbackAction outFallbackAction) {
+        if (outFallbackAction == null) {
+            throw new IllegalArgumentException("fallbackAction must not be null");
+        }
+
+        metaState = applyLockedModifiers(metaState);
+        return nativeGetFallbackAction(mPtr, keyCode, metaState, outFallbackAction);
+    }
+
+    /**
      * Gets the number or symbol associated with the key.
      * <p>
      * The character value is returned, not the numeric value.
@@ -277,6 +302,8 @@
         if (chars == null) {
             throw new IllegalArgumentException("chars must not be null.");
         }
+
+        metaState = applyLockedModifiers(metaState);
         return nativeGetMatch(mPtr, keyCode, chars, metaState);
     }
 
@@ -509,6 +536,16 @@
         return ret;
     }
 
+    private static int applyLockedModifiers(int metaState) {
+        if ((metaState & MetaKeyKeyListener.META_CAP_LOCKED) != 0) {
+            metaState |= KeyEvent.META_CAPS_LOCK_ON;
+        }
+        if ((metaState & MetaKeyKeyListener.META_ALT_LOCKED) != 0) {
+            metaState |= KeyEvent.META_ALT_ON;
+        }
+        return metaState;
+    }
+
     /**
      * Maps Unicode combining diacritical to display-form dead key
      * (display character shifted left 16 bits).
@@ -670,4 +707,14 @@
             super(msg);
         }
     }
+
+    /**
+     * Specifies a substitute key code and meta state as a fallback action
+     * for an unhandled key.
+     * @hide
+     */
+    public static final class FallbackAction {
+        public int keyCode;
+        public int metaState;
+    }
 }
diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
index 03407a3..43b77e6 100755
--- a/core/java/android/view/KeyEvent.java
+++ b/core/java/android/view/KeyEvent.java
@@ -529,15 +529,17 @@
     /** Key code constant: Blue "programmable" key.
      * On TV remotes, acts as a contextual/programmable key. */
     public static final int KEYCODE_PROG_BLUE       = 186;
+    /** Key code constant: App switch key.
+     * Should bring up the application switcher dialog. */
+    public static final int KEYCODE_APP_SWITCH      = 187;
 
-    private static final int LAST_KEYCODE           = KEYCODE_PROG_BLUE;
+    private static final int LAST_KEYCODE           = KEYCODE_APP_SWITCH;
 
     // NOTE: If you add a new keycode here you must also add it to:
     //  isSystem()
     //  native/include/android/keycodes.h
     //  frameworks/base/include/ui/KeycodeLabels.h
     //  external/webkit/WebKit/android/plugins/ANPKeyCodes.h
-    //  tools/puppet_master/PuppetMaster/nav_keys.py
     //  frameworks/base/core/res/res/values/attrs.xml
     //  emulator?
     //
@@ -737,6 +739,7 @@
         "KEYCODE_PROG_GREEN",
         "KEYCODE_PROG_YELLOW",
         "KEYCODE_PROG_BLUE",
+        "KEYCODE_APP_SWITCH",
     };
 
     // Symbolic names of all metakeys in bit order from least significant to most significant.
@@ -1056,7 +1059,17 @@
      * the tracking to be canceled.
      */
     public static final int FLAG_TRACKING = 0x200;
-    
+
+    /**
+     * Set when a key event has been synthesized to implement default behavior
+     * for an event that the application did not handle.
+     * Fallback key events are generated by unhandled trackball motions
+     * (to emulate a directional keypad) and by certain unhandled key presses
+     * that are declared in the key map (such as special function numeric keypad
+     * keys when numlock is off).
+     */
+    public static final int FLAG_FALLBACK = 0x400;
+
     /**
      * Private control to determine when an app is tracking a key sequence.
      * @hide
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 1f5bb5d..ad96686 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -556,7 +556,7 @@
  * improve the security of views that provide access to sensitive functionality.
  * </p><p>
  * To enable touch filtering, call {@link #setFilterTouchesWhenObscured} or set the
- * andoird:filterTouchesWhenObscured attribute to true.  When enabled, the framework
+ * android:filterTouchesWhenObscured layout attribute to true.  When enabled, the framework
  * will discard touches that are received whenever the view's window is obscured by
  * another visible window.  As a result, the view will not receive touches whenever a
  * toast, dialog or other window appears above the view's window.
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 7b81b8f..a9aa8f9 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -4213,7 +4213,7 @@
         boolean noneOfTheChildrenAreTransparent = true;
         for (int i = 0; i < count; i++) {
             final View child = children[i];
-            if ((child.mViewFlags & VISIBILITY_MASK) != GONE || child.getAnimation() != null) {
+            if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE || child.getAnimation() != null) {
                 if (!child.gatherTransparentRegion(region)) {
                     noneOfTheChildrenAreTransparent = false;
                 }
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index a34fe87..9bda637 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -1101,7 +1101,9 @@
                 }
             }
 
-            if (hwInitialized || (windowShouldResize && mAttachInfo.mHardwareRenderer != null)) {
+            if (hwInitialized || (windowShouldResize &&
+                    mAttachInfo.mHardwareRenderer != null &&
+                    mAttachInfo.mHardwareRenderer.isEnabled())) {
                 mAttachInfo.mHardwareRenderer.setup(mWidth, mHeight);
             }
 
@@ -2308,21 +2310,23 @@
         }
 
         final int action = event.getAction();
-        final int metastate = event.getMetaState();
+        final int metaState = event.getMetaState();
         switch (action) {
             case MotionEvent.ACTION_DOWN:
                 x.reset(2);
                 y.reset(2);
                 deliverKeyEvent(new KeyEvent(curTime, curTime,
-                        KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_CENTER,
-                        0, metastate), false);
+                        KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_CENTER, 0, metaState,
+                        KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FALLBACK,
+                        InputDevice.SOURCE_KEYBOARD), false);
                 break;
             case MotionEvent.ACTION_UP:
                 x.reset(2);
                 y.reset(2);
                 deliverKeyEvent(new KeyEvent(curTime, curTime,
-                        KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DPAD_CENTER,
-                        0, metastate), false);
+                        KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DPAD_CENTER, 0, metaState,
+                        KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FALLBACK,
+                        InputDevice.SOURCE_KEYBOARD), false);
                 break;
         }
 
@@ -2372,9 +2376,11 @@
                 if (DEBUG_TRACKBALL) Log.v("foo", "Delivering fake DPAD: "
                         + keycode);
                 movement--;
+                int repeatCount = accelMovement - movement;
                 deliverKeyEvent(new KeyEvent(curTime, curTime,
-                        KeyEvent.ACTION_MULTIPLE, keycode,
-                        accelMovement-movement, metastate), false);
+                        KeyEvent.ACTION_MULTIPLE, keycode, repeatCount, metaState,
+                        KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FALLBACK,
+                        InputDevice.SOURCE_KEYBOARD), false);
             }
             while (movement > 0) {
                 if (DEBUG_TRACKBALL) Log.v("foo", "Delivering fake DPAD: "
@@ -2382,10 +2388,14 @@
                 movement--;
                 curTime = SystemClock.uptimeMillis();
                 deliverKeyEvent(new KeyEvent(curTime, curTime,
-                        KeyEvent.ACTION_DOWN, keycode, 0, event.getMetaState()), false);
+                        KeyEvent.ACTION_DOWN, keycode, 0, metaState,
+                        KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FALLBACK,
+                        InputDevice.SOURCE_KEYBOARD), false);
                 deliverKeyEvent(new KeyEvent(curTime, curTime,
-                        KeyEvent.ACTION_UP, keycode, 0, metastate), false);
-            }
+                        KeyEvent.ACTION_UP, keycode, 0, metaState,
+                        KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FALLBACK,
+                        InputDevice.SOURCE_KEYBOARD), false);
+                }
             mLastTrackballTime = curTime;
         }
 
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index af36d80..3479bf5 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -587,9 +587,10 @@
      *            event will normally go.
      * @param event The key event.
      * @param policyFlags The policy flags associated with the key.
-     * @return Returns true if the policy consumed the event.
+     * @return Returns an alternate key event to redispatch as a fallback, or null to give up.
+     * The caller is responsible for recycling the key event.
      */
-    public boolean dispatchUnhandledKey(WindowState win, KeyEvent event, int policyFlags);
+    public KeyEvent dispatchUnhandledKey(WindowState win, KeyEvent event, int policyFlags);
 
     /**
      * Called when layout of the windows is about to start.
diff --git a/core/java/android/webkit/BrowserFrame.java b/core/java/android/webkit/BrowserFrame.java
index 8f92458..2c38c93 100644
--- a/core/java/android/webkit/BrowserFrame.java
+++ b/core/java/android/webkit/BrowserFrame.java
@@ -599,13 +599,20 @@
 
     public void addJavascriptInterface(Object obj, String interfaceName) {
         assert obj != null;
+        removeJavascriptInterface(interfaceName);
         if (mJSInterfaceMap == null) {
             mJSInterfaceMap = new HashMap<String, Object>();
         }
+        mJSInterfaceMap.put(interfaceName, obj);
+    }
+
+    public void removeJavascriptInterface(String interfaceName) {
+        if (mJSInterfaceMap == null) {
+            return;
+        }
         if (mJSInterfaceMap.containsKey(interfaceName)) {
             mJSInterfaceMap.remove(interfaceName);
         }
-        mJSInterfaceMap.put(interfaceName, obj);
     }
 
     /**
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 3a6ff4d..c6cf918 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -322,8 +322,19 @@
         }
     }
 
+    private class InnerScrollChangedListener implements ViewTreeObserver.OnScrollChangedListener {
+        public void onScrollChanged() {
+            if (isShown()) {
+                setGLRectViewport();
+            }
+        }
+    }
+
     // The listener to capture global layout change event.
-    private InnerGlobalLayoutListener mListener = null;
+    private InnerGlobalLayoutListener mGlobalLayoutListener = null;
+
+    // The listener to capture scroll event.
+    private InnerScrollChangedListener mScrollChangedListener = null;
 
     // if AUTO_REDRAW_HACK is true, then the CALL key will toggle redrawing
     // the screen all-the-time. Good for profiling our drawing code
@@ -434,9 +445,9 @@
     private float mLastVelX;
     private float mLastVelY;
 
-    // A pointer to the native scrollable layer when dragging layers.  Only
-    // valid when mTouchMode is TOUCH_DRAG_LAYER_MODE.
+    // The id of the native layer being scrolled.
     private int mScrollingLayer;
+    private Rect mScrollingLayerRect = new Rect();
 
     // only trigger accelerated fling if the new velocity is at least
     // MINIMUM_VELOCITY_RATIO_FOR_ACCELERATION times of the previous velocity
@@ -937,28 +948,28 @@
      * @param context A Context object used to access application assets.
      * @param attrs An AttributeSet passed to our parent.
      * @param defStyle The default style resource ID.
-     * @param javascriptInterfaces is a Map of interface names, as keys, and
+     * @param javaScriptInterfaces is a Map of interface names, as keys, and
      * object implementing those interfaces, as values.
      * @hide pending API council approval.
      */
     protected WebView(Context context, AttributeSet attrs, int defStyle,
-            Map<String, Object> javascriptInterfaces, boolean privateBrowsing) {
+            Map<String, Object> javaScriptInterfaces, boolean privateBrowsing) {
         super(context, attrs, defStyle);
 
         // Used by the chrome stack to find application paths
         JniUtil.setContext(context);
 
         if (AccessibilityManager.getInstance(context).isEnabled()) {
-            if (javascriptInterfaces == null) {
-                javascriptInterfaces = new HashMap<String, Object>();
+            if (javaScriptInterfaces == null) {
+                javaScriptInterfaces = new HashMap<String, Object>();
             }
-            exposeAccessibilityJavaScriptApi(javascriptInterfaces);
+            exposeAccessibilityJavaScriptApi(javaScriptInterfaces);
         }
 
         mCallbackProxy = new CallbackProxy(context, this);
         mViewManager = new ViewManager(this);
         L10nUtils.loadStrings(context);
-        mWebViewCore = new WebViewCore(context, this, mCallbackProxy, javascriptInterfaces);
+        mWebViewCore = new WebViewCore(context, this, mCallbackProxy, javaScriptInterfaces);
         mDatabase = WebViewDatabase.getInstance(context);
         mScroller = new OverScroller(context, null, 0, 0, false); //TODO Use OverScroller's flywheel
         mZoomManager = new ZoomManager(this, mCallbackProxy);
@@ -1105,10 +1116,10 @@
      * interfaces map provided by the WebView client. In case of conflicting
      * alias with the one of the accessibility API the user specified one wins.
      *
-     * @param javascriptInterfaces A map with interfaces to be exposed to JavaScript.
+     * @param javaScriptInterfaces A map with interfaces to be exposed to JavaScript.
      */
-    private void exposeAccessibilityJavaScriptApi(Map<String, Object> javascriptInterfaces) {
-        if (javascriptInterfaces.containsKey(ALIAS_ACCESSIBILITY_JS_INTERFACE)) {
+    private void exposeAccessibilityJavaScriptApi(Map<String, Object> javaScriptInterfaces) {
+        if (javaScriptInterfaces.containsKey(ALIAS_ACCESSIBILITY_JS_INTERFACE)) {
             Log.w(LOGTAG, "JavaScript interface mapped to \"" + ALIAS_ACCESSIBILITY_JS_INTERFACE
                     + "\" overrides the accessibility API JavaScript interface. No accessibility"
                     + "API will be exposed to JavaScript!");
@@ -1116,7 +1127,7 @@
         }
 
         // expose the TTS for now ...
-        javascriptInterfaces.put(ALIAS_ACCESSIBILITY_JS_INTERFACE,
+        javaScriptInterfaces.put(ALIAS_ACCESSIBILITY_JS_INTERFACE,
                 new TextToSpeech(getContext(), null));
     }
 
@@ -1394,7 +1405,7 @@
             mPrivateHandler.removeCallbacksAndMessages(null);
             mCallbackProxy.removeCallbacksAndMessages(null);
             // Wake up the WebCore thread just in case it is waiting for a
-            // javascript dialog.
+            // JavaScript dialog.
             synchronized (mCallbackProxy) {
                 mCallbackProxy.notify();
             }
@@ -1433,7 +1444,7 @@
 
     /**
      * Inform WebView of the network state. This is used to set
-     * the javascript property window.navigator.isOnline and
+     * the JavaScript property window.navigator.isOnline and
      * generates the online/offline event as specified in HTML5, sec. 5.7.7
      * @param networkUp boolean indicating if network is available
      */
@@ -2100,9 +2111,9 @@
 
     /**
      * Return a HitTestResult based on the current cursor node. If a HTML::a tag
-     * is found and the anchor has a non-javascript url, the HitTestResult type
+     * is found and the anchor has a non-JavaScript url, the HitTestResult type
      * is set to SRC_ANCHOR_TYPE and the url is set in the "extra" field. If the
-     * anchor does not have a url or if it is a javascript url, the type will
+     * anchor does not have a url or if it is a JavaScript url, the type will
      * be UNKNOWN_TYPE and the url has to be retrieved through
      * {@link #requestFocusNodeHref} asynchronously. If a HTML::img tag is
      * found, the HitTestResult type is set to IMAGE_TYPE and the url is set in
@@ -2646,6 +2657,15 @@
     @Override
     protected void onOverScrolled(int scrollX, int scrollY, boolean clampedX,
             boolean clampedY) {
+        // Special-case layer scrolling so that we do not trigger normal scroll
+        // updating.
+        if (mTouchMode == TOUCH_DRAG_LAYER_MODE) {
+            nativeScrollLayer(mScrollingLayer, scrollX, scrollY);
+            mScrollingLayerRect.left = scrollX;
+            mScrollingLayerRect.top = scrollY;
+            invalidate();
+            return;
+        }
         mInOverScrollMode = false;
         int maxX = computeMaxScrollX();
         int maxY = computeMaxScrollY();
@@ -2748,7 +2768,7 @@
     }
 
     /**
-     * Pause all layout, parsing, and javascript timers for all webviews. This
+     * Pause all layout, parsing, and JavaScript timers for all webviews. This
      * is a global requests, not restricted to just this webview. This can be
      * useful if the application has been paused.
      */
@@ -2757,7 +2777,7 @@
     }
 
     /**
-     * Resume all layout, parsing, and javascript timers for all webviews.
+     * Resume all layout, parsing, and JavaScript timers for all webviews.
      * This will resume dispatching all timers.
      */
     public void resumeTimers() {
@@ -2765,13 +2785,12 @@
     }
 
     /**
-     * Call this to pause any extra processing associated with this view and
-     * its associated DOM/plugins/javascript/etc. For example, if the view is
-     * taken offscreen, this could be called to reduce unnecessary CPU and/or
-     * network traffic. When the view is again "active", call onResume().
+     * Call this to pause any extra processing associated with this WebView and
+     * its associated DOM, plugins, JavaScript etc. For example, if the WebView
+     * is taken offscreen, this could be called to reduce unnecessary CPU or
+     * network traffic. When the WebView is again "active", call onResume().
      *
-     * Note that this differs from pauseTimers(), which affects all views/DOMs
-     * @hide
+     * Note that this differs from pauseTimers(), which affects all WebViews.
      */
     public void onPause() {
         if (!mIsPaused) {
@@ -2781,8 +2800,7 @@
     }
 
     /**
-     * Call this to balanace a previous call to onPause()
-     * @hide
+     * Call this to resume a WebView after a previous call to onPause().
      */
     public void onResume() {
         if (mIsPaused) {
@@ -3048,18 +3066,37 @@
             invalidate();  // So we draw again
 
             if (!mScroller.isFinished()) {
-                final int rangeX = computeMaxScrollX();
-                final int rangeY = computeMaxScrollY();
+                int rangeX = computeMaxScrollX();
+                int rangeY = computeMaxScrollY();
+                int overflingDistance = mOverflingDistance;
+
+                // Use the layer's scroll data if needed.
+                if (mTouchMode == TOUCH_DRAG_LAYER_MODE) {
+                    oldX = mScrollingLayerRect.left;
+                    oldY = mScrollingLayerRect.top;
+                    rangeX = mScrollingLayerRect.right;
+                    rangeY = mScrollingLayerRect.bottom;
+                    // No overscrolling for layers.
+                    overflingDistance = 0;
+                }
+
                 overScrollBy(x - oldX, y - oldY, oldX, oldY,
                         rangeX, rangeY,
-                        mOverflingDistance, mOverflingDistance, false);
+                        overflingDistance, overflingDistance, false);
 
                 if (mOverScrollGlow != null) {
                     mOverScrollGlow.absorbGlow(x, y, oldX, oldY, rangeX, rangeY);
                 }
             } else {
-                mScrollX = x;
-                mScrollY = y;
+                if (mTouchMode != TOUCH_DRAG_LAYER_MODE) {
+                    mScrollX = x;
+                    mScrollY = y;
+                } else {
+                    // Update the layer position instead of WebView.
+                    nativeScrollLayer(mScrollingLayer, x, y);
+                    mScrollingLayerRect.left = x;
+                    mScrollingLayerRect.top = y;
+                }
                 abortAnimation();
                 mPrivateHandler.removeMessages(RESUME_WEBCORE_PRIORITY);
                 WebViewCore.resumePriority();
@@ -3415,7 +3452,7 @@
 
     /**
      * Set the chrome handler. This is an implementation of WebChromeClient for
-     * use in handling Javascript dialogs, favicons, titles, and the progress.
+     * use in handling JavaScript dialogs, favicons, titles, and the progress.
      * This will replace the current handler.
      * @param client An implementation of WebChromeClient.
      */
@@ -3478,8 +3515,8 @@
     }
 
     /**
-     * Use this function to bind an object to Javascript so that the
-     * methods can be accessed from Javascript.
+     * Use this function to bind an object to JavaScript so that the
+     * methods can be accessed from JavaScript.
      * <p><strong>IMPORTANT:</strong>
      * <ul>
      * <li> Using addJavascriptInterface() allows JavaScript to control your
@@ -3493,9 +3530,10 @@
      * <li> The Java object that is bound runs in another thread and not in
      * the thread that it was constructed in.</li>
      * </ul></p>
-     * @param obj The class instance to bind to Javascript, null instances are
+     * @param obj The class instance to bind to JavaScript, null instances are
      *            ignored.
-     * @param interfaceName The name to used to expose the class in JavaScript.
+     * @param interfaceName The name to used to expose the instance in
+     *                      JavaScript.
      */
     public void addJavascriptInterface(Object obj, String interfaceName) {
         if (obj == null) {
@@ -3508,6 +3546,16 @@
     }
 
     /**
+     * Removes a previously added JavaScript interface with the given name.
+     * @param interfaceName The name of the interface to remove.
+     */
+    public void removeJavascriptInterface(String interfaceName) {
+        WebViewCore.JSInterfaceData arg = new WebViewCore.JSInterfaceData();
+        arg.mInterfaceName = interfaceName;
+        mWebViewCore.sendMessage(EventHub.REMOVE_JS_INTERFACE, arg);
+    }
+
+    /**
      * Return the WebSettings object used to control the settings for this
      * WebView.
      * @return A WebSettings object that can be used to control this WebView's
@@ -4709,9 +4757,15 @@
         super.onAttachedToWindow();
         if (hasWindowFocus()) setActive(true);
         final ViewTreeObserver treeObserver = getViewTreeObserver();
-        if (treeObserver != null && mListener == null) {
-            mListener = new InnerGlobalLayoutListener();
-            treeObserver.addOnGlobalLayoutListener(mListener);
+        if (treeObserver != null) {
+            if (mGlobalLayoutListener == null) {
+                mGlobalLayoutListener = new InnerGlobalLayoutListener();
+                treeObserver.addOnGlobalLayoutListener(mGlobalLayoutListener);
+            }
+            if (mScrollChangedListener == null) {
+                mScrollChangedListener = new InnerScrollChangedListener();
+                treeObserver.addOnScrollChangedListener(mScrollChangedListener);
+            }
         }
     }
 
@@ -4722,9 +4776,15 @@
         if (hasWindowFocus()) setActive(false);
 
         final ViewTreeObserver treeObserver = getViewTreeObserver();
-        if (treeObserver != null && mListener != null) {
-            treeObserver.removeGlobalOnLayoutListener(mListener);
-            mListener = null;
+        if (treeObserver != null) {
+            if (mGlobalLayoutListener != null) {
+                treeObserver.removeGlobalOnLayoutListener(mGlobalLayoutListener);
+                mGlobalLayoutListener = null;
+            }
+            if (mScrollChangedListener != null) {
+                treeObserver.removeOnScrollChangedListener(mScrollChangedListener);
+                mScrollChangedListener = null;
+            }
         }
 
         super.onDetachedFromWindow();
@@ -5020,14 +5080,15 @@
         startTouch(detector.getFocusX(), detector.getFocusY(), mLastTouchTime);
     }
 
+    // See if there is a layer at x, y and switch to TOUCH_DRAG_LAYER_MODE if a
+    // layer is found.
     private void startScrollingLayer(float x, float y) {
-        if (mTouchMode != TOUCH_DRAG_LAYER_MODE) {
-            int contentX = viewToContentX((int) x + mScrollX);
-            int contentY = viewToContentY((int) y + mScrollY);
-            mScrollingLayer = nativeScrollableLayer(contentX, contentY);
-            if (mScrollingLayer != 0) {
-                mTouchMode = TOUCH_DRAG_LAYER_MODE;
-            }
+        int contentX = viewToContentX((int) x + mScrollX);
+        int contentY = viewToContentY((int) y + mScrollY);
+        mScrollingLayer = nativeScrollableLayer(contentX, contentY,
+                mScrollingLayerRect);
+        if (mScrollingLayer != 0) {
+            mTouchMode = TOUCH_DRAG_LAYER_MODE;
         }
     }
 
@@ -5072,8 +5133,7 @@
         final ScaleGestureDetector detector =
                 mZoomManager.getMultiTouchGestureDetector();
 
-        if (mZoomManager.supportsMultiTouchZoom() && ev.getPointerCount() > 1 &&
-                mTouchMode != TOUCH_DRAG_LAYER_MODE) {
+        if (mZoomManager.supportsMultiTouchZoom() && ev.getPointerCount() > 1) {
             if (!detector.isInProgress() &&
                     ev.getActionMasked() != MotionEvent.ACTION_POINTER_DOWN) {
                 // Insert a fake pointer down event in order to start
@@ -5303,7 +5363,7 @@
                     if (parent != null) {
                         parent.requestDisallowInterceptTouchEvent(true);
                     }
-                    int layer = nativeScrollableLayer(contentX, contentY);
+                    int layer = nativeScrollableLayer(contentX, contentY, mScrollingLayerRect);
                     if (layer == 0) {
                         mAutoScrollX = x <= SELECT_SCROLL ? -SELECT_SCROLL
                             : x >= getViewWidth() - SELECT_SCROLL
@@ -5363,6 +5423,7 @@
                     deltaX = 0;
                     deltaY = 0;
 
+                    startScrollingLayer(x, y);
                     startDrag();
                 }
 
@@ -5431,7 +5492,6 @@
                     mUserScroll = true;
                 }
 
-                startScrollingLayer(x, y);
                 doDrag(deltaX, deltaY);
 
                 // Turn off scrollbars when dragging a layer.
@@ -5654,21 +5714,47 @@
 
     private void doDrag(int deltaX, int deltaY) {
         if ((deltaX | deltaY) != 0) {
-            if (mTouchMode == TOUCH_DRAG_LAYER_MODE) {
-                deltaX = viewToContentDimension(deltaX);
-                deltaY = viewToContentDimension(deltaY);
-                if (nativeScrollLayer(mScrollingLayer, deltaX, deltaY)) {
-                    invalidate();
-                    return;
-                }
-                // Switch to drag mode and fall through.
-                mTouchMode = TOUCH_DRAG_MODE;
-            }
+            int oldX = mScrollX;
+            int oldY = mScrollY;
+            int rangeX = computeMaxScrollX();
+            int rangeY = computeMaxScrollY();
+            int overscrollDistance = mOverscrollDistance;
 
-            final int oldX = mScrollX;
-            final int oldY = mScrollY;
-            final int rangeX = computeMaxScrollX();
-            final int rangeY = computeMaxScrollY();
+            // Check for the original scrolling layer in case we change
+            // directions.  mTouchMode might be TOUCH_DRAG_MODE if we have
+            // reached the edge of a layer but mScrollingLayer will be non-zero
+            // if we initiated the drag on a layer.
+            if (mScrollingLayer != 0) {
+                final int contentX = viewToContentDimension(deltaX);
+                final int contentY = viewToContentDimension(deltaY);
+
+                // Check the scrolling bounds to see if we will actually do any
+                // scrolling.  The rectangle is in document coordinates.
+                final int maxX = mScrollingLayerRect.right;
+                final int maxY = mScrollingLayerRect.bottom;
+                final int resultX = Math.max(0,
+                        Math.min(mScrollingLayerRect.left + contentX, maxX));
+                final int resultY = Math.max(0,
+                        Math.min(mScrollingLayerRect.top + contentY, maxY));
+
+                if (resultX != mScrollingLayerRect.left ||
+                        resultY != mScrollingLayerRect.top) {
+                    // In case we switched to dragging the page.
+                    mTouchMode = TOUCH_DRAG_LAYER_MODE;
+                    deltaX = contentX;
+                    deltaY = contentY;
+                    oldX = mScrollingLayerRect.left;
+                    oldY = mScrollingLayerRect.top;
+                    rangeX = maxX;
+                    rangeY = maxY;
+                } else {
+                    // Scroll the main page if we are not going to scroll the
+                    // layer.  This does not reset mScrollingLayer in case the
+                    // user changes directions and the layer can scroll the
+                    // other way.
+                    mTouchMode = TOUCH_DRAG_MODE;
+                }
+            }
 
             if (mOverScrollGlow != null) {
                 mOverScrollGlow.setOverScrollDeltas(deltaX, deltaY);
@@ -6067,6 +6153,21 @@
         int vx = (int) mVelocityTracker.getXVelocity();
         int vy = (int) mVelocityTracker.getYVelocity();
 
+        int scrollX = mScrollX;
+        int scrollY = mScrollY;
+        int overscrollDistance = mOverscrollDistance;
+        int overflingDistance = mOverflingDistance;
+
+        // Use the layer's scroll data if applicable.
+        if (mTouchMode == TOUCH_DRAG_LAYER_MODE) {
+            scrollX = mScrollingLayerRect.left;
+            scrollY = mScrollingLayerRect.top;
+            maxX = mScrollingLayerRect.right;
+            maxY = mScrollingLayerRect.bottom;
+            // No overscrolling for layers.
+            overscrollDistance = overflingDistance = 0;
+        }
+
         if (mSnapScrollMode != SNAP_NONE) {
             if ((mSnapScrollMode & SNAP_X) == SNAP_X) {
                 vy = 0;
@@ -6084,8 +6185,7 @@
             if (!mSelectingText) {
                 WebViewCore.resumeUpdatePicture(mWebViewCore);
             }
-            if (mScroller.springBack(mScrollX, mScrollY, 0, computeMaxScrollX(),
-                    0, computeMaxScrollY())) {
+            if (mScroller.springBack(scrollX, scrollY, 0, maxX, 0, maxY)) {
                 invalidate();
             }
             return;
@@ -6112,24 +6212,25 @@
                     + " current=" + currentVelocity
                     + " vx=" + vx + " vy=" + vy
                     + " maxX=" + maxX + " maxY=" + maxY
-                    + " mScrollX=" + mScrollX + " mScrollY=" + mScrollY);
+                    + " scrollX=" + scrollX + " scrollY=" + scrollY
+                    + " layer=" + mScrollingLayer);
         }
 
         // Allow sloppy flings without overscrolling at the edges.
-        if ((mScrollX == 0 || mScrollX == maxX) && Math.abs(vx) < Math.abs(vy)) {
+        if ((scrollX == 0 || scrollX == maxX) && Math.abs(vx) < Math.abs(vy)) {
             vx = 0;
         }
-        if ((mScrollY == 0 || mScrollY == maxY) && Math.abs(vy) < Math.abs(vx)) {
+        if ((scrollY == 0 || scrollY == maxY) && Math.abs(vy) < Math.abs(vx)) {
             vy = 0;
         }
 
-        if (mOverscrollDistance < mOverflingDistance) {
-            if ((vx > 0 && mScrollX == -mOverscrollDistance) ||
-                    (vx < 0 && mScrollX == maxX + mOverscrollDistance)) {
+        if (overscrollDistance < overflingDistance) {
+            if ((vx > 0 && scrollX == -overscrollDistance) ||
+                    (vx < 0 && scrollX == maxX + overscrollDistance)) {
                 vx = 0;
             }
-            if ((vy > 0 && mScrollY == -mOverscrollDistance) ||
-                    (vy < 0 && mScrollY == maxY + mOverscrollDistance)) {
+            if ((vy > 0 && scrollY == -overscrollDistance) ||
+                    (vy < 0 && scrollY == maxY + overscrollDistance)) {
                 vy = 0;
             }
         }
@@ -6139,8 +6240,8 @@
         mLastVelocity = velocity;
 
         // no horizontal overscroll if the content just fits
-        mScroller.fling(mScrollX, mScrollY, -vx, -vy, 0, maxX, 0, maxY,
-                maxX == 0 ? 0 : mOverflingDistance, mOverflingDistance);
+        mScroller.fling(scrollX, scrollY, -vx, -vy, 0, maxX, 0, maxY,
+                maxX == 0 ? 0 : overflingDistance, overflingDistance);
         // Duration is calculated based on velocity. With range boundaries and overscroll
         // we may not know how long the final animation will take. (Hence the deprecation
         // warning on the call below.) It's not a big deal for scroll bars but if webcore
@@ -6664,7 +6765,7 @@
                         mSentAutoScrollMessage = false;
                         break;
                     }
-                    scrollBy(mAutoScrollX, mAutoScrollY);
+                    pinScrollBy(mAutoScrollX, mAutoScrollY, true, 0);
                     sendEmptyMessageDelayed(
                             SCROLL_SELECT_TEXT, SELECT_SCROLL_INTERVAL);
                     break;
@@ -6948,6 +7049,7 @@
                                     mDeferTouchMode = TOUCH_DRAG_MODE;
                                     mLastDeferTouchX = x;
                                     mLastDeferTouchY = y;
+                                    startScrollingLayer(x, y);
                                     startDrag();
                                 }
                                 int deltaX = pinLocX((int) (mScrollX
@@ -6956,7 +7058,6 @@
                                 int deltaY = pinLocY((int) (mScrollY
                                         + mLastDeferTouchY - y))
                                         - mScrollY;
-                                startScrollingLayer(x, y);
                                 doDrag(deltaX, deltaY);
                                 if (deltaX != 0) mLastDeferTouchX = x;
                                 if (deltaY != 0) mLastDeferTouchY = y;
@@ -7852,6 +7953,6 @@
     native int nativeGetBlockLeftEdge(int x, int y, float scale);
 
     // Returns a pointer to the scrollable LayerAndroid at the given point.
-    private native int      nativeScrollableLayer(int x, int y);
+    private native int      nativeScrollableLayer(int x, int y, Rect scrollRect);
     private native boolean  nativeScrollLayer(int layer, int dx, int dy);
 }
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index cc94fd0..d2c7fce 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -852,6 +852,7 @@
             "VALID_NODE_BOUNDS", // = 146
             "SAVE_WEBARCHIVE", // = 147
             "WEBKIT_DRAW_LAYERS", // = 148;
+            "REMOVE_JS_INTERFACE", // = 149;
         };
 
     class EventHub {
@@ -925,6 +926,8 @@
         // Update layers
         static final int WEBKIT_DRAW_LAYERS = 148;
 
+        static final int REMOVE_JS_INTERFACE = 149;
+
         // Network-based messaging
         static final int CLEAR_SSL_PREF_TABLE = 150;
 
@@ -1290,6 +1293,12 @@
                                     jsData.mInterfaceName);
                             break;
 
+                        case REMOVE_JS_INTERFACE:
+                            jsData = (JSInterfaceData) msg.obj;
+                            mBrowserFrame.removeJavascriptInterface(
+                                    jsData.mInterfaceName);
+                            break;
+
                         case REQUEST_EXT_REPRESENTATION:
                             mBrowserFrame.externalRepresentation(
                                     (Message) msg.obj);
diff --git a/core/java/android/webkit/ZoomManager.java b/core/java/android/webkit/ZoomManager.java
index b94dc3b..230cc51 100644
--- a/core/java/android/webkit/ZoomManager.java
+++ b/core/java/android/webkit/ZoomManager.java
@@ -580,7 +580,7 @@
         mInvZoomOverviewWidth = 1.0f / width;
     }
 
-    private float getZoomOverviewScale() {
+    /* package */ float getZoomOverviewScale() {
         return mWebView.getViewWidth() * mInvZoomOverviewWidth;
     }
 
@@ -672,7 +672,10 @@
         }
 
         public boolean onScale(ScaleGestureDetector detector) {
-            float scale = Math.round(detector.getScaleFactor() * mActualScale * 100) * 0.01f;
+            // Prevent scaling beyond overview scale.
+            float scale = Math.max(
+                Math.round(detector.getScaleFactor() * mActualScale * 100) * 0.01f,
+                getZoomOverviewScale());
             if (willScaleTriggerZoom(scale)) {
                 mPinchToZoomAnimating = true;
                 // limit the scale change per step
diff --git a/core/java/android/widget/DatePicker.java b/core/java/android/widget/DatePicker.java
index 595b487..4e5bc6e 100644
--- a/core/java/android/widget/DatePicker.java
+++ b/core/java/android/widget/DatePicker.java
@@ -16,6 +16,8 @@
 
 package android.widget;
 
+import com.android.internal.R;
+
 import android.annotation.Widget;
 import android.content.Context;
 import android.content.res.TypedArray;
@@ -26,50 +28,44 @@
 import android.util.AttributeSet;
 import android.util.SparseArray;
 import android.view.LayoutInflater;
-import android.widget.NumberPicker;
-import android.widget.NumberPicker.OnChangedListener;
+import android.widget.NumberPicker.OnChangeListener;
 
-import com.android.internal.R;
-
-import java.text.DateFormatSymbols;
 import java.text.SimpleDateFormat;
 import java.util.Calendar;
 import java.util.Locale;
 
 /**
  * A view for selecting a month / year / day based on a calendar like layout.
- *
- * <p>See the <a href="{@docRoot}resources/tutorials/views/hello-datepicker.html">Date Picker
- * tutorial</a>.</p>
- *
+ * <p>
+ * See the <a href="{@docRoot}
+ * resources/tutorials/views/hello-datepicker.html">Date Picker tutorial</a>.
+ * </p>
  * For a dialog using this view, see {@link android.app.DatePickerDialog}.
  */
 @Widget
 public class DatePicker extends FrameLayout {
 
     private static final int DEFAULT_START_YEAR = 1900;
+
     private static final int DEFAULT_END_YEAR = 2100;
 
-    // This ignores Undecimber, but we only support real Gregorian calendars.
-    private static final int NUMBER_OF_MONTHS = 12;
-
-    /* UI Components */
     private final NumberPicker mDayPicker;
+
     private final NumberPicker mMonthPicker;
+
     private final NumberPicker mYearPicker;
 
-    /**
-     * How we notify users the date has changed.
-     */
-    private OnDateChangedListener mOnDateChangedListener;
-    
-    private int mDay;
-    private int mMonth;
-    private int mYear;
+    private final DayPicker mMiniMonthDayPicker;
 
-    private Object mMonthUpdateLock = new Object();
-    private volatile Locale mMonthLocale;
-    private String[] mShortMonths;
+    private OnDateChangedListener mOnDateChangedListener;
+
+    private Locale mMonthLocale;
+
+    private final Calendar mTempCalendar = Calendar.getInstance();
+
+    private final int mNumberOfMonths = mTempCalendar.getActualMaximum(Calendar.MONTH) + 1;
+
+    private final String[] mShortMonths = new String[mNumberOfMonths];
 
     /**
      * The callback used to indicate the user changes the date.
@@ -80,7 +76,7 @@
          * @param view The view associated with this listener.
          * @param year The year that was set.
          * @param monthOfYear The month that was set (0-11) for compatibility
-         *  with {@link java.util.Calendar}.
+         *            with {@link java.util.Calendar}.
          * @param dayOfMonth The day of the month that was set.
          */
         void onDateChanged(DatePicker view, int year, int monthOfYear, int dayOfMonth);
@@ -89,7 +85,7 @@
     public DatePicker(Context context) {
         this(context, null);
     }
-    
+
     public DatePicker(Context context, AttributeSet attrs) {
         this(context, attrs, 0);
     }
@@ -97,103 +93,85 @@
     public DatePicker(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
 
-        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+        LayoutInflater inflater = (LayoutInflater) context
+                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
         inflater.inflate(R.layout.date_picker, this, true);
 
+        OnChangeListener onChangeListener = new OnChangeListener() {
+            public void onChange(NumberPicker picker, int oldVal, int newVal) {
+                notifyDateChanged();
+                updateMiniMonth();
+            }
+        };
+
+        // day
         mDayPicker = (NumberPicker) findViewById(R.id.day);
         mDayPicker.setFormatter(NumberPicker.TWO_DIGIT_FORMATTER);
-        mDayPicker.setSpeed(100);
-        mDayPicker.setOnChangeListener(new OnChangedListener() {
-            public void onChanged(NumberPicker picker, int oldVal, int newVal) {
-                mDay = newVal;
-                notifyDateChanged();
-            }
-        });
+        mDayPicker.setOnLongPressUpdateInterval(100);
+        mDayPicker.setOnChangeListener(onChangeListener);
+
+        // month
         mMonthPicker = (NumberPicker) findViewById(R.id.month);
-        mMonthPicker.setFormatter(NumberPicker.TWO_DIGIT_FORMATTER);
-        final String[] months = getShortMonths();
+        mMonthPicker.setRange(0, mNumberOfMonths - 1, getShortMonths());
+        mMonthPicker.setOnLongPressUpdateInterval(200);
+        mMonthPicker.setOnChangeListener(onChangeListener);
 
-        /*
-         * If the user is in a locale where the month names are numeric,
-         * use just the number instead of the "month" character for
-         * consistency with the other fields.
-         */
-        if (months[0].startsWith("1")) {
-            for (int i = 0; i < months.length; i++) {
-                months[i] = String.valueOf(i + 1);
-            }
-            mMonthPicker.setRange(1, NUMBER_OF_MONTHS);
-        } else {
-            mMonthPicker.setRange(1, NUMBER_OF_MONTHS, months);
-        }
-
-        mMonthPicker.setSpeed(200);
-        mMonthPicker.setOnChangeListener(new OnChangedListener() {
-            public void onChanged(NumberPicker picker, int oldVal, int newVal) {
-                
-                /* We display the month 1-12 but store it 0-11 so always
-                 * subtract by one to ensure our internal state is always 0-11
-                 */
-                mMonth = newVal - 1;
-                // Adjust max day of the month
-                adjustMaxDay();
-                notifyDateChanged();
-                updateDaySpinner();
-            }
-        });
+        // year
         mYearPicker = (NumberPicker) findViewById(R.id.year);
-        mYearPicker.setSpeed(100);
-        mYearPicker.setOnChangeListener(new OnChangedListener() {
-            public void onChanged(NumberPicker picker, int oldVal, int newVal) {
-                mYear = newVal;
-                // Adjust max day for leap years if needed
-                adjustMaxDay();
-                notifyDateChanged();
-                updateDaySpinner();
-            }
-        });
-        
-        // attributes
+        mYearPicker.setOnLongPressUpdateInterval(100);
+        mYearPicker.setOnChangeListener(onChangeListener);
         TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DatePicker);
-
         int mStartYear = a.getInt(R.styleable.DatePicker_startYear, DEFAULT_START_YEAR);
         int mEndYear = a.getInt(R.styleable.DatePicker_endYear, DEFAULT_END_YEAR);
         mYearPicker.setRange(mStartYear, mEndYear);
-        
         a.recycle();
+
+        // mini-month day-picker
+        mMiniMonthDayPicker = (DayPicker) findViewById(R.id.mini_month_day_picker);
+        mTempCalendar.clear();
+        mTempCalendar.set(mStartYear, 0, 1);
+        Calendar endRangeDate = (Calendar) mTempCalendar.clone();
+        endRangeDate.set(mEndYear, 11, 31);
+        mMiniMonthDayPicker.setRange(mTempCalendar, endRangeDate);
+        mMiniMonthDayPicker.setOnDateChangeListener(new DayPicker.OnSelectedDayChangeListener() {
+            public void onSelectedDayChange(DayPicker view, int year, int month, int monthDay) {
+                updateDate(year, month, monthDay);
+            }
+        });
         
         // initialize to current date
-        Calendar cal = Calendar.getInstance();
-        init(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DAY_OF_MONTH), null);
-        
+        mTempCalendar.setTimeInMillis(System.currentTimeMillis());
+        init(mTempCalendar.get(Calendar.YEAR), mTempCalendar.get(Calendar.MONTH),
+                mTempCalendar.get(Calendar.DAY_OF_MONTH), null);
+
         // re-order the number pickers to match the current date format
-        reorderPickers(months);
-        
-        if (!isEnabled()) {
-            setEnabled(false);
-        }
+        reorderPickers();
     }
-    
+
     @Override
     public void setEnabled(boolean enabled) {
         super.setEnabled(enabled);
         mDayPicker.setEnabled(enabled);
         mMonthPicker.setEnabled(enabled);
         mYearPicker.setEnabled(enabled);
+        mMiniMonthDayPicker.setEnabled(enabled);
     }
 
-    private void reorderPickers(String[] months) {
+    /**
+     * Reorders the pickers according to the date format in the current locale.
+     */
+    private void reorderPickers() {
         java.text.DateFormat format;
         String order;
 
         /*
-         * If the user is in a locale where the medium date format is
-         * still numeric (Japanese and Czech, for example), respect
-         * the date format order setting.  Otherwise, use the order
-         * that the locale says is appropriate for a spelled-out date.
+         * If the user is in a locale where the medium date format is still
+         * numeric (Japanese and Czech, for example), respect the date format
+         * order setting. Otherwise, use the order that the locale says is
+         * appropriate for a spelled-out date.
          */
 
-        if (months[0].startsWith("1")) {
+        if (getShortMonths()[0].startsWith("1")) {
             format = DateFormat.getDateFormat(getContext());
         } else {
             format = DateFormat.getMediumDateFormat(getContext());
@@ -206,10 +184,11 @@
             order = new String(DateFormat.getDateFormatOrder(getContext()));
         }
 
-        /* Remove the 3 pickers from their parent and then add them back in the
+        /*
+         * Remove the 3 pickers from their parent and then add them back in the
          * required order.
          */
-        LinearLayout parent = (LinearLayout) findViewById(R.id.parent);
+        LinearLayout parent = (LinearLayout) findViewById(R.id.pickers);
         parent.removeAllViews();
 
         boolean quoted = false;
@@ -230,7 +209,7 @@
                     parent.addView(mMonthPicker);
                     didMonth = true;
                 } else if (c == DateFormat.YEAR && !didYear) {
-                    parent.addView (mYearPicker);
+                    parent.addView(mYearPicker);
                     didYear = true;
                 }
             }
@@ -248,40 +227,145 @@
         }
     }
 
-    public void updateDate(int year, int monthOfYear, int dayOfMonth) {
-        if (mYear != year || mMonth != monthOfYear || mDay != dayOfMonth) {
-            mYear = year;
-            mMonth = monthOfYear;
-            mDay = dayOfMonth;
-            updateSpinners();
-            reorderPickers(getShortMonths());
+    /**
+     * Updates the current date.
+     *
+     * @param year The year.
+     * @param month The month which is <strong>starting from zero</strong>.
+     * @param dayOfMonth The day of the month.
+     */
+    public void updateDate(int year, int month, int dayOfMonth) {
+        if (mYearPicker.getCurrent() != year
+                || mDayPicker.getCurrent() != dayOfMonth
+                || mMonthPicker.getCurrent() != month) {
+            updatePickers(year, month, dayOfMonth);
+            updateMiniMonth();
             notifyDateChanged();
         }
     }
 
+    /**
+     * @return The short month abbreviations.
+     */
     private String[] getShortMonths() {
         final Locale currentLocale = Locale.getDefault();
-        if (currentLocale.equals(mMonthLocale) && mShortMonths != null) {
+        if (currentLocale.equals(mMonthLocale)) {
             return mShortMonths;
         } else {
-            synchronized (mMonthUpdateLock) {
-                if (!currentLocale.equals(mMonthLocale)) {
-                    mShortMonths = new String[NUMBER_OF_MONTHS];
-                    for (int i = 0; i < NUMBER_OF_MONTHS; i++) {
-                        mShortMonths[i] = DateUtils.getMonthString(Calendar.JANUARY + i,
-                                DateUtils.LENGTH_MEDIUM);
-                    }
-                    mMonthLocale = currentLocale;
-                }
+            for (int i = 0; i < mNumberOfMonths; i++) {
+                mShortMonths[i] = DateUtils.getMonthString(Calendar.JANUARY + i,
+                        DateUtils.LENGTH_MEDIUM);
             }
+            mMonthLocale = currentLocale;
             return mShortMonths;
         }
     }
 
+    // Override so we are in complete control of save / restore for this widget.
+    @Override
+    protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
+        dispatchThawSelfOnly(container);
+    }
+
+    @Override
+    protected Parcelable onSaveInstanceState() {
+        Parcelable superState = super.onSaveInstanceState();
+        return new SavedState(superState, mYearPicker.getCurrent(), mMonthPicker.getCurrent(),
+                mDayPicker.getCurrent());
+    }
+
+    @Override
+    protected void onRestoreInstanceState(Parcelable state) {
+        SavedState ss = (SavedState) state;
+        super.onRestoreInstanceState(ss.getSuperState());
+        updatePickers(ss.mYear, ss.mMonth, ss.mDay);
+    }
+
+    /**
+     * Initialize the state. If the provided values designate an inconsistent
+     * date the values are normalized before updating the pickers.
+     *
+     * @param year The initial year.
+     * @param monthOfYear The initial month <strong>starting from zero</strong>.
+     * @param dayOfMonth The initial day of the month.
+     * @param onDateChangedListener How user is notified date is changed by
+     *            user, can be null.
+     */
+    public void init(int year, int monthOfYear, int dayOfMonth,
+            OnDateChangedListener onDateChangedListener) {
+        mOnDateChangedListener = onDateChangedListener;
+        updateDate(year, monthOfYear, dayOfMonth);
+    }
+
+    /**
+     * Updates the pickers with the given <code>year</code>, <code>month</code>,
+     * and <code>dayOfMonth</code>. If the provided values designate an inconsistent
+     * date the values are normalized before updating the pickers.
+     */
+    private void updatePickers(int year, int month, int dayOfMonth) {
+        // make sure the date is normalized
+        mTempCalendar.clear();
+        mTempCalendar.set(year, month, dayOfMonth);
+        mYearPicker.setCurrent(mTempCalendar.get(Calendar.YEAR));
+        mMonthPicker.setCurrent(mTempCalendar.get(Calendar.MONTH));
+        mDayPicker.setRange(1, mTempCalendar.getActualMaximum(Calendar.DAY_OF_MONTH));
+        mDayPicker.setCurrent(mTempCalendar.get(Calendar.DAY_OF_MONTH));
+    }
+
+    /**
+     * Updates the mini-month with the given year, month, and day selected by the
+     * number pickers.
+     */
+    private void updateMiniMonth() {
+        Calendar selectedDay = mMiniMonthDayPicker.getSelectedDay();
+        if (selectedDay.get(Calendar.YEAR) != mYearPicker.getCurrent()
+                || selectedDay.get(Calendar.MONTH) != mMonthPicker.getCurrent()
+                || selectedDay.get(Calendar.DAY_OF_MONTH) != mDayPicker.getCurrent()) {
+            mMiniMonthDayPicker.goTo(mYearPicker.getCurrent(), mMonthPicker.getCurrent(),
+                    mDayPicker.getCurrent(), false, true, false);
+        }
+    }
+
+    /**
+     * @return The selected year.
+     */
+    public int getYear() {
+        return mYearPicker.getCurrent();
+    }
+
+    /**
+     * @return The selected month.
+     */
+    public int getMonth() {
+        return mMonthPicker.getCurrent();
+    }
+
+    /**
+     * @return The selected day of month.
+     */
+    public int getDayOfMonth() {
+        return mDayPicker.getCurrent();
+    }
+
+    /**
+     * Notifies the listener, if such, for a change in the selected date.
+     */
+    private void notifyDateChanged() {
+        if (mOnDateChangedListener != null) {
+            mOnDateChangedListener.onDateChanged(DatePicker.this, mYearPicker.getCurrent(),
+                    mMonthPicker.getCurrent(), mDayPicker.getCurrent());
+        }
+    }
+
+    /**
+     * Class for managing state storing/restoring.
+     */
     private static class SavedState extends BaseSavedState {
 
         private final int mYear;
+
         private final int mMonth;
+
         private final int mDay;
 
         /**
@@ -293,7 +377,7 @@
             mMonth = month;
             mDay = day;
         }
-        
+
         /**
          * Constructor called from {@link #CREATOR}
          */
@@ -304,18 +388,6 @@
             mDay = in.readInt();
         }
 
-        public int getYear() {
-            return mYear;
-        }
-
-        public int getMonth() {
-            return mMonth;
-        }
-
-        public int getDay() {
-            return mDay;
-        }
-
         @Override
         public void writeToParcel(Parcel dest, int flags) {
             super.writeToParcel(dest, flags);
@@ -324,104 +396,17 @@
             dest.writeInt(mDay);
         }
 
-        public static final Parcelable.Creator<SavedState> CREATOR =
-                new Creator<SavedState>() {
+        @SuppressWarnings("all")
+        // suppress unused and hiding
+        public static final Parcelable.Creator<SavedState> CREATOR = new Creator<SavedState>() {
 
-                    public SavedState createFromParcel(Parcel in) {
-                        return new SavedState(in);
-                    }
+            public SavedState createFromParcel(Parcel in) {
+                return new SavedState(in);
+            }
 
-                    public SavedState[] newArray(int size) {
-                        return new SavedState[size];
-                    }
-                };
-    }
-
-
-    /**
-     * Override so we are in complete control of save / restore for this widget.
-     */
-    @Override
-    protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
-        dispatchThawSelfOnly(container);
-    }
-
-    @Override
-    protected Parcelable onSaveInstanceState() {
-        Parcelable superState = super.onSaveInstanceState();
-        
-        return new SavedState(superState, mYear, mMonth, mDay);
-    }
-
-    @Override
-    protected void onRestoreInstanceState(Parcelable state) {
-        SavedState ss = (SavedState) state;
-        super.onRestoreInstanceState(ss.getSuperState());
-        mYear = ss.getYear();
-        mMonth = ss.getMonth();
-        mDay = ss.getDay();
-        updateSpinners();
-    }
-
-    /**
-     * Initialize the state.
-     * @param year The initial year.
-     * @param monthOfYear The initial month.
-     * @param dayOfMonth The initial day of the month.
-     * @param onDateChangedListener How user is notified date is changed by user, can be null.
-     */
-    public void init(int year, int monthOfYear, int dayOfMonth,
-            OnDateChangedListener onDateChangedListener) {
-        mYear = year;
-        mMonth = monthOfYear;
-        mDay = dayOfMonth;
-        mOnDateChangedListener = onDateChangedListener;
-        updateSpinners();
-    }
-
-    private void updateSpinners() {
-        updateDaySpinner();
-        mYearPicker.setCurrent(mYear);
-        
-        /* The month display uses 1-12 but our internal state stores it
-         * 0-11 so add one when setting the display.
-         */
-        mMonthPicker.setCurrent(mMonth + 1);
-    }
-
-    private void updateDaySpinner() {
-        Calendar cal = Calendar.getInstance();
-        cal.set(mYear, mMonth, mDay);
-        int max = cal.getActualMaximum(Calendar.DAY_OF_MONTH);
-        mDayPicker.setRange(1, max);
-        mDayPicker.setCurrent(mDay);
-    }
-
-    public int getYear() {
-        return mYear;
-    }
-
-    public int getMonth() {
-        return mMonth;
-    }
-
-    public int getDayOfMonth() {
-        return mDay;
-    }
-
-    private void adjustMaxDay(){
-        Calendar cal = Calendar.getInstance();
-        cal.set(Calendar.YEAR, mYear);
-        cal.set(Calendar.MONTH, mMonth);
-        int max = cal.getActualMaximum(Calendar.DAY_OF_MONTH);
-        if (mDay > max) {
-            mDay = max;
-        }
-    }
-
-    private void notifyDateChanged() {
-        if (mOnDateChangedListener != null) {
-            mOnDateChangedListener.onDateChanged(DatePicker.this, mYear, mMonth, mDay);
-        }
+            public SavedState[] newArray(int size) {
+                return new SavedState[size];
+            }
+        };
     }
 }
diff --git a/core/java/android/widget/DayPicker.java b/core/java/android/widget/DayPicker.java
new file mode 100644
index 0000000..11c23ab
--- /dev/null
+++ b/core/java/android/widget/DayPicker.java
@@ -0,0 +1,1474 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.widget;
+
+import com.android.internal.R;
+
+import android.app.Service;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.database.DataSetObserver;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Paint.Align;
+import android.graphics.Paint.Style;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.text.format.DateFormat;
+import android.text.format.DateUtils;
+import android.text.format.Time;
+import android.util.AttributeSet;
+import android.util.TypedValue;
+import android.view.GestureDetector;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AbsListView.OnScrollListener;
+
+import java.security.InvalidParameterException;
+import java.util.Calendar;
+import java.util.HashMap;
+import java.util.Locale;
+
+import libcore.icu.LocaleData;
+
+/**
+ * Displays a day picker in the form of a calendar. The calendar
+ * is represented as a list where each row depicts a week. Each week is
+ * composed of items that are selectable days.
+ */
+public class DayPicker extends FrameLayout {
+
+    /**
+     * The number of milliseconds in a day.
+     *
+     * @hide
+     */
+    protected static final long MILLIS_IN_DAY = 86400000L;
+
+    /**
+     * The number of day in a week.
+     *
+     * @hide
+     */
+    protected static final int DAYS_PER_WEEK = 7;
+
+    /**
+     * The number of milliseconds in a week.
+     *
+     * @hide
+     */
+    protected static final long MILLIS_IN_WEEK = DAYS_PER_WEEK * MILLIS_IN_DAY;
+
+    /**
+     * Affects when the month selection will change while scrolling up
+     *
+     * @hide
+     */ 
+    protected static final int SCROLL_HYST_WEEKS = 2;
+
+    /**
+     * How long the GoTo fling animation should last.
+     *
+     * @hide
+     */
+    protected static final int GOTO_SCROLL_DURATION = 1000;
+
+    /**
+     * The duration of the adjustment upon a user scroll in milliseconds.
+     *
+     * @hide
+     */
+    protected static final int ADJUSTMENT_SCROLL_DURATION = 500;
+
+    /**
+     * How long to wait after receiving an onScrollStateChanged notification
+     * before acting on it.
+     *
+     * @hide
+     */
+    protected static final int SCROLL_CHANGE_DELAY = 40;
+
+    /**
+     * The scale used to compensate for different screen density.
+     *
+     * @hide
+     */
+    protected static float sScale;
+
+    /**
+     * The top offset of the weeks list.
+     *
+     * @hide
+     */
+    protected static int mListTopOffset = 2;
+
+    /**
+     * The visible height of a week view.
+     *
+     * @hide
+     */
+    protected int mWeekMinVisibleHeight = 12;
+
+
+    /**
+     * The visible height of a week view.
+     *
+     * @hide
+     */
+    protected int mBottomBuffer = 20;
+
+    /**
+     * The number of shown weeks.
+     *
+     * @hide
+     */
+    protected int mShownWeekCount = 6;
+
+    /**
+     * Flag whether to show the week number.
+     *
+     * @hide
+     */
+    protected boolean mShowWeekNumber = true;
+
+    /**
+     * The number of day per week to be shown
+     *
+     * @hide
+     */
+    protected int mDaysPerWeek = 7;
+
+    /**
+     * The friction of the week list while flinging.
+     *
+     * @hide
+     */
+    protected float mFriction = .05f;
+
+    /**
+     * Scale for adjusting velocity of the week list while flinging.
+     *
+     * @hide
+     */
+    protected float mVelocityScale = 0.333f;
+
+    /**
+     * The adapter for the weeks list.
+     *
+     * @hide
+     */
+    protected WeeksAdapter mAdapter;
+
+    /**
+     * The weeks list.
+     *
+     * @hide
+     */
+    protected ListView mListView;
+
+    /**
+     * The name of the month to display.
+     *
+     * @hide
+     */
+    protected TextView mMonthName;
+
+    /**
+     * The header with week day names.
+     *
+     * @hide
+     */
+    protected ViewGroup mDayNamesHeader;
+
+    /**
+     * Cached labels for the week names header.
+     *
+     * @hide
+     */
+    protected String[] mDayLabels;
+
+    /**
+     * Temporary instance to avoid multiple instantiations.
+     *
+     * @hide
+     */
+    protected Calendar mTempCalendar = Calendar.getInstance();
+
+    /**
+     * The first day of the week based on the current locale.
+     *
+     * @hide
+     */
+    protected int mFirstDayOfWeek = LocaleData.get(Locale.getDefault()).firstDayOfWeek;
+
+    /**
+     * The first day of the focused month.
+     *
+     * @hide
+     */
+    protected Calendar mFirstDayOfMonth = Calendar.getInstance();
+
+    /**
+     * Which month should be displayed/highlighted [0-11]
+     *
+     * @hide
+     */
+    protected int mCurrentMonthDisplayed;
+
+    /**
+     * Used for tracking during a scroll.
+     *
+     * @hide
+     */
+    protected long mPreviousScrollPosition;
+
+    /**
+     * Used for tracking which direction the view is scrolling.
+     *
+     * @hide
+     */
+    protected boolean mIsScrollingUp = false;
+
+    /**
+     * The previous scroll state of the weeks ListView.
+     *
+     * @hide
+     */
+    protected int mPreviousScrollState = OnScrollListener.SCROLL_STATE_IDLE;
+
+    /**
+     * The current scroll state of the weeks ListView.
+     *
+     * @hide
+     */
+    protected int mCurrentScrollState = OnScrollListener.SCROLL_STATE_IDLE;
+
+    /**
+     * Listener for changes in the selected day.
+     *
+     * @hide
+     */
+    protected OnSelectedDayChangeListener mOnChangeListener;
+
+    /**
+     * Command for adjusting the position after a scroll/fling.
+     *
+     * @hide
+     */
+    protected ScrollStateRunnable mScrollStateChangedRunnable = new ScrollStateRunnable();
+
+    /**
+     * The start date of the range supported by this picker.
+     *
+     * @hide
+     */
+    protected Calendar mStartRangeDate = Calendar.getInstance();
+
+    /**
+     * The end date of the range supported by this picker.
+     *
+     * @hide
+     */
+    protected Calendar mEndRangeDate = Calendar.getInstance();
+
+    /**
+     * String for formatting the month name in the title text view.
+     *
+     * @hide
+     */
+    protected String mMonthNameFormatSrting = "MMMM, yyyy";
+
+    /**
+     * The callback used to indicate the user changes the date.
+     */
+    public interface OnSelectedDayChangeListener {
+
+        /**
+         * Called upon change of the selected day.
+         *
+         * @param view The view associated with this listener.
+         * @param year The year that was set.
+         * @param month The month that was set [0-11].
+         * @param dayOfMonth The day of the month that was set.
+         */
+        public void onSelectedDayChange(DayPicker view, int year, int month, int dayOfMonth);
+    }
+
+    public DayPicker(Context context) {
+        this(context, null);
+    }
+
+    public DayPicker(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public DayPicker(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, 0);
+
+        LayoutInflater layoutInflater = (LayoutInflater) mContext
+                .getSystemService(Service.LAYOUT_INFLATER_SERVICE);
+        View content = layoutInflater.inflate(R.layout.day_picker, null, false);
+        addView(content);
+
+        mListView = (ListView) findViewById(R.id.list);
+        mDayNamesHeader = (ViewGroup) content.findViewById(com.android.internal.R.id.day_names);
+        mMonthName = (TextView) content.findViewById(com.android.internal.R.id.month_name);
+
+        // Adjust sizes for screen density
+        if (sScale == 0) {
+            sScale = mContext.getResources().getDisplayMetrics().density;
+            if (sScale != 1) {
+                mWeekMinVisibleHeight *= sScale;
+                mBottomBuffer *= sScale;
+                mListTopOffset *= sScale;
+            }
+        }
+
+        // set default range
+        mStartRangeDate.clear();
+        mStartRangeDate.set(1900, 0, 1);
+        mEndRangeDate.clear();
+        mEndRangeDate.set(2100, 0, 1);
+
+        setUpHeader();
+        updateHeader();
+        setUpListView();
+        setUpAdapter();
+
+        // go to today now
+        mTempCalendar.setTimeInMillis(System.currentTimeMillis());
+        goTo(mTempCalendar, false, true, true);
+        invalidate();
+    }
+
+    /**
+     * Sets the range supported by this day picker. This is the picker will not
+     * support dates before <code>startRangeDate</code> and <code>endRangeDate
+     * </code>.
+     *
+     * @param startRangeDate The start date.
+     * @param endRangeDate The end date.
+     */
+    public void setRange(Calendar startRangeDate, Calendar endRangeDate) {
+        boolean doSetupAdapter = false;
+        if (mStartRangeDate.get(Calendar.DAY_OF_YEAR) != startRangeDate.get(Calendar.DAY_OF_YEAR)
+                || mStartRangeDate.get(Calendar.YEAR) != startRangeDate.get(Calendar.YEAR)) {
+            mStartRangeDate = startRangeDate;
+            doSetupAdapter = true;
+        }
+        if (mEndRangeDate.get(Calendar.DAY_OF_YEAR) != endRangeDate.get(Calendar.DAY_OF_YEAR)
+                || mEndRangeDate.get(Calendar.YEAR) != endRangeDate.get(Calendar.YEAR)) {
+            mEndRangeDate = endRangeDate;
+            doSetupAdapter = true;
+            
+        }
+        if (doSetupAdapter) {
+            setUpAdapter();
+        }
+    }
+
+    /**
+     * Sets the listener to be notified upon day selection changes.
+     *
+     * @param listener The listener to be called back.
+     */
+    public void setOnDateChangeListener(OnSelectedDayChangeListener listener) {
+        mOnChangeListener = listener;
+    }
+
+    /**
+     * Gets the selected day.
+     *
+     * @return The selected day.
+     */
+    public Calendar getSelectedDay() {
+        return mAdapter.mSelectedDay;
+    }
+
+    /**
+     * Sets the selected day. This is equivalent to a call to
+     * {@link #goTo(Calendar, boolean, boolean, boolean)} with
+     * the arguments <code>selectedDay</code>, <code>false</code>,
+     * <code>true</code>, <code>false</code> respectively.
+     *
+     * @param selectedDay The selected day.
+     */
+    public void setSelectedDay(Calendar selectedDay) {
+        goTo(selectedDay, false, true, false);
+    }
+
+    /**
+     * Creates a new adapter if necessary and sets up its parameters. Override
+     * this method to provide a custom adapter.
+     *
+     * @hide
+     */
+    protected void setUpAdapter() {
+        if (mAdapter == null) {
+            mAdapter = new WeeksAdapter(getContext());
+            mAdapter.registerDataSetObserver(new DataSetObserver() {
+                @Override
+                public void onChanged() {
+                    if (mOnChangeListener != null) {
+                        Calendar selectedDay = mAdapter.getSelectedDay();
+                        mOnChangeListener.onSelectedDayChange(DayPicker.this,
+                                selectedDay.get(Calendar.YEAR),
+                                selectedDay.get(Calendar.MONTH),
+                                selectedDay.get(Calendar.DAY_OF_MONTH));
+                    }
+                }
+            });
+            mListView.setAdapter(mAdapter);
+        }
+
+        // refresh the view with the new parameters
+        mAdapter.notifyDataSetChanged();
+    }
+
+    /**
+     * Sets up the strings to be used by the header. Override this method to use
+     * different strings or modify the view params.
+     *
+     * @hide
+     */
+    protected void setUpHeader() {
+        mDayLabels = new String[mDaysPerWeek];
+        for (int i = mFirstDayOfWeek, count = mFirstDayOfWeek + mDaysPerWeek; i < count; i++) {
+            int calendarDay = (i < mDaysPerWeek) ? i : 1; // Calendar.MONDAY is
+            // 1
+            mDayLabels[i - mFirstDayOfWeek] = DateUtils.getDayOfWeekString(calendarDay,
+                    DateUtils.LENGTH_SHORTEST);
+        }
+    }
+
+    /**
+     * Sets all the required fields for the list view. Override this method to
+     * set a different list view behavior.
+     *
+     * @hide
+     */
+    protected void setUpListView() {
+        // Configure the listview
+        mListView.setDivider(null);
+        mListView.setItemsCanFocus(true);
+        mListView.setVerticalScrollBarEnabled(false);
+        mListView.setOnScrollListener(new OnScrollListener() {
+            public void onScrollStateChanged(AbsListView view, int scrollState) {
+                DayPicker.this.onScrollStateChanged(view, scrollState);
+            }
+
+            public void onScroll(
+                    AbsListView view, int firstVisibleItem, int visibleItemCount,
+                    int totalItemCount) {
+                DayPicker.this.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount);
+            }
+        });
+        // Make the scrolling behavior nicer
+        mListView.setFriction(mFriction);
+        mListView.setVelocityScale(mVelocityScale);
+    }
+
+    /**
+     * Fixes the day names header to provide correct spacing and updates the
+     * label text. Override this to set up a custom header.
+     *
+     * @hide
+     */
+    protected void updateHeader() {
+        TextView label = (TextView) mDayNamesHeader.getChildAt(0);
+        if (mShowWeekNumber) {
+            label.setVisibility(View.VISIBLE);
+        } else {
+            label.setVisibility(View.GONE);
+        }
+        for (int i = 1, count = mDayNamesHeader.getChildCount(); i < count; i++) {
+            label = (TextView) mDayNamesHeader.getChildAt(i);
+            if (i < mDaysPerWeek + 1) {
+                label.setText(mDayLabels[i - 1]);
+                label.setVisibility(View.VISIBLE);
+            } else {
+                label.setVisibility(View.GONE);
+            }
+        }
+        mDayNamesHeader.invalidate();
+    }
+
+    /**
+     * This moves to the specified time in the view. If the time is not already
+     * in range it will move the list so that the first of the month containing
+     * the time is at the top of the view. If the new time is already in view
+     * the list will not be scrolled unless forceScroll is true. This time may
+     * optionally be highlighted as selected as well.
+     *
+     * @param year The year to move to.
+     * @param month The month to move to <strong>starting from zero<strong>.
+     * @param dayOfMonth The month day to move to.
+     * @param animate Whether to scroll to the given time or just redraw at the
+     *            new location.
+     * @param setSelected Whether to set the given time as selected
+     * @param forceScroll Whether to recenter even if the time is already
+     *            visible.
+     */
+    public void goTo(int year, int month, int dayOfMonth, boolean animate, boolean setSelected,
+            boolean forceScroll) {
+        mTempCalendar.clear();
+        mTempCalendar.set(year, month, dayOfMonth);
+        goTo(mTempCalendar, animate, setSelected, forceScroll);
+    }
+
+    /**
+     * This moves to the specified time in the view. If the time is not already
+     * in range it will move the list so that the first of the month containing
+     * the time is at the top of the view. If the new time is already in view
+     * the list will not be scrolled unless forceScroll is true. This time may
+     * optionally be highlighted as selected as well.
+     * 
+     * @param date The time to move to.
+     * @param animate Whether to scroll to the given time or just redraw at the
+     *            new location.
+     * @param setSelected Whether to set the given time as selected.
+     * @param forceScroll Whether to recenter even if the time is already
+     *            visible.
+     */
+    public void goTo(Calendar date, boolean animate, boolean setSelected, boolean forceScroll) {
+        long timeInMillis = date.getTimeInMillis();
+        if (timeInMillis < mStartRangeDate.getTimeInMillis()
+                || timeInMillis > mEndRangeDate.getTimeInMillis()) {
+            throw new IllegalArgumentException("Time not between " + mStartRangeDate.getTime()
+                    + " and " + mEndRangeDate.getTime());
+        }
+        // Find the first and last entirely visible weeks
+        int firstFullyVisiblePosition = mListView.getFirstVisiblePosition();
+        View firstChild = mListView.getChildAt(0);
+        if (firstChild != null && firstChild.getTop() < 0) {
+            firstFullyVisiblePosition++;
+        }
+        int lastFullyVisiblePosition = firstFullyVisiblePosition + mShownWeekCount - 1;
+        if (firstChild != null && firstChild.getTop() > mBottomBuffer) {
+            lastFullyVisiblePosition--;
+        }
+        if (setSelected) {
+            mAdapter.setSelectedDay(date);
+        }
+        // Get the week we're going to
+        int position = getWeeksDelta(date);
+
+        // Check if the selected day is now outside of our visible range
+        // and if so scroll to the month that contains it
+        if (position < firstFullyVisiblePosition || position > lastFullyVisiblePosition
+                || forceScroll) {
+            mFirstDayOfMonth.setTimeInMillis(date.getTimeInMillis());
+            mFirstDayOfMonth.setTimeZone(date.getTimeZone());
+            mFirstDayOfMonth.set(Calendar.DAY_OF_MONTH, 1);
+
+            setMonthDisplayed(mFirstDayOfMonth);
+            position = getWeeksDelta(mFirstDayOfMonth);
+
+            mPreviousScrollState = OnScrollListener.SCROLL_STATE_FLING;
+            if (animate) {
+                mListView.smoothScrollToPositionFromTop(position, mListTopOffset,
+                        GOTO_SCROLL_DURATION);
+            } else {
+                mListView.setSelectionFromTop(position, mListTopOffset);
+                // Perform any after scroll operations that are needed
+                onScrollStateChanged(mListView, OnScrollListener.SCROLL_STATE_IDLE);
+            }
+        } else if (setSelected) {
+            // Otherwise just set the selection
+            setMonthDisplayed(date);
+        }
+    }
+
+    /**
+     * Called when a <code>view</code> transitions to a new <code>scrollState
+     * </code>.
+     *
+     * @hide
+     */
+    protected void onScrollStateChanged(AbsListView view, int scrollState) {
+        mScrollStateChangedRunnable.doScrollStateChange(view, scrollState);
+    }
+
+    /**
+     * Updates the title and selected month if the <code>view</code> has moved to a new
+     * month.
+     *
+     * @hide
+     */
+    protected void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
+            int totalItemCount) {
+        WeekView child = (WeekView) view.getChildAt(0);
+        if (child == null) {
+            return;
+        }
+
+        // Figure out where we are
+        int offset = child.getBottom() < mWeekMinVisibleHeight ? 1 : 0;
+        long currScroll = view.getFirstVisiblePosition() * child.getHeight() - child.getBottom();
+
+        // If we have moved since our last call update the direction
+        if (currScroll < mPreviousScrollPosition) {
+            mIsScrollingUp = true;
+        } else if (currScroll > mPreviousScrollPosition) {
+            mIsScrollingUp = false;
+        } else {
+            return;
+        }
+
+        // Use some hysteresis for checking which month to highlight. This
+        // causes the month to transition when two full weeks of a month are
+        // visible when scrolling up, and when the first day in a month reaches
+        // the top of the screen when scrolling down.
+        if (mIsScrollingUp) {
+            child = (WeekView) view.getChildAt(SCROLL_HYST_WEEKS + offset);
+        } else if (offset != 0) {
+            child = (WeekView) view.getChildAt(offset);
+        }
+
+        // Find out which month we're moving into
+        int month;
+        if (mIsScrollingUp) {
+            month = child.getMonthOfFirstWeekDay();
+        } else {
+            month = child.getMonthOfLastWeekDay();
+        }
+
+        // And how it relates to our current highlighted month
+        int monthDiff;
+        if (mCurrentMonthDisplayed == 11 && month == 0) {
+            monthDiff = 1;
+        } else if (mCurrentMonthDisplayed == 0 && month == 11) {
+            monthDiff = -1;
+        } else {
+            monthDiff = month - mCurrentMonthDisplayed;
+        }
+
+        // Only switch months if we're scrolling away from the currently
+        // selected month
+        if ((!mIsScrollingUp && monthDiff > 0) || (mIsScrollingUp && monthDiff < 0)) {
+            Calendar firstDay = child.getFirstDay();
+            if (mIsScrollingUp) {
+                firstDay.add(Calendar.DAY_OF_MONTH, -DAYS_PER_WEEK);
+            } else {
+                firstDay.add(Calendar.DAY_OF_MONTH, DAYS_PER_WEEK);
+            }
+            setMonthDisplayed(firstDay);
+        }
+        mPreviousScrollPosition = currScroll;
+        mPreviousScrollState = mCurrentScrollState;
+    }
+
+    /**
+     * Sets the month displayed at the top of this view based on time. Override
+     * to add custom events when the title is changed.
+     *
+     * @param calendar A day in the new focus month.
+     *
+     * @hide
+     */
+    protected void setMonthDisplayed(Calendar calendar) {
+        mMonthName.setText(DateFormat.format(mMonthNameFormatSrting, calendar));
+        mMonthName.invalidate();
+        mCurrentMonthDisplayed = calendar.get(Calendar.MONTH);
+        mAdapter.setFocusMonth(mCurrentMonthDisplayed);
+        // TODO Send Accessibility Event
+    }
+
+    /**
+     * @return Returns the number of weeks between the current week day of the
+     *         <code>fromDate</code> and the first day of week of
+     *         <code>toDate</code>.
+     *
+     * @hide
+     */
+    protected int getWeeksDelta(Calendar toDate) {
+        if (toDate.before(mStartRangeDate)) {
+            throw new IllegalArgumentException("fromDate: " + mStartRangeDate.getTime()
+                    + " does not precede toDate: " + toDate.getTime());
+        }
+        int fromDateDayOfWeek = mStartRangeDate.get(Calendar.DAY_OF_WEEK);
+        long diff = (fromDateDayOfWeek - toDate.getFirstDayOfWeek()) * MILLIS_IN_DAY;
+        if (diff < 0) {
+            diff = diff + MILLIS_IN_WEEK;
+        }
+        long refDay = mStartRangeDate.getTimeInMillis() - diff;
+        return (int) ((toDate.getTimeInMillis() - refDay) / MILLIS_IN_WEEK);
+    }
+
+    /**
+     * Command responsible for acting upon scroll state changes.
+     *
+     * @hide
+     */
+    protected class ScrollStateRunnable implements Runnable {
+        private AbsListView mView;
+
+        private int mNewState;
+
+        /**
+         * Sets up the runnable with a short delay in case the scroll state
+         * immediately changes again.
+         *
+         * @param view The list view that changed state
+         * @param scrollState The new state it changed to
+         */
+        public void doScrollStateChange(AbsListView view, int scrollState) {
+            removeCallbacks(this);
+            mView = view;
+            mNewState = scrollState;
+            removeCallbacks(this);
+            postDelayed(this, SCROLL_CHANGE_DELAY);
+        }
+
+        public void run() {
+            mCurrentScrollState = mNewState;
+            // Fix the position after a scroll or a fling ends
+            if (mNewState == OnScrollListener.SCROLL_STATE_IDLE
+                    && mPreviousScrollState != OnScrollListener.SCROLL_STATE_IDLE) {
+                mPreviousScrollState = mNewState;
+                View child = mView.getChildAt(0);
+                if (child == null) {
+                    // The view is no longer visible, just return
+                    return;
+                }
+                int dist = child.getBottom() - mListTopOffset;
+                if (dist > mListTopOffset) {
+                    if (mIsScrollingUp) {
+                        mView.smoothScrollBy(dist - child.getHeight(), ADJUSTMENT_SCROLL_DURATION);
+                    } else {
+                        mView.smoothScrollBy(dist, ADJUSTMENT_SCROLL_DURATION);
+                    }
+                }
+            } else {
+                mPreviousScrollState = mNewState;
+            }
+        }
+    }
+
+    /**
+     * <p>
+     * This is a specialized adapter for creating a list of weeks with
+     * selectable days. It can be configured to display the week number, start
+     * the week on a given day, show a reduced number of days, or display an
+     * arbitrary number of weeks at a time.
+     * </p>
+     *
+     * @hide
+     */
+    public class WeeksAdapter extends BaseAdapter implements OnTouchListener {
+
+        /**
+         * The default maximum year supported by the Date Time Picker.
+         */
+        public static final int DEFAULT_MAX_CALENDAR_YEAR = 2100;
+
+        /**
+         * The default minimum year supported by the Date Time Picker.
+         */
+        public static final int DEFAULT_MIN_CALENDAR_YEAR = 1900;
+
+        /**
+         * The number of weeks to display at a time.
+         */
+        public static final String WEEK_PARAMS_NUM_WEEKS = "num_weeks";
+
+        /**
+         * Which month should be in focus currently.
+         */
+        public static final String WEEK_PARAMS_FOCUS_MONTH = "focus_month";
+
+        /**
+         * Whether the week number should be shown. Non-zero to show them.
+         */
+        public static final String WEEK_PARAMS_SHOW_WEEK = "week_numbers";
+
+        /**
+         * Which day the week should start on. {@link Time#SUNDAY} through
+         * {@link Time#SATURDAY}.
+         */
+        public static final String WEEK_PARAMS_WEEK_START = "week_start";
+
+        /**
+         * The year of the highlighted day.
+         */
+        public static final String WEEK_PARAMS_YEAR = "selected_year";
+
+        /**
+         * The month of the highlighted day.
+         */
+        public static final String WEEK_PARAMS_MONTH = "selected_month";
+
+        /**
+         * The year of the highlighted day.
+         */
+        public static final String WEEK_PARAMS_DAY_OF_MONTH = "selected_day_of_month";
+
+        /**
+         * The start date of the supported interval.
+         */
+        public static final String WEEK_PARAMS_START_DATE_RANGE_MILLIS = "start_date_gange_millis";
+
+        /**
+         * The end date of the supported interval.
+         */
+        public static final String WEEK_PARAMS_END_DATE_RANGE_MILLIS = "end_date_gange_millis";
+
+        /**
+         * How many days of the week to display [1-7].
+         */
+        public static final String WEEK_PARAMS_DAYS_PER_WEEK = "days_per_week";
+
+        protected int WEEK_7_OVERHANG_HEIGHT = 7;
+
+        protected int mSelectedWeek;
+
+        protected GestureDetector mGestureDetector;
+
+        protected int mFocusMonth = 0;
+
+        private final Calendar mSelectedDay = Calendar.getInstance();
+
+        private int mTotalWeekCount = -1;
+
+        public WeeksAdapter(Context context) {
+            mContext = context;
+
+            if (sScale == 0) {
+                sScale = context.getResources().getDisplayMetrics().density;
+                if (sScale != 1) {
+                    WEEK_7_OVERHANG_HEIGHT *= sScale;
+                }
+            }
+            init();
+        }
+
+        /**
+         * Set up the gesture detector and selected time
+         */
+        protected void init() {
+            mGestureDetector = new GestureDetector(mContext, new CalendarGestureListener());
+            mSelectedWeek = getWeeksDelta(mSelectedDay);
+            mTotalWeekCount = getWeeksDelta(mEndRangeDate);
+        }
+
+        /**
+         * Updates the selected day and related parameters.
+         * 
+         * @param selectedDay The time to highlight
+         */
+        public void setSelectedDay(Calendar selectedDay) {
+            if (selectedDay.get(Calendar.DAY_OF_YEAR) == mSelectedDay.get(Calendar.DAY_OF_YEAR)
+                    && selectedDay.get(Calendar.YEAR) == mSelectedDay.get(Calendar.YEAR)) {
+                return;
+            }
+            mSelectedDay.setTimeInMillis(selectedDay.getTimeInMillis());
+            mSelectedDay.setTimeZone(selectedDay.getTimeZone());
+            mSelectedWeek = getWeeksDelta(mSelectedDay);
+            mFocusMonth = mSelectedDay.get(Calendar.MONTH);
+            notifyDataSetChanged();
+            invalidate();  // Test
+        }
+
+        /**
+         * @return The selected day of month.
+         */
+        public Calendar getSelectedDay() {
+            return mSelectedDay;
+        }
+
+        /**
+         * updates any config options that may have changed and refreshes the
+         * view
+         */
+        public void refresh() {
+            notifyDataSetChanged();
+        }
+
+        @Override
+        public int getCount() {
+            return mTotalWeekCount;
+        }
+
+        @Override
+        public Object getItem(int position) {
+            return null;
+        }
+
+        @Override
+        public long getItemId(int position) {
+            return position;
+        }
+
+        @SuppressWarnings("unchecked")
+        @Override
+        public View getView(int position, View convertView, ViewGroup parent) {
+            WeekView v;
+            HashMap<String, Object> drawingParams = null;
+            if (convertView != null) {
+                v = (WeekView) convertView;
+                // We store the drawing parameters in the view so it can be
+                // recycled
+                drawingParams = (HashMap<String, Object>) v.getTag();
+            } else {
+                v = getNewView();
+                // Set up the new view
+                android.widget.AbsListView.LayoutParams params =
+                    new android.widget.AbsListView.LayoutParams(
+                        LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
+                v.setLayoutParams(params);
+                v.setClickable(true);
+                v.setOnTouchListener(this);
+
+                drawingParams = new HashMap<String, Object>();
+            }
+
+            // pass in all the view parameters
+            putDrawingParementer(drawingParams, WeekView.VIEW_PARAMS_SHOW_WK_NUM,
+                    mShowWeekNumber ? 1 : 0);
+            putDrawingParementer(drawingParams, WeekView.VIEW_PARAMS_WEEK_START, mFirstDayOfWeek);
+            putDrawingParementer(drawingParams, WeekView.VIEW_PARAMS_NUM_DAYS, mDaysPerWeek);
+            putDrawingParementer(drawingParams, WeekView.VIEW_PARAMS_WEEK, position);
+            putDrawingParementer(drawingParams, WeekView.VIEW_PARAMS_FOCUS_MONTH, mFocusMonth);
+            putDrawingParementer(drawingParams, WeekView.VIEW_PARAMS_SELECTED_DAY,
+                    (mSelectedWeek == position) ? mSelectedDay.get(Calendar.DAY_OF_WEEK) : -1);
+            v.setWeekParams(drawingParams);
+
+            return v;
+        }
+
+        /**
+         * Puts the given <code>value</code> for the drawing
+         * <code>parameter</code> in the <code>drawingParams</code>.
+         */
+        private void putDrawingParementer(HashMap<String, Object> drawingParams, String parameter,
+                int value) {
+            int[] valueArray = (int[]) drawingParams.get(parameter);
+            if (valueArray == null) {
+                valueArray = new int[1];
+                drawingParams.put(parameter, valueArray);
+            }
+            valueArray[0] = value;
+        }
+
+        /**
+         * Creates a new WeekView and returns it. Override this to customize the
+         * view creation.
+         *
+         * @return A new WeekView
+         */
+        protected WeekView getNewView() {
+            return new WeekView(mContext);
+        }
+
+        /**
+         * Changes which month is in focus and updates the view.
+         *
+         * @param month The month to show as in focus [0-11]
+         */
+        public void setFocusMonth(int month) {
+            if (mFocusMonth == month) {
+                return;
+            }
+            mFocusMonth = month;
+            notifyDataSetChanged();
+        }
+
+        @Override
+        public boolean onTouch(View v, MotionEvent event) {
+            if (mGestureDetector.onTouchEvent(event)) {
+                WeekView weekView = (WeekView) v;
+                weekView.getDayFromLocation(event.getX(), mTempCalendar);
+                if (mTempCalendar.get(Calendar.YEAR) != 0) {
+                    onDayTapped(mTempCalendar);
+                }
+                return true;
+            }
+            return false;
+        }
+
+        /**
+         * Maintains the same hour/min/sec but moves the day to the tapped day.
+         * 
+         * @param day The day that was tapped
+         */
+        protected void onDayTapped(Calendar day) {
+            setSelectedDay(day);
+        }
+
+        /**
+         * This is here so we can identify single tap events and set the
+         * selected day correctly
+         */
+        protected class CalendarGestureListener extends GestureDetector.SimpleOnGestureListener {
+            @Override
+            public boolean onSingleTapUp(MotionEvent e) {
+                return true;
+            }
+        }
+    }
+
+    /**
+     * <p>
+     * This is a dynamic view for drawing a single week. It can be configured to
+     * display the week number, start the week on a given day, or show a reduced
+     * number of days. It is intended for use as a single view within a
+     * ListView. See {@link WeeksAdapter} for usage.
+     * </p>
+     *
+     * @hide
+     */
+    public class WeekView extends View {
+
+        /*
+         * These params can be passed into the view to control how it appears.
+         * {@link #VIEW_PARAMS_WEEK} is the only required field, though the
+         * default values are unlikely to fit most layouts correctly.
+         */
+
+        /**
+         * This sets the height of this week in pixels
+         */
+        public static final String VIEW_PARAMS_HEIGHT = "height";
+
+        /**
+         * This specifies the position (or weeks since the epoch) of this week.
+         */
+        public static final String VIEW_PARAMS_WEEK = "week";
+
+        /**
+         * This sets one of the days in this view as selected
+         * {@link Time#SUNDAY} through {@link Time#SATURDAY}.
+         */
+        public static final String VIEW_PARAMS_SELECTED_DAY = "selected_day";
+
+        /**
+         * Which day the week should start on. {@link Time#SUNDAY} through
+         * {@link Time#SATURDAY}.
+         */
+        public static final String VIEW_PARAMS_WEEK_START = "week_start";
+
+        /**
+         * How many days to display at a time. Days will be displayed starting
+         * with {@link #mFirstDay}.
+         */
+        public static final String VIEW_PARAMS_NUM_DAYS = "num_days";
+
+        /**
+         * Which month is currently in focus, as defined by {@link Time#month}
+         * [0-11].
+         */
+        public static final String VIEW_PARAMS_FOCUS_MONTH = "focus_month";
+
+        /**
+         * If this month should display week numbers. false if 0, true
+         * otherwise.
+         */
+        public static final String VIEW_PARAMS_SHOW_WK_NUM = "show_wk_num";
+
+        protected int mDefaultHeight = 32;
+
+        protected int mMinHeight = 10;
+
+        protected static final int DEFAULT_SELECTED_DAY = -1;
+
+        protected static final int DEFAULT_WEEK_START = Calendar.SUNDAY;
+
+        protected static final int DEFAULT_NUM_DAYS = 7;
+
+        protected static final int DEFAULT_SHOW_WK_NUM = 0;
+
+        protected static final int DEFAULT_FOCUS_MONTH = -1;
+
+        protected static final int DAY_SEPARATOR_WIDTH = 1;
+
+        protected int mNumberTextSize = 14;
+
+        // affects the padding on the sides of this view
+        protected int mPadding = 0;
+
+        protected final Rect mTempRect = new Rect();
+
+        protected final Paint mDrawPaint = new Paint();
+
+        protected Paint mMonthNumDrawPaint = new Paint();
+
+        protected Drawable mSelectedDayLine;
+
+        protected final int mSelectionBackgroundColor;
+
+        protected final int mFocusedMonthDateColor;
+
+        protected final int mOtherMonthDateColor;
+
+        protected final int mGridLinesColor;
+
+        protected final int mWeekNumberColor;
+
+        // Cache the number strings so we don't have to recompute them each time
+        protected String[] mDayNumbers;
+
+        // Quick lookup for checking which days are in the focus month
+        protected boolean[] mFocusDay;
+
+        // The first day displayed by this item
+        protected Calendar mFirstDay;
+
+        // The month of the first day in this week
+        protected int mMonthOfFirstWeekDay = -1;
+
+        // The month of the last day in this week
+        protected int mLastWeekDayMonth = -1;
+
+        // The position of this week, equivalent to weeks since the week of Jan
+        // 1st, 1900
+        protected int mWeek = -1;
+
+        // Quick reference to the width of this view, matches parent
+        protected int mWidth;
+
+        // The height this view should draw at in pixels, set by height param
+        protected int mHeight = mDefaultHeight;
+
+        // Whether the week number should be shown
+        protected boolean mShowWeekNum = false;
+
+        // If this view contains the selected day
+        protected boolean mHasSelectedDay = false;
+
+        // Which day is selected [0-6] or -1 if no day is selected
+        protected int mSelectedDay = DEFAULT_SELECTED_DAY;
+
+        // How many days to display
+        protected int mNumDays = DEFAULT_NUM_DAYS;
+
+        // The number of days + a spot for week number if it is displayed
+        protected int mNumCells = mNumDays;
+
+        // The left edge of the selected day
+        protected int mSelectedLeft = -1;
+
+        // The right edge of the selected day
+        protected int mSelectedRight = -1;
+
+        public WeekView(Context context) {
+            super(context);
+
+            TypedValue outTypedValue = new TypedValue();
+            context.getTheme().resolveAttribute(R.attr.dayPickerWeekViewStyle, outTypedValue, true);
+            TypedArray attributesArray = context.obtainStyledAttributes(outTypedValue.resourceId,
+                    R.styleable.DayPickerWeekView);
+
+            mSelectionBackgroundColor = attributesArray.getColor(
+                    R.styleable.DayPickerWeekView_selectionBackgroundColor, 0);
+            mFocusedMonthDateColor = attributesArray.getColor(
+                    R.styleable.DayPickerWeekView_focusedMonthDateColor, 0);
+            mOtherMonthDateColor = attributesArray.getColor(
+                    R.styleable.DayPickerWeekView_otherMonthDateColor, 0);
+            mGridLinesColor = attributesArray.getColor(
+                    R.styleable.DayPickerWeekView_gridLinesColor, 0);
+            mWeekNumberColor = attributesArray.getColor(
+                    R.styleable.DayPickerWeekView_weekNumberColor, 0);
+            mSelectedDayLine = attributesArray
+                    .getDrawable(R.styleable.DayPickerWeekView_selectedDayLine);
+            attributesArray.recycle();
+
+            if (sScale == 0) {
+                sScale = context.getResources().getDisplayMetrics().density;
+                if (sScale != 1) {
+                    mDefaultHeight *= sScale;
+                    mMinHeight *= sScale;
+                    mNumberTextSize *= sScale;
+                }
+            }
+
+            // Sets up any standard paints that will be used
+            setPaintProperties();
+        }
+
+        /**
+         * Sets all the parameters for displaying this week. The only required
+         * parameter is the week number. Other parameters have a default value
+         * and will only update if a new value is included, except for focus
+         * month, which will always default to no focus month if no value is
+         * passed in. See {@link #VIEW_PARAMS_HEIGHT} for more info on
+         * parameters.
+         *
+         * @param params A map of the new parameters, see
+         *            {@link #VIEW_PARAMS_HEIGHT}
+         */
+        public void setWeekParams(HashMap<String, Object> params) {
+            if (!params.containsKey(VIEW_PARAMS_WEEK)) {
+                throw new InvalidParameterException(
+                        "You must specify the week number for this view");
+            }
+            setTag(params);
+            // We keep the current value for any params not present
+            if (params.containsKey(VIEW_PARAMS_HEIGHT)) {
+                mHeight = ((int[]) params.get(VIEW_PARAMS_HEIGHT))[0];
+                if (mHeight < mMinHeight) {
+                    mHeight = mMinHeight;
+                }
+            }
+            if (params.containsKey(VIEW_PARAMS_SELECTED_DAY)) {
+                mSelectedDay = ((int[]) params.get(VIEW_PARAMS_SELECTED_DAY))[0];
+            }
+            mHasSelectedDay = mSelectedDay != -1;
+            if (params.containsKey(VIEW_PARAMS_NUM_DAYS)) {
+                mNumDays = ((int[]) params.get(VIEW_PARAMS_NUM_DAYS))[0];
+            }
+            if (params.containsKey(VIEW_PARAMS_SHOW_WK_NUM)) {
+                if (((int[]) params.get(VIEW_PARAMS_SHOW_WK_NUM))[0] != 0) {
+                    mNumCells = mNumDays + 1;
+                    mShowWeekNum = true;
+                } else {
+                    mShowWeekNum = false;
+                }
+            } else {
+                mNumCells = mShowWeekNum ? mNumDays + 1 : mNumDays;
+            }
+            mWeek = ((int[]) params.get(VIEW_PARAMS_WEEK))[0];
+            mTempCalendar.clear();
+            mTempCalendar.set(1900, 0, 1);
+            mTempCalendar.add(Calendar.WEEK_OF_YEAR, mWeek);
+            if (params.containsKey(VIEW_PARAMS_WEEK_START)) {
+                mTempCalendar.setFirstDayOfWeek(((int[]) params.get(VIEW_PARAMS_WEEK_START))[0]);
+            } else {
+                mTempCalendar.setFirstDayOfWeek(DEFAULT_WEEK_START);
+            }
+
+            // Allocate space for caching the day numbers and focus values
+            mDayNumbers = new String[mNumCells];
+            mFocusDay = new boolean[mNumCells];
+
+            // If we're showing the week number calculate it based on Monday
+            int i = 0;
+            if (mShowWeekNum) {
+                mDayNumbers[0] = Integer.toString(mTempCalendar.get(Calendar.WEEK_OF_YEAR));
+                i++;
+            }
+
+            // Now adjust our starting day based on the start day of the week
+            int diff = mTempCalendar.getFirstDayOfWeek() - mTempCalendar.get(Calendar.DAY_OF_WEEK);
+            mTempCalendar.add(Calendar.DAY_OF_MONTH, diff);
+
+            mFirstDay = (Calendar) mTempCalendar.clone();
+
+            mMonthOfFirstWeekDay = mTempCalendar.get(Calendar.MONTH);
+
+            int focusMonth = params.containsKey(VIEW_PARAMS_FOCUS_MONTH) ? ((int[]) params
+                    .get(VIEW_PARAMS_FOCUS_MONTH))[0] : DEFAULT_FOCUS_MONTH;
+
+            for (; i < mNumCells; i++) {
+                mFocusDay[i] = (mTempCalendar.get(Calendar.MONTH) == focusMonth);
+                mDayNumbers[i] = Integer.toString(mTempCalendar.get(Calendar.DAY_OF_MONTH));
+                mTempCalendar.add(Calendar.DAY_OF_MONTH, 1);
+            }
+            // We do one extra add at the end of the loop, if that pushed us to
+            // new month undo it
+            if (mTempCalendar.get(Calendar.DAY_OF_MONTH) == 1) {
+                mTempCalendar.add(Calendar.DAY_OF_MONTH, -1);
+            }
+            mLastWeekDayMonth = mTempCalendar.get(Calendar.MONTH);
+
+            updateSelectionPositions();
+        }
+
+        /**
+         * Sets up the text and style properties for painting. Override this if
+         * you want to use a different paint.
+         */
+        protected void setPaintProperties() {
+            mDrawPaint.setFakeBoldText(false);
+            mDrawPaint.setAntiAlias(true);
+            mDrawPaint.setTextSize(mNumberTextSize);
+            mDrawPaint.setStyle(Style.FILL);
+
+            mMonthNumDrawPaint.setFakeBoldText(true);
+            mMonthNumDrawPaint.setAntiAlias(true);
+            mMonthNumDrawPaint.setTextSize(mNumberTextSize);
+            mMonthNumDrawPaint.setColor(mFocusedMonthDateColor);
+            mMonthNumDrawPaint.setStyle(Style.FILL);
+            mMonthNumDrawPaint.setTextAlign(Align.CENTER);
+        }
+
+        /**
+         * Returns the month of the first day in this week.
+         *
+         * @return The month the first day of this view is in.
+         */
+        public int getMonthOfFirstWeekDay() {
+            return mMonthOfFirstWeekDay;
+        }
+
+        /**
+         * Returns the month of the last day in this week
+         *
+         * @return The month the last day of this view is in
+         */
+        public int getMonthOfLastWeekDay() {
+            return mLastWeekDayMonth;
+        }
+
+        /**
+         * Returns the first day in this view.
+         *
+         * @return The first day in the view.
+         */
+        public Calendar getFirstDay() {
+            return mFirstDay;
+        }
+
+        /**
+         * Returns the number of days this view will display.
+         */
+        public int getNumDays() {
+            return mNumDays;
+        }
+
+        /**
+         * Calculates the day that the given x position is in, accounting for
+         * week number. Returns a Time referencing that day or null if
+         *
+         * @param x The x position of the touch eventy
+         */
+        public void getDayFromLocation(float x, Calendar outCalendar) {
+            int dayStart = mShowWeekNum ? (mWidth - mPadding * 2) / mNumCells + mPadding : mPadding;
+            if (x < dayStart || x > mWidth - mPadding) {
+                outCalendar.set(0, 0, 0, 0, 0, 0);
+                return;
+            }
+            // Selection is (x - start) / (pixels/day) == (x -s) * day / pixels
+            int dayPosition = (int) ((x - dayStart) * mNumDays / (mWidth - dayStart - mPadding));
+            outCalendar.setTimeZone(mFirstDay.getTimeZone());
+            outCalendar.setTimeInMillis(mFirstDay.getTimeInMillis());
+            outCalendar.add(Calendar.DAY_OF_MONTH, dayPosition);
+        }
+
+        @Override
+        protected void onDraw(Canvas canvas) {
+            drawBackground(canvas);
+            drawWeekNums(canvas);
+            drawDaySeparators(canvas);
+        }
+
+        /**
+         * This draws the selection highlight if a day is selected in this week.
+         * Override this method if you wish to have a different background
+         * drawn.
+         *
+         * @param canvas The canvas to draw on
+         */
+        protected void drawBackground(Canvas canvas) {
+            if (!mHasSelectedDay) {
+                return;
+            }
+            mDrawPaint.setColor(mSelectionBackgroundColor);
+
+            mTempRect.top = DAY_SEPARATOR_WIDTH;
+            mTempRect.bottom = mHeight;
+            mTempRect.left = mShowWeekNum ? mPadding + (mWidth - mPadding * 2) / mNumCells
+                    : mPadding;
+            mTempRect.right = mSelectedLeft - 2;
+            canvas.drawRect(mTempRect, mDrawPaint);
+
+            mTempRect.left = mSelectedRight + 3;
+            mTempRect.right = mWidth - mPadding;
+            canvas.drawRect(mTempRect, mDrawPaint);
+        }
+
+        /**
+         * Draws the week and month day numbers for this week. Override this
+         * method if you need different placement.
+         *
+         * @param canvas The canvas to draw on
+         */
+        protected void drawWeekNums(Canvas canvas) {
+            float textHeight = mDrawPaint.getTextSize();
+            int y = (int) ((mHeight + textHeight) / 2) - DAY_SEPARATOR_WIDTH;
+            int nDays = mNumCells;
+
+            mDrawPaint.setTextAlign(Align.CENTER);
+            int i = 0;
+            int divisor = 2 * nDays;
+            if (mShowWeekNum) {
+                mDrawPaint.setColor(mWeekNumberColor);
+                int x = (mWidth - mPadding * 2) / divisor + mPadding;
+                canvas.drawText(mDayNumbers[0], x, y, mDrawPaint);
+                i++;
+            }
+            for (; i < nDays; i++) {
+                mMonthNumDrawPaint.setColor(mFocusDay[i] ? mFocusedMonthDateColor
+                        : mOtherMonthDateColor);
+                int x = (2 * i + 1) * (mWidth - mPadding * 2) / divisor + mPadding;
+                canvas.drawText(mDayNumbers[i], x, y, mMonthNumDrawPaint);
+            }
+        }
+
+        /**
+         * Draws a horizontal line for separating the weeks. Override this
+         * method if you want custom separators.
+         *
+         * @param canvas The canvas to draw on
+         */
+        protected void drawDaySeparators(Canvas canvas) {
+            mDrawPaint.setColor(mGridLinesColor);
+            mDrawPaint.setStrokeWidth(DAY_SEPARATOR_WIDTH);
+            float x = mShowWeekNum ? mPadding + (mWidth - mPadding * 2) / mNumCells : mPadding;
+            canvas.drawLine(x, 0, mWidth - mPadding, 0, mDrawPaint);
+
+            if (mHasSelectedDay) {
+                mSelectedDayLine.setBounds(mSelectedLeft - 2, DAY_SEPARATOR_WIDTH,
+                        mSelectedLeft + 4, mHeight + 1);
+                mSelectedDayLine.draw(canvas);
+                mSelectedDayLine.setBounds(mSelectedRight - 3, DAY_SEPARATOR_WIDTH,
+                        mSelectedRight + 3, mHeight + 1);
+                mSelectedDayLine.draw(canvas);
+            }
+        }
+
+        @Override
+        protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+            mWidth = w;
+            updateSelectionPositions();
+        }
+
+        /**
+         * This calculates the positions for the selected day lines.
+         */
+        protected void updateSelectionPositions() {
+            if (mHasSelectedDay) {
+                int selectedPosition = mSelectedDay - mTempCalendar.getFirstDayOfWeek();
+                if (selectedPosition < 0) {
+                    selectedPosition += 7;
+                }
+                if (mShowWeekNum) {
+                    selectedPosition++;
+                }
+                mSelectedLeft = selectedPosition * (mWidth - mPadding * 2) / mNumCells + mPadding;
+                mSelectedRight = (selectedPosition + 1) * (mWidth - mPadding * 2) / mNumCells
+                        + mPadding;
+            }
+        }
+
+        @Override
+        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+            setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), mHeight);
+        }
+    }
+}
diff --git a/core/java/android/widget/FrameLayout.java b/core/java/android/widget/FrameLayout.java
index 940fec1..26e191d 100644
--- a/core/java/android/widget/FrameLayout.java
+++ b/core/java/android/widget/FrameLayout.java
@@ -76,6 +76,8 @@
 
     boolean mForegroundBoundsChanged = false;
     
+    private static final int DEFAULT_CHILD_GRAVITY = Gravity.TOP | Gravity.LEFT;
+
     public FrameLayout(Context context) {
         super(context);
     }
@@ -307,41 +309,42 @@
                 int childLeft = parentLeft;
                 int childTop = parentTop;
 
-                final int gravity = lp.gravity;
+                int gravity = lp.gravity;
+                if (gravity == -1) {
+                    gravity = DEFAULT_CHILD_GRAVITY;
+                }
 
-                if (gravity != -1) {
-                    final int horizontalGravity = gravity & Gravity.HORIZONTAL_GRAVITY_MASK;
-                    final int verticalGravity = gravity & Gravity.VERTICAL_GRAVITY_MASK;
+                final int horizontalGravity = gravity & Gravity.HORIZONTAL_GRAVITY_MASK;
+                final int verticalGravity = gravity & Gravity.VERTICAL_GRAVITY_MASK;
 
-                    switch (horizontalGravity) {
-                        case Gravity.LEFT:
-                            childLeft = parentLeft + lp.leftMargin;
-                            break;
-                        case Gravity.CENTER_HORIZONTAL:
-                            childLeft = parentLeft + (parentRight - parentLeft - width) / 2 +
-                                    lp.leftMargin - lp.rightMargin;
-                            break;
-                        case Gravity.RIGHT:
-                            childLeft = parentRight - width - lp.rightMargin;
-                            break;
-                        default:
-                            childLeft = parentLeft + lp.leftMargin;
-                    }
+                switch (horizontalGravity) {
+                    case Gravity.LEFT:
+                        childLeft = parentLeft + lp.leftMargin;
+                        break;
+                    case Gravity.CENTER_HORIZONTAL:
+                        childLeft = parentLeft + (parentRight - parentLeft - width) / 2 +
+                        lp.leftMargin - lp.rightMargin;
+                        break;
+                    case Gravity.RIGHT:
+                        childLeft = parentRight - width - lp.rightMargin;
+                        break;
+                    default:
+                        childLeft = parentLeft + lp.leftMargin;
+                }
 
-                    switch (verticalGravity) {
-                        case Gravity.TOP:
-                            childTop = parentTop + lp.topMargin;
-                            break;
-                        case Gravity.CENTER_VERTICAL:
-                            childTop = parentTop + (parentBottom - parentTop - height) / 2 +
-                                    lp.topMargin - lp.bottomMargin;
-                            break;
-                        case Gravity.BOTTOM:
-                            childTop = parentBottom - height - lp.bottomMargin;
-                            break;
-                        default:
-                            childTop = parentTop + lp.topMargin;
-                    }
+                switch (verticalGravity) {
+                    case Gravity.TOP:
+                        childTop = parentTop + lp.topMargin;
+                        break;
+                    case Gravity.CENTER_VERTICAL:
+                        childTop = parentTop + (parentBottom - parentTop - height) / 2 +
+                        lp.topMargin - lp.bottomMargin;
+                        break;
+                    case Gravity.BOTTOM:
+                        childTop = parentBottom - height - lp.bottomMargin;
+                        break;
+                    default:
+                        childTop = parentTop + lp.topMargin;
                 }
 
                 child.layout(childLeft, childTop, childLeft + width, childTop + height);
diff --git a/core/java/android/widget/HorizontalScrollView.java b/core/java/android/widget/HorizontalScrollView.java
index c05e3ad..50867b9 100644
--- a/core/java/android/widget/HorizontalScrollView.java
+++ b/core/java/android/widget/HorizontalScrollView.java
@@ -1420,8 +1420,8 @@
                 final int height = getHeight();
 
                 canvas.rotate(270);
-                canvas.translate(-height * 1.5f, Math.min(0, scrollX));
-                mEdgeGlowLeft.setSize(getHeight() * 2, getWidth());
+                canvas.translate(-height, Math.min(0, scrollX));
+                mEdgeGlowLeft.setSize(getHeight(), getWidth());
                 if (mEdgeGlowLeft.draw(canvas)) {
                     invalidate();
                 }
@@ -1433,8 +1433,9 @@
                 final int height = getHeight();
 
                 canvas.rotate(90);
-                canvas.translate(-height / 2, -(Math.max(getScrollRange(), scrollX) + width));
-                mEdgeGlowRight.setSize(height * 2, width);
+                canvas.translate(0,
+                        -(Math.max(getScrollRange(), scrollX) + width));
+                mEdgeGlowRight.setSize(height, width);
                 if (mEdgeGlowRight.draw(canvas)) {
                     invalidate();
                 }
diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java
index 43d194f..805bc08 100644
--- a/core/java/android/widget/NumberPicker.java
+++ b/core/java/android/widget/NumberPicker.java
@@ -30,8 +30,8 @@
 import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.Paint;
-import android.graphics.Rect;
 import android.graphics.Paint.Align;
+import android.graphics.Rect;
 import android.text.InputFilter;
 import android.text.InputType;
 import android.text.Spanned;
@@ -41,19 +41,27 @@
 import android.util.SparseArray;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
+import android.view.LayoutInflater.Filter;
 import android.view.MotionEvent;
 import android.view.VelocityTracker;
 import android.view.View;
 import android.view.ViewConfiguration;
-import android.view.LayoutInflater.Filter;
 import android.view.animation.OvershootInterpolator;
 import android.view.inputmethod.InputMethodManager;
 
 /**
- * A view for selecting a number For a dialog using this view, see
- * {@link android.app.TimePickerDialog}.
- *
- * @hide
+ * A widget that enables the user to select a number form a predefined range.
+ * The widget presents an input filed and up and down buttons for selecting the
+ * current value. Pressing/long pressing the up and down buttons increments and
+ * decrements the current value respectively. Touching the input filed shows a
+ * scroll wheel, tapping on which while shown and not moving allows direct edit
+ * of the current value. Sliding motions up or down hide the buttons and the
+ * input filed, show the scroll wheel, and rotate the latter. Flinging is
+ * also supported. The widget enables mapping from positions to strings such
+ * that instead the position index the corresponding string is displayed.
+ * <p>
+ * For an example of using this widget, see {@link android.widget.TimePicker}.
+ * </p>
  */
 @Widget
 public class NumberPicker extends LinearLayout {
@@ -166,7 +174,12 @@
     /**
      * Listener to be notified upon current value change.
      */
-    private OnChangedListener mListener;
+    private OnChangeListener mOnChangeListener;
+
+    /**
+     * Listener to be notified upon scroll state change.
+     */
+    private OnScrollListener mOnScrollListener;
 
     /**
      * Formatter for for displaying the current value.
@@ -176,7 +189,7 @@
     /**
      * The speed for updating the value form long press.
      */
-    private long mLongPressUpdateSpeed = 300;
+    private long mLongPressUpdateInterval = 300;
 
     /**
      * Cache for the string representation of selector indices.
@@ -308,26 +321,79 @@
     private final Rect mTempRect = new Rect();
 
     /**
+     * The current scroll state of the number picker.
+     */
+    private int mScrollState = OnScrollListener.SCROLL_STATE_IDLE;
+
+    /**
      * The callback interface used to indicate the number value has changed.
      */
-    public interface OnChangedListener {
+    public interface OnChangeListener {
         /**
+         * Called upon a change of the current value.
+         *
          * @param picker The NumberPicker associated with this listener.
          * @param oldVal The previous value.
          * @param newVal The new value.
          */
-        void onChanged(NumberPicker picker, int oldVal, int newVal);
+        void onChange(NumberPicker picker, int oldVal, int newVal);
     }
 
     /**
-     * Interface used to format the number into a string for presentation
+     * Interface for listening to the picker scroll state.
+     */
+    public interface OnScrollListener {
+
+        /**
+         * The view is not scrolling.
+         */
+        public static int SCROLL_STATE_IDLE = 0;
+
+        /**
+         * The user is scrolling using touch, and their finger is still on the screen.
+         */
+        public static int SCROLL_STATE_TOUCH_SCROLL = 1;
+
+        /**
+         * The user had previously been scrolling using touch and performed a fling.
+         */
+        public static int SCROLL_STATE_FLING = 2;
+
+        /**
+         * Callback method to be invoked while the number picker is being scrolled.
+         *
+         * @param view The view whose scroll state is being reported
+         * @param scrollState The current scroll state. One of {@link #SCROLL_STATE_IDLE},
+         * {@link #SCROLL_STATE_TOUCH_SCROLL} or {@link #SCROLL_STATE_IDLE}.
+         */
+        public void onScrollStateChange(NumberPicker view, int scrollState);
+    }
+
+    /**
+     * Interface used to format the number into a string for presentation.
      */
     public interface Formatter {
-        String toString(int value);
+
+        /**
+         * Formats a string representation of the current index.
+         *
+         * @param value The currently selected value.
+         * @return A formatted string representation.
+         */
+        public String toString(int value);
     }
 
     /**
-     * Create a new number picker
+     * Create a new number picker.
+     *
+     * @param context The application environment.
+     */
+    public NumberPicker(Context context) {
+        this(context, null);
+    }
+
+    /**
+     * Create a new number picker.
      *
      * @param context The application environment.
      * @param attrs A collection of attributes.
@@ -492,11 +558,15 @@
                 mBeginEditOnUpEvent = false;
                 mAdjustScrollerOnUpEvent = true;
                 if (mDrawSelectorWheel) {
-                    mBeginEditOnUpEvent = mFlingScroller.isFinished()
+                    boolean scrollersFinished = mFlingScroller.isFinished()
                             && mAdjustScroller.isFinished();
+                    if (!scrollersFinished) {
+                        mFlingScroller.forceFinished(true);
+                        mAdjustScroller.forceFinished(true);
+                        tryNotifyScrollListener(OnScrollListener.SCROLL_STATE_IDLE);
+                    }
+                    mBeginEditOnUpEvent = scrollersFinished;
                     mAdjustScrollerOnUpEvent = true;
-                    mFlingScroller.forceFinished(true);
-                    mAdjustScroller.forceFinished(true);
                     hideInputControls();
                     return true;
                 }
@@ -512,6 +582,7 @@
                 int deltaDownY = (int) Math.abs(currentMoveY - mLastDownEventY);
                 if (deltaDownY > mTouchSlop) {
                     mBeginEditOnUpEvent = false;
+                    tryNotifyScrollListener(OnScrollListener.SCROLL_STATE_TOUCH_SCROLL);
                     setDrawSelectorWheel(true);
                     hideInputControls();
                     return true;
@@ -531,10 +602,12 @@
         switch (action) {
             case MotionEvent.ACTION_MOVE:
                 float currentMoveY = ev.getY();
-                if (mBeginEditOnUpEvent) {
+                if (mBeginEditOnUpEvent
+                        || mScrollState != OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) {
                     int deltaDownY = (int) Math.abs(currentMoveY - mLastDownEventY);
                     if (deltaDownY > mTouchSlop) {
                         mBeginEditOnUpEvent = false;
+                        tryNotifyScrollListener(OnScrollListener.SCROLL_STATE_TOUCH_SCROLL);
                     }
                 }
                 int deltaMoveY = (int) (currentMoveY - mLastMotionEventY);
@@ -550,6 +623,7 @@
                     InputMethodManager imm = (InputMethodManager) getContext().getSystemService(
                             Context.INPUT_METHOD_SERVICE);
                     imm.showSoftInput(mInputText, 0);
+                    mInputText.setSelection(0, mInputText.getText().length());
                     return true;
                 }
                 VelocityTracker velocityTracker = mVelocityTracker;
@@ -557,6 +631,7 @@
                 int initialVelocity = (int) velocityTracker.getYVelocity();
                 if (Math.abs(initialVelocity) > mMinimumFlingVelocity) {
                     fling(initialVelocity);
+                    tryNotifyScrollListener(OnScrollListener.SCROLL_STATE_FLING);
                 } else {
                     if (mAdjustScrollerOnUpEvent) {
                         if (mFlingScroller.isFinished() && mAdjustScroller.isFinished()) {
@@ -686,20 +761,40 @@
         }
     }
 
-    /**
-     * Set the callback that indicates the number has been adjusted by the user.
-     *
-     * @param listener the callback, should not be null.
-     */
-    public void setOnChangeListener(OnChangedListener listener) {
-        mListener = listener;
+    @Override
+    public int getSolidColor() {
+        return mSolidColor;
     }
 
     /**
-     * Set the formatter that will be used to format the number for presentation
+     * Sets the listener to be notified on change of the current value.
+     *
+     * @param onChangeListener The listener.
+     */
+    public void setOnChangeListener(OnChangeListener onChangeListener) {
+        mOnChangeListener = onChangeListener;
+    }
+
+    /**
+     * Set listener to be notified for scroll state changes.
+     *
+     * @param onScrollListener the callback, should not be null.
+     */
+    public void setOnScrollListener(OnScrollListener onScrollListener) {
+        mOnScrollListener = onScrollListener;
+    }
+
+    /**
+     * Set the formatter to be used for formatting the current value.
+     * <p>
+     * Note: If you have provided alternative values for the selected positons
+     *       this formatter is never invoked.
+     * </p>
      *
      * @param formatter the formatter object. If formatter is null,
-     *            String.valueOf() will be used
+     *            String.valueOf() will be used.
+     *
+     * @see #setRange(int, int, String[])
      */
     public void setFormatter(Formatter formatter) {
         mFormatter = formatter;
@@ -719,11 +814,11 @@
     /**
      * Set the range of numbers allowed for the number picker. The current value
      * will be automatically set to the start. Also provide a mapping for values
-     * used to display to the user.
+     * used to display to the user instead of the numbers in the range.
      *
-     * @param start the start of the range (inclusive)
-     * @param end the end of the range (inclusive)
-     * @param displayedValues the values displayed to the user.
+     * @param start The start of the range (inclusive).
+     * @param end The end of the range (inclusive).
+     * @param displayedValues The values displayed to the user.
      */
     public void setRange(int start, int end, String[] displayedValues) {
         boolean wrapSelector = (end - start) >= mSelectorIndices.length;
@@ -734,12 +829,20 @@
      * Set the range of numbers allowed for the number picker. The current value
      * will be automatically set to the start. Also provide a mapping for values
      * used to display to the user.
+     * <p>
+     * Note: The <code>wrapSelectorWheel</code> argument is ignored if the range
+     * (difference between <code>start</code> and <code>end</code>) us less than
+     * five since this is the number of values shown by the selector wheel.
+     * </p>
      *
      * @param start the start of the range (inclusive)
      * @param end the end of the range (inclusive)
      * @param displayedValues the values displayed to the user.
+     * @param wrapSelectorWheel Whether to wrap the selector wheel.
+     *
+     * @see #setWrapSelectorWheel(boolean)
      */
-    public void setRange(int start, int end, String[] displayedValues, boolean wrapSelector) {
+    public void setRange(int start, int end, String[] displayedValues, boolean wrapSelectorWheel) {
         if (start < 0 || end < 0) {
             throw new IllegalArgumentException("start and end must be > 0");
         }
@@ -749,7 +852,7 @@
         mEnd = end;
         mCurrent = start;
 
-        setWrapSelector(wrapSelector);
+        setWrapSelectorWheel(wrapSelectorWheel);
         updateInputTextView();
 
         if (displayedValues != null) {
@@ -768,8 +871,9 @@
      * Set the current value for the number picker.
      *
      * @param current the current value the start of the range (inclusive)
+     *
      * @throws IllegalArgumentException when current is not within the range of
-     *             of the number picker
+     *             of the number picker.
      */
     public void setCurrent(int current) {
         if (current < mStart || current > mEnd) {
@@ -781,12 +885,14 @@
     }
 
     /**
-     * Sets whether the selector shown during flinging/scrolling should wrap
-     * around the beginning and end values.
+     * Sets whether the selector wheel shown during flinging/scrolling should wrap
+     * around the beginning and end values. By default if the range is more than
+     * five (the number of items shown on the selector wheel) the selector wheel
+     * wrapping is enabled.
      *
      * @param wrapSelector Whether to wrap.
      */
-    public void setWrapSelector(boolean wrapSelector) {
+    public void setWrapSelectorWheel(boolean wrapSelector) {
         if (wrapSelector && (mEnd - mStart) < mSelectorIndices.length) {
             throw new IllegalStateException("Range less than selector items count.");
         }
@@ -798,18 +904,18 @@
     }
 
     /**
-     * Sets the speed at which the numbers will scroll when the +/- buttons are
-     * longpressed
+     * Sets the speed at which the numbers be incremented and decremented when
+     * the up and down buttons are long pressed respectively.
      *
-     * @param speed The speed (in milliseconds) at which the numbers will scroll
-     *            default 300ms
+     * @param intervalMillis The speed (in milliseconds) at which the numbers
+     *            will be incremented and decremented (default 300ms).
      */
-    public void setSpeed(long speed) {
-        mLongPressUpdateSpeed = speed;
+    public void setOnLongPressUpdateInterval(long intervalMillis) {
+        mLongPressUpdateInterval = intervalMillis;
     }
 
     /**
-     * Returns the current value of the NumberPicker
+     * Returns the current value of the NumberPicker.
      *
      * @return the current value.
      */
@@ -817,9 +923,22 @@
         return mCurrent;
     }
 
-    @Override
-    public int getSolidColor() {
-        return mSolidColor;
+    /**
+     * Returns the range lower value of the NumberPicker.
+     *
+     * @return The lower number of the range.
+     */
+    public int getRangeStart() {
+        return mStart;
+    }
+
+    /**
+     * Returns the range end value of the NumberPicker.
+     *
+     * @return The upper number of the range.
+     */
+    public int getRangeEnd() {
+        return mEnd;
     }
 
     @Override
@@ -892,24 +1011,6 @@
     }
 
     /**
-     * Returns the upper value of the range of the NumberPicker
-     *
-     * @return the uppper number of the range.
-     */
-    protected int getEndRange() {
-        return mEnd;
-    }
-
-    /**
-     * Returns the lower value of the range of the NumberPicker
-     *
-     * @return the lower number of the range.
-     */
-    protected int getBeginRange() {
-        return mStart;
-    }
-
-    /**
      * Sets the current value of this NumberPicker, and sets mPrevious to the
      * previous value. If current is greater than mEnd less than mStart, the
      * value of mCurrent is wrapped around. Subclasses can override this to
@@ -966,6 +1067,7 @@
     private void onScrollerFinished(Scroller scroller) {
         if (scroller == mFlingScroller) {
             postAdjustScrollerCommand(0);
+            tryNotifyScrollListener(OnScrollListener.SCROLL_STATE_IDLE);
         } else {
             showInputControls();
             updateInputTextView();
@@ -973,6 +1075,17 @@
     }
 
     /**
+     * Notifies the scroll listener for the given <code>scrollState</code>
+     * if the scroll state differs from the current scroll state.
+     */
+    private void tryNotifyScrollListener(int scrollState) {
+        if (mOnScrollListener != null && mScrollState != scrollState) {
+            mScrollState = scrollState;
+            mOnScrollListener.onScrollStateChange(this, scrollState);
+        }
+    }
+
+    /**
      * Flings the selector with the given <code>velocityY</code>.
      */
     private void fling(int velocityY) {
@@ -1118,7 +1231,8 @@
             scrollSelectorValue = "";
         } else {
             if (mDisplayedValues != null) {
-                scrollSelectorValue = mDisplayedValues[selectorIndex];
+                int displayedValueIndex = selectorIndex - mStart;
+                scrollSelectorValue = mDisplayedValues[displayedValueIndex];
             } else {
                 scrollSelectorValue = formatNumber(selectorIndex);
             }
@@ -1167,8 +1281,8 @@
      * NumberPicker.
      */
     private void notifyChange(int previous, int current) {
-        if (mListener != null) {
-            mListener.onChanged(this, previous, mCurrent);
+        if (mOnChangeListener != null) {
+            mOnChangeListener.onChange(this, previous, mCurrent);
         }
     }
 
@@ -1368,7 +1482,7 @@
 
         public void run() {
             changeCurrent(mCurrent + mUpdateStep);
-            postDelayed(this, mLongPressUpdateSpeed);
+            postDelayed(this, mLongPressUpdateInterval);
         }
     }
 }
diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java
index 9fa90dc..f25edd8 100644
--- a/core/java/android/widget/ScrollView.java
+++ b/core/java/android/widget/ScrollView.java
@@ -1467,8 +1467,8 @@
                 final int restoreCount = canvas.save();
                 final int width = getWidth();
 
-                canvas.translate(-width / 2, Math.min(0, scrollY));
-                mEdgeGlowTop.setSize(width * 2, getHeight());
+                canvas.translate(0, Math.min(0, scrollY));
+                mEdgeGlowTop.setSize(width, getHeight());
                 if (mEdgeGlowTop.draw(canvas)) {
                     invalidate();
                 }
@@ -1479,9 +1479,9 @@
                 final int width = getWidth();
                 final int height = getHeight();
 
-                canvas.translate(-width / 2, Math.max(getScrollRange(), scrollY) + height);
+                canvas.translate(-width, Math.max(getScrollRange(), scrollY) + height);
                 canvas.rotate(180, width, 0);
-                mEdgeGlowBottom.setSize(width * 2, height);
+                mEdgeGlowBottom.setSize(width, height);
                 if (mEdgeGlowBottom.draw(canvas)) {
                     invalidate();
                 }
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index a86610dd..144cf9c 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -3933,6 +3933,9 @@
             hideError();
         }
 
+        if (mBlink != null) {
+            mBlink.cancel();
+        }
         hideControllers();
     }
 
@@ -6282,11 +6285,7 @@
         mCursorVisible = visible;
         invalidate();
 
-        if (visible) {
-            makeBlink();
-        } else if (mBlink != null) {
-            mBlink.removeCallbacks(mBlink);
-        }
+        makeBlink();
 
         // InsertionPointCursorController depends on mCursorVisible
         prepareCursorControllers();
@@ -6782,7 +6781,7 @@
     }
 
     private void makeBlink() {
-        if (!mCursorVisible) {
+        if (!mCursorVisible || !isTextEditable()) {
             if (mBlink != null) {
                 mBlink.removeCallbacks(mBlink);
             }
@@ -7134,6 +7133,7 @@
                 mLayout != null;
 
         if (!mInsertionControllerEnabled) {
+            hideInsertionPointCursorController();
             mInsertionPointCursorController = null;
         }
 
@@ -7388,14 +7388,14 @@
     }
 
     private boolean canSelectText() {
-        return textCanBeSelected() && mText.length() != 0;
+        return hasSelectionController() && mText.length() != 0;
     }
 
     private boolean textCanBeSelected() {
         // prepareCursorController() relies on this method.
         // If you change this condition, make sure prepareCursorController is called anywhere
         // the value of this condition might be changed.
-        return (mText instanceof Spannable && mMovement != null && mMovement.canSelectArbitrarily());
+        return mText instanceof Spannable && mMovement != null && mMovement.canSelectArbitrarily();
     }
 
     private boolean canCut() {
@@ -7529,6 +7529,10 @@
     }
 
     private void selectCurrentWord() {
+        if (!canSelectText()) {
+            return;
+        }
+
         if (hasPasswordTransformationMethod()) {
             // selectCurrentWord is not available on a password field and would return an
             // arbitrary 10-charater selection around pressed position. Select all instead.
@@ -7544,7 +7548,6 @@
             minOffset = getSelectionStart();
             maxOffset = getSelectionEnd();
         } else {
-            // selectionModifierCursorController is guaranteed to exist at that point
             SelectionModifierCursorController selectionController = getSelectionController();
             minOffset = selectionController.getMinTouchOffset();
             maxOffset = selectionController.getMaxTouchOffset();
@@ -7921,12 +7924,8 @@
 
         selectCurrentWord();
         ActionMode.Callback actionModeCallback = new SelectionActionModeCallback();
-        if (actionModeCallback != null) {
-            mSelectionActionMode = startActionMode(actionModeCallback);
-            return mSelectionActionMode != null;
-        }
-
-        return false;
+        mSelectionActionMode = startActionMode(actionModeCallback);
+        return mSelectionActionMode != null;
     }
 
     /**
diff --git a/core/java/android/widget/TimePicker.java b/core/java/android/widget/TimePicker.java
index 6cf1387..203b637 100644
--- a/core/java/android/widget/TimePicker.java
+++ b/core/java/android/widget/TimePicker.java
@@ -25,7 +25,7 @@
 import android.util.AttributeSet;
 import android.view.LayoutInflater;
 import android.view.View;
-import android.widget.NumberPicker.OnChangedListener;
+import android.widget.NumberPicker.OnChangeListener;
 
 import java.text.DateFormatSymbols;
 import java.util.Calendar;
@@ -110,8 +110,8 @@
 
         // hour
         mHourPicker = (NumberPicker) findViewById(R.id.hour);
-        mHourPicker.setOnChangeListener(new NumberPicker.OnChangedListener() {
-            public void onChanged(NumberPicker spinner, int oldVal, int newVal) {
+        mHourPicker.setOnChangeListener(new NumberPicker.OnChangeListener() {
+            public void onChange(NumberPicker spinner, int oldVal, int newVal) {
                 mCurrentHour = newVal;
                 if (!mIs24HourView) {
                     // adjust from [1-12] to [0-11] internally, with the times
@@ -135,10 +135,10 @@
         // digits of minute
         mMinutePicker = (NumberPicker) findViewById(R.id.minute);
         mMinutePicker.setRange(0, 59);
-        mMinutePicker.setSpeed(100);
+        mMinutePicker.setOnLongPressUpdateInterval(100);
         mMinutePicker.setFormatter(NumberPicker.TWO_DIGIT_FORMATTER);
-        mMinutePicker.setOnChangeListener(new NumberPicker.OnChangedListener() {
-            public void onChanged(NumberPicker spinner, int oldVal, int newVal) {
+        mMinutePicker.setOnChangeListener(new NumberPicker.OnChangeListener() {
+            public void onChange(NumberPicker spinner, int oldVal, int newVal) {
                 mCurrentMinute = newVal;
                 onTimeChanged();
             }
@@ -146,8 +146,8 @@
 
         // am/pm
         mAmPmPicker = (NumberPicker) findViewById(R.id.amPm);
-        mAmPmPicker.setOnChangeListener(new OnChangedListener() {
-            public void onChanged(NumberPicker picker, int oldVal, int newVal) {
+        mAmPmPicker.setOnChangeListener(new OnChangeListener() {
+            public void onChange(NumberPicker picker, int oldVal, int newVal) {
                 picker.requestFocus();
                 if (mIsAm) {
                     // Currently AM switching to PM
@@ -184,7 +184,7 @@
             setEnabled(false);
         }
     }
-    
+
     @Override
     public void setEnabled(boolean enabled) {
         super.setEnabled(enabled);
diff --git a/core/java/com/android/internal/app/ActionBarImpl.java b/core/java/com/android/internal/app/ActionBarImpl.java
index ce7ab84..3e19811 100644
--- a/core/java/com/android/internal/app/ActionBarImpl.java
+++ b/core/java/com/android/internal/app/ActionBarImpl.java
@@ -23,9 +23,9 @@
 import com.android.internal.widget.ActionBarView;
 
 import android.animation.Animator;
-import android.animation.ObjectAnimator;
 import android.animation.Animator.AnimatorListener;
 import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
 import android.app.ActionBar;
 import android.app.Activity;
 import android.app.Dialog;
@@ -40,10 +40,10 @@
 import android.view.MenuInflater;
 import android.view.MenuItem;
 import android.view.View;
+import android.view.Window;
 import android.widget.FrameLayout;
 import android.widget.LinearLayout;
 import android.widget.SpinnerAdapter;
-import android.widget.ViewAnimator;
 
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
@@ -67,6 +67,7 @@
     private ActionBarView mActionView;
     private ActionBarContextView mUpperContextView;
     private LinearLayout mLowerContextView;
+    private View mContentView;
 
     private ArrayList<TabImpl> mTabs = new ArrayList<TabImpl>();
 
@@ -88,7 +89,7 @@
 
     final Handler mHandler = new Handler();
 
-    private Animator mCurrentAnimation;
+    private Animator mCurrentAnim;
 
     final AnimatorListener[] mAfterAnimation = new AnimatorListener[] {
             new AnimatorListener() { // NORMAL_VIEW
@@ -101,7 +102,7 @@
                     if (mLowerContextView != null) {
                         mLowerContextView.removeAllViews();
                     }
-                    mCurrentAnimation = null;
+                    mCurrentAnim = null;
                     hideAllExcept(NORMAL_VIEW);
                 }
 
@@ -120,7 +121,7 @@
 
                 @Override
                 public void onAnimationEnd(Animator animation) {
-                    mCurrentAnimation = null;
+                    mCurrentAnim = null;
                     hideAllExcept(CONTEXT_VIEW);
                 }
 
@@ -134,9 +135,56 @@
             }
     };
 
+    final AnimatorListener mHideListener = new AnimatorListener() {
+        @Override
+        public void onAnimationStart(Animator animation) {
+        }
+
+        @Override
+        public void onAnimationEnd(Animator animation) {
+            if (mContentView != null) {
+                mContentView.setTranslationY(0);
+            }
+            mContainerView.setVisibility(View.GONE);
+            mCurrentAnim = null;
+        }
+
+        @Override
+        public void onAnimationCancel(Animator animation) {
+        }
+
+        @Override
+        public void onAnimationRepeat(Animator animation) {
+        }
+    };
+
+    final AnimatorListener mShowListener = new AnimatorListener() {
+        @Override
+        public void onAnimationStart(Animator animation) {
+        }
+
+        @Override
+        public void onAnimationEnd(Animator animation) {
+            mCurrentAnim = null;
+        }
+
+        @Override
+        public void onAnimationCancel(Animator animation) {
+        }
+
+        @Override
+        public void onAnimationRepeat(Animator animation) {
+        }
+    };
+
     public ActionBarImpl(Activity activity) {
         mActivity = activity;
-        init(activity.getWindow().getDecorView());
+        Window window = activity.getWindow();
+        View decor = window.getDecorView();
+        init(decor);
+        if (!mActivity.getWindow().hasFeature(Window.FEATURE_ACTION_BAR_OVERLAY)) {
+            mContentView = decor.findViewById(android.R.id.content);
+        }
     }
 
     public ActionBarImpl(Dialog dialog) {
@@ -444,14 +492,45 @@
 
     @Override
     public void show() {
-        // TODO animate!
+        if (mCurrentAnim != null) {
+            mCurrentAnim.end();
+        }
+        if (mContainerView.getVisibility() == View.VISIBLE) {
+            return;
+        }
         mContainerView.setVisibility(View.VISIBLE);
+        mContainerView.setAlpha(0);
+        mContainerView.setTranslationY(-mContainerView.getHeight());
+        AnimatorSet anim = new AnimatorSet();
+        AnimatorSet.Builder b = anim.play(ObjectAnimator.ofFloat(mContainerView, "translationY", 0))
+            .with(ObjectAnimator.ofFloat(mContainerView, "alpha", 1));
+        if (mContentView != null) {
+            b.with(ObjectAnimator.ofFloat(mContentView, "translationY", -mContainerView.getHeight(), 0));
+        }
+        anim.addListener(mShowListener);
+        mCurrentAnim = anim;
+        anim.start();
     }
 
     @Override
     public void hide() {
-        // TODO animate!
-        mContainerView.setVisibility(View.GONE);
+        if (mCurrentAnim != null) {
+            mCurrentAnim.end();
+        }
+        if (mContainerView.getVisibility() == View.GONE) {
+            return;
+        }
+        mContainerView.setAlpha(1);
+        AnimatorSet anim = new AnimatorSet();
+        AnimatorSet.Builder b = anim.play(
+                ObjectAnimator.ofFloat(mContainerView, "translationY", -mContainerView.getHeight()))
+            .with(ObjectAnimator.ofFloat(mContainerView, "alpha", 0));
+        if (mContentView != null) {
+            b.with(ObjectAnimator.ofFloat(mContentView, "translationY", 0, -mContainerView.getHeight()));
+        }
+        anim.addListener(mHideListener);
+        mCurrentAnim = anim;
+        anim.start();
     }
 
     public boolean isShowing() {
@@ -459,10 +538,7 @@
     }
 
     private long animateTo(int viewIndex) {
-        // Don't wait for the current animation to finish.
-        if (mCurrentAnimation != null) {
-            mCurrentAnimation.end();
-        }
+        show();
 
         AnimatorSet set = new AnimatorSet();
 
@@ -492,7 +568,7 @@
 
         set.addListener(mAfterAnimation[viewIndex]);
 
-        mCurrentAnimation = set;
+        mCurrentAnim = set;
         set.start();
         return set.getDuration();
     }
diff --git a/core/java/com/android/internal/app/NetInitiatedActivity.java b/core/java/com/android/internal/app/NetInitiatedActivity.java
index 36f45b2..6039cc2 100755
--- a/core/java/com/android/internal/app/NetInitiatedActivity.java
+++ b/core/java/com/android/internal/app/NetInitiatedActivity.java
@@ -26,6 +26,8 @@
 import android.widget.Toast;
 import android.util.Log;
 import android.location.LocationManager;
+
+import com.android.internal.R;
 import com.android.internal.location.GpsNetInitiatedHandler;
 
 /**
@@ -42,10 +44,6 @@
     private static final int POSITIVE_BUTTON = AlertDialog.BUTTON_POSITIVE;
     private static final int NEGATIVE_BUTTON = AlertDialog.BUTTON_NEGATIVE;
 
-    // Dialog button text
-    public static final String BUTTON_TEXT_ACCEPT = "Accept";
-    public static final String BUTTON_TEXT_DENY = "Deny";
-
     // Received ID from intent, -1 when no notification is in progress
     private int notificationId = -1;
 
@@ -67,12 +65,13 @@
         // Set up the "dialog"
         final Intent intent = getIntent();
         final AlertController.AlertParams p = mAlertParams;
+        Context context = getApplicationContext();
         p.mIconId = com.android.internal.R.drawable.ic_dialog_usb;
         p.mTitle = intent.getStringExtra(GpsNetInitiatedHandler.NI_INTENT_KEY_TITLE);
         p.mMessage = intent.getStringExtra(GpsNetInitiatedHandler.NI_INTENT_KEY_MESSAGE);
-        p.mPositiveButtonText = BUTTON_TEXT_ACCEPT;
+        p.mPositiveButtonText = String.format(context.getString(R.string.gpsVerifYes));
         p.mPositiveButtonListener = this;
-        p.mNegativeButtonText = BUTTON_TEXT_DENY;
+        p.mNegativeButtonText = String.format(context.getString(R.string.gpsVerifNo));
         p.mNegativeButtonListener = this;
 
         notificationId = intent.getIntExtra(GpsNetInitiatedHandler.NI_INTENT_KEY_NOTIF_ID, -1);
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 630830d..145feb5 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -3090,13 +3090,18 @@
                 }
             }
 
-            void readExcessivePowerFromParcelLocked(Parcel in) {
+            boolean readExcessivePowerFromParcelLocked(Parcel in) {
                 final int N = in.readInt();
                 if (N == 0) {
                     mExcessivePower = null;
-                    return;
+                    return true;
                 }
 
+                if (N > 10000) {
+                    Slog.w(TAG, "File corrupt: too many excessive power entries " + N);
+                    return false;
+                }
+                
                 mExcessivePower = new ArrayList<ExcessivePower>();
                 for (int i=0; i<N; i++) {
                     ExcessivePower ew = new ExcessivePower();
@@ -3105,6 +3110,7 @@
                     ew.usedTime = in.readLong();
                     mExcessivePower.add(ew);
                 }
+                return true;
             }
 
             void writeToParcelLocked(Parcel out) {
@@ -4700,7 +4706,7 @@
             }
 
             int NW = in.readInt();
-            if (NW > 10000) {
+            if (NW > 100) {
                 Slog.w(TAG, "File corrupt: too many wake locks " + NW);
                 return;
             }
@@ -4718,7 +4724,7 @@
             }
 
             int NP = in.readInt();
-            if (NP > 10000) {
+            if (NP > 1000) {
                 Slog.w(TAG, "File corrupt: too many sensors " + NP);
                 return;
             }
@@ -4731,7 +4737,7 @@
             }
 
             NP = in.readInt();
-            if (NP > 10000) {
+            if (NP > 1000) {
                 Slog.w(TAG, "File corrupt: too many processes " + NP);
                 return;
             }
@@ -4742,6 +4748,10 @@
                 p.mSystemTime = p.mLoadedSystemTime = in.readLong();
                 p.mStarts = p.mLoadedStarts = in.readInt();
                 int NSB = in.readInt();
+                if (NSB > 100) {
+                    Slog.w(TAG, "File corrupt: too many speed bins " + NSB);
+                    return;
+                }
                 p.mSpeedBins = new SamplingCounter[NSB];
                 for (int i=0; i<NSB; i++) {
                     if (in.readInt() != 0) {
@@ -4749,7 +4759,9 @@
                         p.mSpeedBins[i].readSummaryFromParcelLocked(in);
                     }
                 }
-                p.readExcessivePowerFromParcelLocked(in);
+                if (!p.readExcessivePowerFromParcelLocked(in)) {
+                    return;
+                }
             }
 
             NP = in.readInt();
@@ -4762,6 +4774,10 @@
                 Uid.Pkg p = u.getPackageStatsLocked(pkgName);
                 p.mWakeups = p.mLoadedWakeups = in.readInt();
                 final int NS = in.readInt();
+                if (NS > 1000) {
+                    Slog.w(TAG, "File corrupt: too many services " + NS);
+                    return;
+                }
                 for (int is = 0; is < NS; is++) {
                     String servName = in.readString();
                     Uid.Pkg.Serv s = u.getServiceStatsLocked(pkgName, servName);
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 848bf9e..dea53bf 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -557,8 +557,6 @@
 
     public static void main(String argv[]) {
         try {
-            VMRuntime.getRuntime().setMinimumHeapSize(5 * 1024 * 1024);
-
             // Start profiling the zygote initialization.
             SamplingProfilerIntegration.start();
 
diff --git a/core/java/com/android/internal/widget/DrawableHolder.java b/core/java/com/android/internal/widget/DrawableHolder.java
index a528aeb..947e0f3 100644
--- a/core/java/com/android/internal/widget/DrawableHolder.java
+++ b/core/java/com/android/internal/widget/DrawableHolder.java
@@ -87,15 +87,12 @@
      * @param property
      */
     public void removeAnimationFor(String property) {
-        ArrayList<ObjectAnimator> removalList = new ArrayList<ObjectAnimator>();
-        for (ObjectAnimator currentAnim : mAnimators) {
+        ArrayList<ObjectAnimator> removalList = (ArrayList<ObjectAnimator>)mAnimators.clone();
+        for (ObjectAnimator currentAnim : removalList) {
             if (property.equals(currentAnim.getPropertyName())) {
                 currentAnim.cancel();
-                removalList.add(currentAnim);
             }
         }
-        if (DBG) Log.v(TAG, "Remove list size: " + removalList.size());
-        mAnimators.removeAll(removalList);
     }
 
     /**
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index bcd7bae..8eeed3d 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -51,11 +51,11 @@
 	android_view_InputChannel.cpp \
 	android_view_InputQueue.cpp \
 	android_view_KeyEvent.cpp \
+	android_view_KeyCharacterMap.cpp \
 	android_view_GLES20Canvas.cpp \
 	android_view_MotionEvent.cpp \
 	android_text_AndroidCharacter.cpp \
 	android_text_AndroidBidi.cpp \
-	android_text_KeyCharacterMap.cpp \
 	android_os_Debug.cpp \
 	android_os_FileUtils.cpp \
 	android_os_MemoryFile.cpp \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index e50233e..98bdb52 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -353,33 +353,12 @@
  */
 jclass AndroidRuntime::findClass(JNIEnv* env, const char* className)
 {
-    char* convName = NULL;
-
     if (env->ExceptionCheck()) {
-        LOGE("ERROR: exception pending on entry to findClass()\n");
+        LOGE("ERROR: exception pending on entry to findClass()");
         return NULL;
     }
 
     /*
-     * JNI FindClass uses class names with slashes, but ClassLoader.loadClass
-     * uses the dotted "binary name" format.  We don't need to convert the
-     * name with the new approach.
-     */
-#if 0
-    /* (convName only created if necessary -- use className) */
-    for (char* cp = const_cast<char*>(className); *cp != '\0'; cp++) {
-        if (*cp == '.') {
-            if (convName == NULL) {
-                convName = strdup(className);
-                cp = convName + (cp-className);
-                className = convName;
-            }
-            *cp = '/';
-        }
-    }
-#endif
-
-    /*
      * This is a little awkward because the JNI FindClass call uses the
      * class loader associated with the native method we're executing in.
      * Because this native method is part of a "boot" class, JNI doesn't
@@ -394,7 +373,6 @@
      * have to do things the hard way.
      */
     jclass cls = NULL;
-    //cls = env->FindClass(className);
 
     jclass javaLangClassLoader;
     jmethodID getSystemClassLoader, loadClass;
@@ -416,24 +394,21 @@
     /* create an object for the class name string; alloc could fail */
     strClassName = env->NewStringUTF(className);
     if (env->ExceptionCheck()) {
-        LOGE("ERROR: unable to convert '%s' to string\n", className);
-        goto bail;
+        LOGE("ERROR: unable to convert '%s' to string", className);
+        return NULL;
     }
-    LOGV("system class loader is %p, loading %p (%s)\n",
+    LOGV("system class loader is %p, loading %p (%s)",
         systemClassLoader, strClassName, className);
 
     /* try to find the named class */
     cls = (jclass) env->CallObjectMethod(systemClassLoader, loadClass,
                         strClassName);
     if (env->ExceptionCheck()) {
-        LOGE("ERROR: unable to load class '%s' from %p\n",
+        LOGE("ERROR: unable to load class '%s' from %p",
             className, systemClassLoader);
-        cls = NULL;
-        goto bail;
+        return NULL;
     }
 
-bail:
-    free(convName);
     return cls;
 }
 
@@ -576,6 +551,7 @@
     char dexoptFlagsBuf[PROPERTY_VALUE_MAX];
     char enableAssertBuf[sizeof("-ea:")-1 + PROPERTY_VALUE_MAX];
     char jniOptsBuf[sizeof("-Xjniopts:")-1 + PROPERTY_VALUE_MAX];
+    char heapstartsizeOptsBuf[sizeof("-Xms")-1 + PROPERTY_VALUE_MAX];
     char heapsizeOptsBuf[sizeof("-Xmx")-1 + PROPERTY_VALUE_MAX];
     char extraOptsBuf[PROPERTY_VALUE_MAX];
     char* stackTraceFile = NULL;
@@ -650,6 +626,11 @@
     mOptions.add(opt);
     //options[curOpt++].optionString = "-verbose:class";
 
+    strcpy(heapstartsizeOptsBuf, "-Xms");
+    property_get("dalvik.vm.heapstartsize", heapstartsizeOptsBuf+4, "2m");
+    opt.optionString = heapstartsizeOptsBuf;
+    mOptions.add(opt);
+
     strcpy(heapsizeOptsBuf, "-Xmx");
     property_get("dalvik.vm.heapsize", heapsizeOptsBuf+4, "16m");
     //LOGI("Heap size: %s", heapsizeOptsBuf);
diff --git a/core/jni/android_text_KeyCharacterMap.cpp b/core/jni/android_view_KeyCharacterMap.cpp
similarity index 78%
rename from core/jni/android_text_KeyCharacterMap.cpp
rename to core/jni/android_view_KeyCharacterMap.cpp
index a7e62c1..bfeec4f 100644
--- a/core/jni/android_text_KeyCharacterMap.cpp
+++ b/core/jni/android_view_KeyCharacterMap.cpp
@@ -29,6 +29,14 @@
     jclass clazz;
 } gKeyEventClassInfo;
 
+static struct {
+    jclass clazz;
+
+    jfieldID keyCode;
+    jfieldID metaState;
+} gFallbackActionClassInfo;
+
+
 static jint nativeLoad(JNIEnv *env, jobject clazz, jint deviceId) {
     KeyCharacterMap* map;
     status_t status = KeyCharacterMap::loadByDeviceId(deviceId, &map);
@@ -54,6 +62,21 @@
     return map->getCharacter(keyCode, metaState);
 }
 
+static jboolean nativeGetFallbackAction(JNIEnv *env, jobject clazz, jint ptr, jint keyCode,
+        jint metaState, jobject fallbackActionObj) {
+    KeyCharacterMap* map = reinterpret_cast<KeyCharacterMap*>(ptr);
+    KeyCharacterMap::FallbackAction fallbackAction;
+
+    bool result = map->getFallbackAction(keyCode, metaState, &fallbackAction);
+    if (result) {
+        env->SetIntField(fallbackActionObj, gFallbackActionClassInfo.keyCode,
+                fallbackAction.keyCode);
+        env->SetIntField(fallbackActionObj, gFallbackActionClassInfo.metaState,
+                fallbackAction.metaState);
+    }
+    return result;
+}
+
 static jchar nativeGetNumber(JNIEnv *env, jobject clazz, jint ptr, jint keyCode) {
     KeyCharacterMap* map = reinterpret_cast<KeyCharacterMap*>(ptr);
     return map->getNumber(keyCode);
@@ -126,6 +149,8 @@
             (void*)nativeDispose },
     { "nativeGetCharacter", "(III)C",
             (void*)nativeGetCharacter },
+    { "nativeGetFallbackAction", "(IIILandroid/view/KeyCharacterMap$FallbackAction;)Z",
+            (void*)nativeGetFallbackAction },
     { "nativeGetNumber", "(II)C",
             (void*)nativeGetNumber },
     { "nativeGetMatch", "(II[CI)C",
@@ -143,10 +168,22 @@
         LOG_FATAL_IF(! var, "Unable to find class " className); \
         var = jclass(env->NewGlobalRef(var));
 
+#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
+        var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
+        LOG_FATAL_IF(! var, "Unable to find field " fieldName);
+
 int register_android_text_KeyCharacterMap(JNIEnv* env)
 {
     FIND_CLASS(gKeyEventClassInfo.clazz, "android/view/KeyEvent");
 
+    FIND_CLASS(gFallbackActionClassInfo.clazz, "android/view/KeyCharacterMap$FallbackAction");
+
+    GET_FIELD_ID(gFallbackActionClassInfo.keyCode, gFallbackActionClassInfo.clazz,
+            "keyCode", "I");
+
+    GET_FIELD_ID(gFallbackActionClassInfo.metaState, gFallbackActionClassInfo.clazz,
+            "metaState", "I");
+
     return AndroidRuntime::registerNativeMethods(env,
             "android/view/KeyCharacterMap", g_methods, NELEM(g_methods));
 }
diff --git a/core/res/res/drawable-hdpi/simple_week_dayline_holo_light.9.png b/core/res/res/drawable-hdpi/simple_week_dayline_holo_light.9.png
new file mode 100644
index 0000000..ed1a5e9
--- /dev/null
+++ b/core/res/res/drawable-hdpi/simple_week_dayline_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/simple_week_dayline_holo_light.9.png b/core/res/res/drawable-mdpi/simple_week_dayline_holo_light.9.png
new file mode 100644
index 0000000..f264cb6
--- /dev/null
+++ b/core/res/res/drawable-mdpi/simple_week_dayline_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_notify_chat.png b/core/res/res/drawable-mdpi/stat_notify_chat.png
index 068b7ec..8cf02cc 100644
--- a/core/res/res/drawable-mdpi/stat_notify_chat.png
+++ b/core/res/res/drawable-mdpi/stat_notify_chat.png
Binary files differ
diff --git a/core/res/res/layout/date_picker.xml b/core/res/res/layout/date_picker.xml
index 4fd46b3..5c023ee 100644
--- a/core/res/res/layout/date_picker.xml
+++ b/core/res/res/layout/date_picker.xml
@@ -19,45 +19,74 @@
 
 <!-- Layout of date picker-->
 
-<!-- Warning: everything within the parent is removed and re-ordered depending
-     on the date format selected by the user. -->
+<!-- Warning: everything within the "pickers" layout is removed and re-ordered
+     depending on the date format selected by the user.
+-->
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/parent"
-    android:orientation="horizontal"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
     android:layout_gravity="center_horizontal"
-    android:layout_width="wrap_content"
-    android:layout_height="wrap_content">
+    android:orientation="horizontal"
+    android:gravity="center">
 
-    <!-- Month -->
-    <NumberPicker
-        android:id="@+id/month"
-        android:layout_width="80dip"
+    <LinearLayout android:id="@+id/pickers"
+        android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_marginLeft="1dip"
-        android:layout_marginRight="1dip"
-        android:focusable="true"
-        android:focusableInTouchMode="true"
-        />
+        android:layout_marginRight="15dip"
+        android:layout_weight="0.5"
+        android:orientation="horizontal"
+        android:gravity="center">
 
-    <!-- Day -->
-    <NumberPicker
-        android:id="@+id/day"
-        android:layout_width="80dip"
-        android:layout_height="wrap_content"
-        android:layout_marginLeft="1dip"
-        android:layout_marginRight="1dip"
-        android:focusable="true"
-        android:focusableInTouchMode="true"
-        />
+        <!-- Month -->
+        <NumberPicker
+            android:id="@+id/month"
+            android:layout_width="48dip"
+            android:layout_height="wrap_content"
+            android:layout_marginLeft="15dip"
+            android:layout_marginRight="15dip"
+            android:layout_marginTop="35dip"
+            android:layout_marginBottom="35dip"
+            android:focusable="true"
+            android:focusableInTouchMode="true"
+            />
 
-    <!-- Year -->
-    <NumberPicker
-        android:id="@+id/year"
-        android:layout_width="95dip"
-        android:layout_height="wrap_content"
-        android:layout_marginLeft="1dip"
-        android:layout_marginRight="1dip"
-        android:focusable="true"
-        android:focusableInTouchMode="true"
-        />
+        <!-- Day -->
+        <NumberPicker
+            android:id="@+id/day"
+            android:layout_width="48dip"
+            android:layout_height="wrap_content"
+            android:layout_marginLeft="15dip"
+            android:layout_marginRight="15dip"
+            android:layout_marginTop="35dip"
+            android:layout_marginBottom="35dip"
+            android:focusable="true"
+            android:focusableInTouchMode="true"
+            />
+
+        <!-- Year -->
+        <NumberPicker
+            android:id="@+id/year"
+            android:layout_width="48dip"
+            android:layout_height="wrap_content"
+            android:layout_marginLeft="15dip"
+            android:layout_marginRight="15dip"
+            android:layout_marginTop="35dip"
+            android:layout_marginBottom="35dip"       
+            android:focusable="true"
+            android:focusableInTouchMode="true"
+            />
+
+    </LinearLayout>
+
+    <!-- mini-month day-picker -->
+      <DayPicker
+          android:id="@+id/mini_month_day_picker"
+          android:layout_width="200dip"
+          android:layout_height="230dip"
+          android:layout_marginLeft="15dip"
+          android:layout_weight="0.5"
+          android:focusable="true"
+          android:focusableInTouchMode="true"
+          />
+
 </LinearLayout>
diff --git a/core/res/res/layout/date_picker_dialog.xml b/core/res/res/layout/date_picker_dialog.xml
index 949c8a3..90de1f5 100644
--- a/core/res/res/layout/date_picker_dialog.xml
+++ b/core/res/res/layout/date_picker_dialog.xml
@@ -17,9 +17,14 @@
 */
 -->
 
+<!-- Note: We want the DatePicker to take as much space as possible, therefore
+           we set the width and height bigger than the max AlertDialog size
+           determined by our parent WeightedLinearLayout.
+
+           See: alert_dialog.xml
+-->
 <DatePicker xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/datePicker"
-    android:padding="5dip"
     android:layout_gravity="center_horizontal"
-    android:layout_width="wrap_content"
-    android:layout_height="wrap_content"/>
+    android:layout_width="250dip"
+    android:layout_height="600dip"/>
diff --git a/core/res/res/layout/day_picker.xml b/core/res/res/layout/day_picker.xml
new file mode 100644
index 0000000..46ab450
--- /dev/null
+++ b/core/res/res/layout/day_picker.xml
@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* Copyright 2010, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License")
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:fillViewport="true" >
+
+    <TextView android:id="@+android:id/month_name"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_horizontal" 
+        android:paddingTop="10dip"
+        android:paddingBottom="10dip"
+        style="@android:style/TextAppearance.Medium" />
+
+    <LinearLayout android:id="@+android:id/day_names"
+        android:orientation="horizontal"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginBottom="6dip"
+        android:layout_marginRight="2dip"
+        android:layout_marginLeft="2dip"
+        android:gravity="center">
+
+        <TextView android:layout_width="0dip"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:gravity="center"
+            android:visibility="gone" />
+
+        <TextView android:layout_width="0dip"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:gravity="center"
+            style="?android:attr/dayPickerWeekDayViewStyle" />
+
+        <TextView android:layout_width="0dip"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:gravity="center"
+            style="?android:attr/dayPickerWeekDayViewStyle" />
+
+        <TextView android:layout_width="0dip"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:gravity="center"
+            style="?android:attr/dayPickerWeekDayViewStyle" />
+
+        <TextView android:layout_width="0dip"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:gravity="center"
+            style="?android:attr/dayPickerWeekDayViewStyle" />
+
+        <TextView android:layout_width="0dip"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:gravity="center"
+            style="?android:attr/dayPickerWeekDayViewStyle" />
+
+        <TextView android:layout_width="0dip"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:gravity="center"
+            style="?android:attr/dayPickerWeekDayViewStyle" />
+
+        <TextView android:layout_width="0dip"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:gravity="center"
+            style="?android:attr/dayPickerWeekDayViewStyle" />
+
+    </LinearLayout>
+
+    <ListView android:id="@android:id/list"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:drawSelectorOnTop="false"
+            android:cacheColorHint="@android:color/transparent"
+            android:fastScrollEnabled="false"
+            android:overScrollMode="never" />
+
+</LinearLayout>
diff --git a/core/res/res/layout/time_picker.xml b/core/res/res/layout/time_picker.xml
index fa288422..bf81c18 100644
--- a/core/res/res/layout/time_picker.xml
+++ b/core/res/res/layout/time_picker.xml
@@ -30,7 +30,7 @@
         android:id="@+id/hour"
         android:layout_width="48dip"
         android:layout_height="wrap_content"
-        android:layout_marginRight="20dip"
+        android:layout_marginRight="13dip"
         android:layout_marginTop="35dip"
         android:layout_marginBottom="35dip"
         android:focusable="true"
@@ -50,8 +50,8 @@
         android:id="@+id/minute"
         android:layout_width="48dip"
         android:layout_height="wrap_content"
-        android:layout_marginLeft="20dip"
-        android:layout_marginRight="22dip"
+        android:layout_marginLeft="13dip"
+        android:layout_marginRight="15dip"
         android:layout_marginTop="35dip"
         android:layout_marginBottom="35dip"
         android:focusable="true"
@@ -63,7 +63,7 @@
         android:id="@+id/amPm"
         android:layout_width="48dip"
         android:layout_height="wrap_content"
-        android:layout_marginLeft="22dip"
+        android:layout_marginLeft="15dip"
         android:layout_marginTop="35dip"
         android:layout_marginBottom="35dip"
         android:focusable="true"
diff --git a/core/res/res/layout/time_picker_dialog.xml b/core/res/res/layout/time_picker_dialog.xml
index d5a6b5e..09326c8 100644
--- a/core/res/res/layout/time_picker_dialog.xml
+++ b/core/res/res/layout/time_picker_dialog.xml
@@ -22,4 +22,4 @@
     android:layout_gravity="center_horizontal"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
-    android:padding="5dip" />
+    />
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 109fb0d..4bd91b3 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -503,16 +503,23 @@
         <attr name="listPopupWindowStyle" format="reference" />
         <!-- Default PopupMenu style. -->
         <attr name="popupMenuStyle" format="reference" />
-        <!-- NumberPicker up button style -->
+
+        <!-- @hide NumberPicker up button style -->
         <attr name="numberPickerUpButtonStyle" format="reference" />
-        <!-- NumberPicker down button style -->
+        <!-- @hide NumberPicker down button style -->
         <attr name="numberPickerDownButtonStyle" format="reference" />
-        <!-- NumberPicker input text style -->
+        <!-- @hide NumberPicker input text style -->
         <attr name="numberPickerInputTextStyle" format="reference" />
 
-        <!-- NumberPicker the fading edge length of the selector wheel -->
+        <!-- @hide NumberPicker the fading edge length of the selector wheel -->
         <attr name="numberPickerStyle" format="reference" />
 
+        <!-- @hide DayPicker$WeekView style-->
+        <attr name="dayPickerWeekViewStyle" format="reference" />
+
+        <!-- @hide DayPickerDayView style-->
+        <attr name="dayPickerWeekDayViewStyle" format="reference" />
+
         <!-- =================== -->
         <!-- Action bar styles   -->
         <!-- =================== -->
@@ -1260,6 +1267,7 @@
         <enum name="KEYCODE_PROG_GREEN" value="184" />
         <enum name="KEYCODE_PROG_YELLOW" value="185" />
         <enum name="KEYCODE_PROG_BLUE" value="186" />
+        <enum name="KEYCODE_APP_SWITCH" value="187" />
     </attr>
 
     <!-- ***************************************************************** -->
@@ -2943,6 +2951,16 @@
     </declare-styleable>
 
     <!-- @hide -->
+    <declare-styleable name="DayPickerWeekView">
+        <attr name="selectionBackgroundColor" format="color|reference" />
+        <attr name="focusedMonthDateColor" format="color|reference" />
+        <attr name="otherMonthDateColor" format="color|reference" />
+        <attr name="weekNumberColor" format="color|reference" />
+        <attr name="gridLinesColor" format="color|reference" />
+        <attr name="selectedDayLine" format="reference" />
+    </declare-styleable>
+
+    <!-- @hide -->
     <declare-styleable name="NumberPicker">
         <attr name="orientation" />
         <attr name="solidColor" format="color|reference" />
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index ae029e5..8fa1d32 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1567,6 +1567,6 @@
   <public type="style" name="Holo.Light.ButtonBar.AlertDialog" />
   <public type="style" name="Holo.SegmentedButton" />
   <public type="style" name="Holo.Light.SegmentedButton" />
-
   <public type="string" name="selectTextMode" />
+
 </resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 0f5ff05..2e235f0 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -2295,6 +2295,8 @@
 
     <!-- The title of the time picker dialog. [CHAR LIMIT=NONE] -->
     <string name="time_picker_dialog_title">Set time</string>
+    <!-- The title of the date picker dialog. [CHAR LIMIT=NONE] -->
+    <string name="date_picker_dialog_title">Set date</string>
     <!-- Name of the button in the date/time picker to accept the date/time change -->
     <string name="date_time_set">Set</string>
 
@@ -2621,4 +2623,19 @@
     <!-- ActionBar action to use the current selection to open the Find on page functionality [CHAR LIMIT=10]-->
     <string name="find">Find</string>
 
+    <!-- Network positioning notification ticker. The name of the user (e.g. John Doe) who sent
+         the request is shown as a dynamic string. -->
+    <string name="gpsNotifTicker">Location request from <xliff:g id="name">%s</xliff:g></string>
+    <!-- Network positioning notification and verification title to inform the user about
+         an incoming location request. -->
+    <string name="gpsNotifTitle">Location request</string>
+    <!-- Network positioning notification message. The name of the user (e.g. John Doe) and
+         service (SUPL-service) who sent the request is shown as dynamic strings.
+         Translation should not be longer than master text. -->
+    <string name="gpsNotifMessage">Requested by <xliff:g id="name">%1$s</xliff:g> (<xliff:g id="service" example="SUPL-service">%2$s</xliff:g>)</string>
+    <!-- Network positioning verification Yes. Button to push to share location information. -->
+    <string name="gpsVerifYes">Yes</string>
+    <!-- Network positioning verification No. Button to push to deny sharing of location
+         information. -->
+    <string name="gpsVerifNo">No</string>
 </resources>
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 58553e1..8d7556f 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -238,6 +238,11 @@
         <item name="android:textColor">#ff272727</item>
     </style>
 
+    <!-- @hide -->
+    <style name="TextAppearance.Small.DayPickerWeekDayView">
+        <item name="android:textStyle">bold</item>
+    </style>
+
     <!-- Widget Styles -->
 
     <style name="Widget">
@@ -468,21 +473,35 @@
         <item name="android:background">@android:drawable/btn_default</item>
     </style>
 
+    <!-- @hide -->
+    <style name="Widget.DayPickerWeekView">
+        <item name="android:selectionBackgroundColor">#330099FF</item>
+        <item name="android:focusedMonthDateColor">#FFFFFFFF</item>
+        <item name="android:otherMonthDateColor">#66FFFFFF</item>
+        <item name="android:weekNumberColor">#33FFFFFF</item>
+        <item name="android:gridLinesColor">#19FFFFFF</item>
+        <item name="selectedDayLine">@android:drawable/simple_week_dayline_holo_light</item>
+    </style>
+
+    <!-- @hide -->
     <style name="Widget.NumberPicker">
         <item name="android:orientation">vertical</item>
         <item name="android:fadingEdge">vertical</item>
         <item name="android:fadingEdgeLength">50dip</item>
-        <item name="android:solidColor">?android:attr/colorBackground</item>
+        <item name="android:solidColor">@android:color/transparent</item>
     </style>
 
+    <!-- @hide -->
     <style name="Widget.ImageButton.NumberPickerUpButton">
         <item name="android:background">@android:drawable/timepicker_up_btn</item>
     </style>
 
+    <!-- @hide -->
     <style name="Widget.ImageButton.NumberPickerDownButton">
         <item name="android:background">@android:drawable/timepicker_down_btn</item>
     </style>
 
+    <!-- @hide -->
     <style name="Widget.EditText.NumberPickerInputText">
         <item name="android:textAppearance">@style/TextAppearance.Large.Inverse.NumberPickerInputText</item>
         <item name="android:gravity">center</item>
@@ -834,6 +853,7 @@
         <item name="android:textStyle">bold</item>
     </style>
 
+    <!-- @hide -->
     <style name="TextAppearance.Large.Inverse.NumberPickerInputText">
         <item name="android:textColor">@android:color/primary_text_light</item>
         <item name="android:textSize">30sp</item>
@@ -1200,6 +1220,11 @@
         <item name="android:textSize">18sp</item>
     </style>
 
+    <!-- @hide -->
+    <style name="TextAppearance.Holo.DayPickerWeekDayView" parent="TextAppearance.Small.DayPickerWeekDayView">
+        <item name="android:textColor">#505050</item>
+    </style>
+
     <!-- Light text styles -->
     <style name="TextAppearance.Holo.Light" parent="TextAppearance.Holo">
     </style>
@@ -1296,6 +1321,10 @@
         <item name="android:textSize">18sp</item>
     </style>
 
+    <!-- @hide -->
+    <style name="TextAppearance.Holo.Light.DayPickerWeekDayView" parent="TextAppearance.Small.DayPickerWeekDayView">
+    </style>
+
     <!-- Widget Styles -->
 
     <style name="Widget.Holo" parent="Widget">
@@ -1406,22 +1435,35 @@
         <item name="android:listSelector">?android:attr/selectableItemBackground</item>
     </style>
 
+    <!-- @hide -->
+    <style name="Widget.Holo.DayPickerWeekView">
+        <item name="android:selectionBackgroundColor">#330099FF</item>
+        <item name="android:focusedMonthDateColor">#FFFFFFFF</item>
+        <item name="android:otherMonthDateColor">#66FFFFFF</item>
+        <item name="android:weekNumberColor">#33FFFFFF</item>
+        <item name="android:gridLinesColor">#19FFFFFF</item>
+        <item name="selectedDayLine">@android:drawable/simple_week_dayline_holo_light</item>
+    </style>
+
     <style name="Widget.Holo.ImageButton" parent="Widget.ImageButton">
         <item name="android:background">@android:drawable/btn_default_holo_dark</item>
     </style>
 
+    <!-- @hide -->
     <style name="Widget.Holo.ImageButton.NumberPickerUpButton">
         <item name="android:background">@null</item>
         <item name="android:paddingBottom">26sp</item>
         <item name="android:src">@android:drawable/timepicker_up_btn_holo_dark</item>
     </style>
 
+    <!-- @hide -->
     <style name="Widget.Holo.ImageButton.NumberPickerDownButton">
         <item name="android:background">@null</item>
         <item name="android:paddingTop">26sp</item>
         <item name="android:src">@android:drawable/timepicker_down_btn_holo_dark</item>
     </style>
 
+    <!-- @hide -->
     <style name="Widget.Holo.EditText.NumberPickerInputText">
         <item name="android:paddingTop">13sp</item>
         <item name="android:paddingBottom">13sp</item>
@@ -1767,14 +1809,21 @@
         <item name="android:background">@android:drawable/btn_default_holo_light</item>
     </style>
 
+    <!-- @hide -->
+    <style name="Widget.Holo.Light.DayPickerWeekView" parent="Widget.DayPickerWeekView">
+    </style>
+
+    <!-- @hide -->
     <style name="Widget.Holo.Light.ImageButton.NumberPickerUpButton" parent="Widget.Holo.Light.ImageButton.NumberPickerUpButton">
         <item name="android:background">@android:drawable/timepicker_up_btn_holo_light</item>
     </style>
 
+    <!-- @hide -->
     <style name="Widget.Holo.Light.ImageButton.NumberPickerDownButton" parent="Widget.Holo.ImageButton.NumberPickerDownButton">
         <item name="android:background">@android:drawable/timepicker_down_btn_holo_light</item>
     </style>
 
+    <!-- @hide -->
     <style name="Widget.Holo.Light.EditText.NumberPickerInputText" parent="Widget.Holo.EditText.NumberPickerInputText">
     </style>
 
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index 0f21e9f..94e8f96 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -26,7 +26,7 @@
          of it a dark color.
     -->
     <style name="Theme">
-    
+
         <item name="colorForeground">@android:color/bright_foreground_dark</item>
         <item name="colorForegroundInverse">@android:color/bright_foreground_dark_inverse</item>
         <item name="colorBackground">@android:color/background_dark</item>
@@ -280,6 +280,12 @@
         <item name="numberPickerInputTextStyle">@style/Widget.EditText.NumberPickerInputText</item>
         <item name="numberPickerStyle">@style/Widget.NumberPicker</item>
 
+        <!-- DayPicker$WeekView style-->
+        <item name="dayPickerWeekViewStyle">@style/Widget.DayPickerWeekView</item>
+
+        <!-- DayPickerWeekDayView style-->
+        <item name="dayPickerWeekDayViewStyle">@style/TextAppearance.Small.DayPickerWeekDayView</item>
+
     </style>
 
     <!-- Variant of the default (dark) theme with no title bar -->
@@ -917,6 +923,12 @@
         <item name="numberPickerDownButtonStyle">@style/Widget.Holo.ImageButton.NumberPickerDownButton</item>
         <item name="numberPickerInputTextStyle">@style/Widget.Holo.EditText.NumberPickerInputText</item>
 
+        <!-- DayPicker$WeekView style-->
+        <item name="dayPickerWeekViewStyle">@style/Widget.Holo.DayPickerWeekView</item>
+
+        <!-- DayPickerWeekDayView style-->
+        <item name="dayPickerWeekDayViewStyle">@style/TextAppearance.Holo.DayPickerWeekDayView</item>
+
     </style>
 
     <!-- New Honeycomb holographic theme. Light version.  The widgets in the
@@ -1162,6 +1174,12 @@
         <item name="numberPickerDownButtonStyle">@style/Widget.Holo.Light.ImageButton.NumberPickerDownButton</item>
         <item name="numberPickerInputTextStyle">@style/Widget.Holo.Light.EditText.NumberPickerInputText</item>
 
+        <!-- DayPicker$WeekView style-->
+        <item name="dayPickerWeekViewStyle">@style/Widget.Holo.Light.DayPickerWeekView</item>
+
+        <!-- DayPickerWeekDayView style-->
+        <item name="dayPickerWeekDayViewStyle">@style/TextAppearance.Holo.Light.DayPickerWeekDayView</item>
+
     </style>
 
     <!-- Development legacy name; if you're using this, switch. -->
diff --git a/core/tests/ConnectivityManagerTest/Android.mk b/core/tests/ConnectivityManagerTest/Android.mk
index a1546fa..56011f7 100644
--- a/core/tests/ConnectivityManagerTest/Android.mk
+++ b/core/tests/ConnectivityManagerTest/Android.mk
@@ -25,6 +25,6 @@
 
 LOCAL_PACKAGE_NAME := ConnectivityManagerTest
 
-#LOCAL_INSTRUMENTATION_FOR := connectivitymanagertest
+LOCAL_CERTIFICATE := platform
 
 include $(BUILD_PACKAGE)
diff --git a/core/tests/ConnectivityManagerTest/AndroidManifest.xml b/core/tests/ConnectivityManagerTest/AndroidManifest.xml
index b116bea..05f8b39 100644
--- a/core/tests/ConnectivityManagerTest/AndroidManifest.xml
+++ b/core/tests/ConnectivityManagerTest/AndroidManifest.xml
@@ -16,7 +16,8 @@
 
 <!-- package name must be unique so suffix with "tests" so package loader doesn't ignore us -->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="com.android.connectivitymanagertest">
+  package="com.android.connectivitymanagertest"
+  android:sharedUserId="com.android.uid.test">
 
     <!-- We add an application tag here just so that we can indicate that
          this package needs to link against the android.test library,
@@ -67,5 +68,9 @@
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
     <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
     <uses-permission android:name="android.permission.WRITE_SETTINGS" />
+    <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
     <uses-permission android:name="android.permission.WAKE_LOCK" />
+    <uses-permission android:name="android.permission.DEVICE_POWER" />
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+
 </manifest>
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerStressTestRunner.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerStressTestRunner.java
index 47f208a..5b76e39 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerStressTestRunner.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerStressTestRunner.java
@@ -19,8 +19,8 @@
 import android.os.Bundle;
 import android.test.InstrumentationTestRunner;
 import android.test.InstrumentationTestSuite;
-import android.util.Log;
 import com.android.connectivitymanagertest.stress.WifiApStress;
+import com.android.connectivitymanagertest.stress.WifiStressTest;
 
 import junit.framework.TestSuite;
 
@@ -34,10 +34,18 @@
  */
 
 public class ConnectivityManagerStressTestRunner extends InstrumentationTestRunner {
+    public int mSoftapIterations = 100;
+    public int mScanIterations = 100;
+    public int mReconnectIterations = 100;
+    public int mSleepTime = 30 * 1000;  // default sleep time is 30 seconds
+    public String mReconnectSsid = "securenetdhcp";
+    public String mReconnectPassword = "androidwifi";
+
     @Override
     public TestSuite getAllTests() {
         TestSuite suite = new InstrumentationTestSuite(this);
         suite.addTestSuite(WifiApStress.class);
+        suite.addTestSuite(WifiStressTest.class);
         return suite;
     }
 
@@ -49,14 +57,46 @@
     @Override
     public void onCreate(Bundle icicle) {
         super.onCreate(icicle);
-        String stressValue = (String) icicle.get("stressnum");
-        if (stressValue != null) {
-            int iteration = Integer.parseInt(stressValue);
+        String valueStr = (String) icicle.get("softap_iterations");
+        if (valueStr != null) {
+            int iteration = Integer.parseInt(valueStr);
             if (iteration > 0) {
-                numStress = iteration;
+                mSoftapIterations = iteration;
+            }
+        }
+
+        String scanIterationStr = (String) icicle.get("scan_iterations");
+        if (scanIterationStr != null) {
+            int scanIteration = Integer.parseInt(scanIterationStr);
+            if (scanIteration > 0) {
+                mScanIterations = scanIteration;
+            }
+        }
+
+        String ssidStr= (String) icicle.get("reconnect_ssid");
+        if (ssidStr != null) {
+            mReconnectSsid = ssidStr;
+        }
+
+        String passwordStr = (String) icicle.get("reconnect_password");
+        if (passwordStr != null) {
+            mReconnectPassword = passwordStr;
+        }
+
+        String reconnectStr = (String) icicle.get("reconnect_iterations");
+        if (reconnectStr != null) {
+            int iteration = Integer.parseInt(reconnectStr);
+            if (iteration > 0) {
+                mReconnectIterations = iteration;
+            }
+        }
+
+        String sleepTimeStr = (String) icicle.get("sleep_time");
+        if (sleepTimeStr != null) {
+            int sleepTime = Integer.parseInt(sleepTimeStr);
+            if (sleepTime > 0) {
+                mSleepTime = 1000 * sleepTime;
             }
         }
     }
-
-    public int numStress = 100;
 }
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java
index 2888696..af74c6f 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java
@@ -76,6 +76,7 @@
     public String mBssid;
     public String mPowerSsid = "GoogleGuest"; //Default power SSID
     private Context mContext;
+    public boolean scanResultAvailable = false;
 
     /*
      * Control Wifi States
@@ -142,6 +143,7 @@
             String action = intent.getAction();
             Log.v("WifiReceiver", "onReceive() is calleld with " + intent);
             if (action.equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
+                log("scan results are available");
                 notifyScanResult();
             } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
                 mWifiNetworkInfo =
@@ -174,6 +176,7 @@
 
     public ConnectivityManagerTestActivity() {
         mState = State.UNKNOWN;
+        scanResultAvailable = false;
     }
 
     @Override
@@ -267,6 +270,7 @@
     private void notifyScanResult() {
         synchronized (this) {
             log("notify that scan results are available");
+            scanResultAvailable = true;
             this.notify();
         }
     }
@@ -328,6 +332,8 @@
         long startTime = System.currentTimeMillis();
         while (true) {
             if ((System.currentTimeMillis() - startTime) > timeout) {
+                log("waitForNetworkState time out, the state of network type " + networkType +
+                        " is: " + mCM.getNetworkInfo(networkType).getState());
                 if (mCM.getNetworkInfo(networkType).getState() != expectedState) {
                     return false;
                 } else {
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiApStress.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiApStress.java
index cc53ddc..21ab0e6 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiApStress.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiApStress.java
@@ -19,25 +19,36 @@
 
 import com.android.connectivitymanagertest.ConnectivityManagerStressTestRunner;
 import com.android.connectivitymanagertest.ConnectivityManagerTestActivity;
-import com.android.connectivitymanagertest.ConnectivityManagerTestRunner;
 
+import android.content.Context;
 import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiConfiguration.KeyMgmt;
 import android.net.wifi.WifiConfiguration.AuthAlgorithm;
+import android.net.wifi.WifiManager;
+import android.os.Environment;
+import android.os.PowerManager;
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.suitebuilder.annotation.LargeTest;
 import android.util.Log;
 
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+
 /**
  * Stress the wifi driver as access point.
  */
 public class WifiApStress
     extends ActivityInstrumentationTestCase2<ConnectivityManagerTestActivity> {
     private final static String TAG = "WifiApStress";
-    private ConnectivityManagerTestActivity mAct;
     private static String NETWORK_ID = "AndroidAPTest";
     private static String PASSWD = "androidwifi";
-    private int max_num;
+    private final static String OUTPUT_FILE = "WifiApStressOutput.txt";
+    private ConnectivityManagerTestActivity mAct;
+    private int iterations;
+    private PowerManager.WakeLock mWakelock = null;
+    private BufferedWriter mOutputWriter = null;
+    private int mLastIteration = 0;
 
     public WifiApStress() {
         super(ConnectivityManagerTestActivity.class);
@@ -47,11 +58,27 @@
     public void setUp() throws Exception {
         super.setUp();
         mAct = getActivity();
-        max_num = ((ConnectivityManagerStressTestRunner)getInstrumentation()).numStress;
+        ConnectivityManagerStressTestRunner mRunner =
+            (ConnectivityManagerStressTestRunner)getInstrumentation();
+        iterations = mRunner.mSoftapIterations;
+        PowerManager pm =
+            (PowerManager)mRunner.getContext().getSystemService(Context.POWER_SERVICE);
+        mWakelock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "wifiApStress");
+        mWakelock.acquire();
     }
 
     @Override
     public void tearDown() throws Exception {
+        if (mWakelock != null) {
+            mWakelock.release();
+        }
+        // write the total number of iterations into output file
+        mOutputWriter = new BufferedWriter(new FileWriter(new File(
+                Environment.getExternalStorageDirectory(), OUTPUT_FILE)));
+        mOutputWriter.write(String.format("iteration %d out of %d"
+                + "\n", mLastIteration, iterations));
+        mOutputWriter.flush();
+        mOutputWriter.close();
         super.tearDown();
     }
 
@@ -67,15 +94,18 @@
         if (mAct.mWifiManager.isWifiEnabled()) {
             mAct.disableWifi();
         }
-        for (int i = 0; i < max_num; i++) {
+        int i;
+        for (i = 0; i < iterations; i++) {
             Log.v(TAG, "iteration: " + i);
+            mLastIteration = i;
             // enable Wifi tethering
             assertTrue(mAct.mWifiManager.setWifiApEnabled(config, true));
             // Wait for wifi ap state to be ENABLED
-            assertTrue(mAct.waitForWifiAPState(mAct.mWifiManager.WIFI_AP_STATE_ENABLED,
-                    mAct.LONG_TIMEOUT));
+            assertTrue(mAct.waitForWifiAPState(WifiManager.WIFI_AP_STATE_ENABLED,
+                    ConnectivityManagerTestActivity.LONG_TIMEOUT));
             // Wait for wifi tethering result
-            assertEquals(mAct.SUCCESS, mAct.waitForTetherStateChange(2*mAct.SHORT_TIMEOUT));
+            assertEquals(ConnectivityManagerTestActivity.SUCCESS,
+                    mAct.waitForTetherStateChange(2*ConnectivityManagerTestActivity.SHORT_TIMEOUT));
             // Allow the wifi tethering to be enabled for 10 seconds
             try {
                 Thread.sleep(2 * ConnectivityManagerTestActivity.SHORT_TIMEOUT);
@@ -84,6 +114,9 @@
             }
             assertTrue(mAct.mWifiManager.setWifiApEnabled(config, false));
         }
+        if (i == iterations) {
+            mLastIteration = iterations;
+        }
     }
 
 }
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java
new file mode 100644
index 0000000..0756a72
--- /dev/null
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java
@@ -0,0 +1,301 @@
+/*
+ * Copyright (C) 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.connectivitymanagertest.stress;
+
+import com.android.connectivitymanagertest.ConnectivityManagerStressTestRunner;
+import com.android.connectivitymanagertest.ConnectivityManagerTestActivity;
+
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo.State;
+import android.net.wifi.ScanResult;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiConfiguration.IpAssignment;
+import android.net.wifi.WifiConfiguration.KeyMgmt;
+import android.net.wifi.WifiConfiguration.ProxySettings;
+import android.net.wifi.WifiManager;
+import android.os.Environment;
+import android.os.PowerManager;
+import android.os.SystemClock;
+import android.provider.Settings;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.LargeTest;
+
+import android.util.Log;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * Stress Wi-Fi connection, scanning and reconnection after sleep.
+ *
+ * To run this stress test suite, type
+ * adb shell am instrument -e class com.android.connectivitymanagertest.stress.WifiStressTest
+ *                  -w com.android.connectivitymanagertest/.ConnectivityManagerStressTestRunner
+ */
+public class WifiStressTest
+    extends ActivityInstrumentationTestCase2<ConnectivityManagerTestActivity> {
+    private final static String TAG = "WifiStressTest";
+
+    /**
+     * Wi-Fi idle time for default sleep policy
+     */
+    private final static long WIFI_IDLE_MS = 5 * 1000;
+
+    /**
+     * The delay for Wi-Fi to get into idle, after screen off + WIFI_IDEL_MS + WIFI_IDLE_DELAY
+     * the Wi-Fi should be in idle mode and device should be in cellular mode.
+     */
+    private final static long WIFI_IDLE_DELAY = 3 * 1000;
+
+    private final static String OUTPUT_FILE = "WifiStressTestOutput.txt";
+    private ConnectivityManagerTestActivity mAct;
+    private int mReconnectIterations;
+    private int mWifiSleepTime;
+    private int mScanIterations;
+    private String mSsid;
+    private String mPassword;
+    private ConnectivityManagerStressTestRunner mRunner;
+    private PowerManager.WakeLock wl = null;
+    private BufferedWriter mOutputWriter = null;
+
+    public WifiStressTest() {
+        super(ConnectivityManagerTestActivity.class);
+    }
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        mAct = getActivity();
+        mRunner = (ConnectivityManagerStressTestRunner) getInstrumentation();
+        mReconnectIterations = mRunner.mReconnectIterations;
+        mSsid = mRunner.mReconnectSsid;
+        mPassword = mRunner.mReconnectPassword;
+        mScanIterations = mRunner.mScanIterations;
+        mWifiSleepTime = mRunner.mSleepTime;
+        wl = null;
+        mOutputWriter = new BufferedWriter(new FileWriter(new File(
+                Environment.getExternalStorageDirectory(), OUTPUT_FILE), true));
+        if (!mAct.mWifiManager.isWifiEnabled()) {
+            if (!mAct.enableWifi()) {
+                tearDown();
+                fail("enable wifi failed.");
+            }
+            sleep(ConnectivityManagerTestActivity.SHORT_TIMEOUT,
+                    "Interruped while waiting for wifi on");
+        }
+    }
+
+    @Override
+    public void tearDown() throws Exception {
+        log("tearDown()");
+        if ((wl != null) && wl.isHeld()) {
+            wl.release();
+        }
+        if (mOutputWriter != null) {
+            mOutputWriter.close();
+        }
+        super.tearDown();
+    }
+
+    private void writeOutput(String s) {
+        log("write message: " + s);
+        if (mOutputWriter == null) {
+            log("no writer attached to file " + OUTPUT_FILE);
+            return;
+        }
+        try {
+            mOutputWriter.write(s + "\n");
+            mOutputWriter.flush();
+        } catch (IOException e) {
+            log("failed to write output.");
+        }
+    }
+
+    private void turnScreenOff() {
+        log("Turn screen off");
+        if (wl != null) {
+            log("release wake lock");
+            wl.release();
+        }
+        PowerManager pm =
+            (PowerManager) mRunner.getContext().getSystemService(Context.POWER_SERVICE);
+        pm.goToSleep(SystemClock.uptimeMillis() + 50);
+    }
+
+    private void turnScreenOn() {
+        log("Turn screen on");
+        PowerManager pm =
+            (PowerManager)mRunner.getContext().getSystemService(Context.POWER_SERVICE);
+        wl = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP,
+                "wifiStressTest");
+        wl.acquire();
+    }
+
+    public void log(String message) {
+        Log.v(TAG, message);
+    }
+
+    private void sleep(long sometime, String errorMsg) {
+        try {
+            Thread.sleep(sometime);
+        } catch (InterruptedException e) {
+            fail(errorMsg);
+        }
+    }
+
+    /**
+     *  Stress Wifi Scanning
+     *  TODO: test the scanning quality for each frequency band
+     */
+    @LargeTest
+    public void testWifiScanning() {
+        int scanTimeSum = 0;
+        int i;
+        int averageScanTime = 0;
+        int ssidAppearInScanResultsCount = 0; // count times of given ssid appear in scan results.
+        for (i = 0; i < mScanIterations; i++) {
+            log("testWifiScanning: iteration: " + i);
+            writeOutput(String.format("scan iteration %d out of %d",
+                    i, mScanIterations));
+            writeOutput(String.format("average scanning time is %d", averageScanTime));
+            writeOutput(String.format("ssid appear %d out of %d scan iterations",
+                    ssidAppearInScanResultsCount, mScanIterations));
+            long startTime = System.currentTimeMillis();
+            mAct.scanResultAvailable = false;
+            assertTrue("start scan failed", mAct.mWifiManager.startScanActive());
+            while (true) {
+                if ((System.currentTimeMillis() - startTime) >
+                ConnectivityManagerTestActivity.WIFI_SCAN_TIMEOUT) {
+                    fail("Wifi scanning takes more than " +
+                            ConnectivityManagerTestActivity.WIFI_SCAN_TIMEOUT + " ms");
+                }
+                synchronized(mAct) {
+                    try {
+                        mAct.wait(ConnectivityManagerTestActivity.WAIT_FOR_SCAN_RESULT);
+                    } catch (InterruptedException e) {
+                        e.printStackTrace();
+                    }
+                    if (mAct.scanResultAvailable) {
+                        long scanTime = (System.currentTimeMillis() - startTime);
+                        scanTimeSum += scanTime;
+                        averageScanTime = scanTimeSum/mScanIterations;
+                        log("average scanning time: " + averageScanTime);
+                        break;
+                    }
+                }
+            }
+            if ((mAct.mWifiManager.getScanResults() == null) ||
+                    (mAct.mWifiManager.getScanResults().size() <= 0)) {
+                fail("Scan results are empty ");
+            }
+
+            List<ScanResult> netList = mAct.mWifiManager.getScanResults();
+            if (netList != null) {
+                log("size of scan result list: " + netList.size());
+                for (int s = 0; s < netList.size(); s++) {
+                    ScanResult sr= netList.get(s);
+                    log(String.format("scan result for %s is: %s", sr.SSID, sr.toString()));
+                    log(String.format("signal level for %s is %d ", sr.SSID, sr.level));
+                    if (sr.SSID.equals(mSsid)) {
+                        ssidAppearInScanResultsCount += 1;
+                        log("Number of times " + mSsid + " appear in the scan list: " +
+                                ssidAppearInScanResultsCount);
+                        break;
+                    }
+                }
+            }
+        }
+        if (i == mScanIterations) {
+            writeOutput(String.format("scan iteration %d out of %d",
+                    i, mScanIterations));
+            writeOutput(String.format("average scanning time is %d", averageScanTime));
+            writeOutput(String.format("ssid appear %d out of %d scan iterations",
+                    ssidAppearInScanResultsCount, mScanIterations));
+        }
+    }
+
+    // Stress Wifi reconnection to secure net after sleep
+    @LargeTest
+    public void testWifiReconnectionAfterSleep() {
+        int value = Settings.System.getInt(mRunner.getContext().getContentResolver(),
+                Settings.System.WIFI_SLEEP_POLICY, -1);
+        if (value < 0) {
+            Settings.System.putInt(mRunner.getContext().getContentResolver(),
+                    Settings.System.WIFI_SLEEP_POLICY, Settings.System.WIFI_SLEEP_POLICY_DEFAULT);
+            log("set wifi sleep policy to default value");
+        }
+        Settings.Secure.putLong(mRunner.getContext().getContentResolver(),
+                Settings.Secure.WIFI_IDLE_MS, WIFI_IDLE_MS);
+
+        // Connect to a Wi-Fi network
+        turnScreenOn();
+        WifiConfiguration config = new WifiConfiguration();
+        config.SSID = mSsid;
+        config.allowedKeyManagement.set(KeyMgmt.WPA_PSK);
+        if (mPassword.matches("[0-9A-Fa-f]{64}")) {
+            config.preSharedKey = mPassword;
+        } else {
+            config.preSharedKey = '"' + mPassword + '"';
+        }
+        config.ipAssignment = IpAssignment.DHCP;
+        config.proxySettings = ProxySettings.NONE;
+
+        assertTrue("Failed to connect to Wi-Fi network: " + mSsid,
+                mAct.connectToWifiWithConfiguration(config));
+        assertTrue(mAct.waitForWifiState(WifiManager.WIFI_STATE_ENABLED,
+                ConnectivityManagerTestActivity.SHORT_TIMEOUT));
+        assertTrue(mAct.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
+                ConnectivityManagerTestActivity.LONG_TIMEOUT));
+        int i;
+        for (i = 0; i < mReconnectIterations; i++) {
+            // 1. Put device into sleep
+            // 2. Wait for the device to sleep for sometime, very 3G is connected
+            // 3. Wake up the device
+            writeOutput(String.format("reconnection after sleep iteration %d out of %d",
+                    i, mReconnectIterations));
+            log("iteration: " + i);
+            turnScreenOff();
+            PowerManager pm =
+                (PowerManager)mRunner.getContext().getSystemService(Context.POWER_SERVICE);
+            assertFalse(pm.isScreenOn());
+            sleep(WIFI_IDLE_MS + WIFI_IDLE_DELAY, "Interruped while wait for wifi to be idle");
+            assertTrue("Wait for Wi-Fi to idle timeout",
+                    mAct.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.DISCONNECTED,
+                    ConnectivityManagerTestActivity.SHORT_TIMEOUT));
+            assertTrue("Wait for cellular connection timeout",
+                    mAct.waitForNetworkState(ConnectivityManager.TYPE_MOBILE, State.CONNECTED,
+                    ConnectivityManagerTestActivity.LONG_TIMEOUT));
+            sleep(mWifiSleepTime + WIFI_IDLE_DELAY, "Interrupted while device is in sleep mode");
+            // Turn screen on again
+            turnScreenOn();
+            assertTrue("Wait for Wi-Fi enable timeout after wake up",
+                    mAct.waitForWifiState(WifiManager.WIFI_STATE_ENABLED,
+                    ConnectivityManagerTestActivity.SHORT_TIMEOUT));
+            assertTrue("Wait for Wi-Fi connection timeout after wake up",
+                    mAct.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
+                    ConnectivityManagerTestActivity.LONG_TIMEOUT));
+        }
+        if (i == mReconnectIterations) {
+            writeOutput(String.format("reconnection after sleep iteration %d out of %d",
+                    i, mReconnectIterations));
+        }
+    }
+}
diff --git a/data/keyboards/Generic.kcm b/data/keyboards/Generic.kcm
index 24b485d..14d7c80 100644
--- a/data/keyboards/Generic.kcm
+++ b/data/keyboards/Generic.kcm
@@ -42,7 +42,9 @@
     label:                              'C'
     base:                               'c'
     shift, capslock:                    'C'
-    ctrl, alt, meta:                    none
+    alt:                                '\u00e7'
+    shift+alt:                          '\u00c7'
+    ctrl, meta:                         none
 }
 
 key D {
@@ -56,7 +58,8 @@
     label:                              'E'
     base:                               'e'
     shift, capslock:                    'E'
-    ctrl, alt, meta:                    none
+    alt:                                '\u0301'
+    ctrl, meta:                         none
 }
 
 key F {
@@ -84,7 +87,8 @@
     label:                              'I'
     base:                               'i'
     shift, capslock:                    'I'
-    ctrl, alt, meta:                    none
+    alt:                                '\u0302'
+    ctrl, meta:                         none
 }
 
 key J {
@@ -119,7 +123,8 @@
     label:                              'N'
     base:                               'n'
     shift, capslock:                    'N'
-    ctrl, alt, meta:                    none
+    alt:                                '\u0303'
+    ctrl, meta:                         none
 }
 
 key O {
@@ -154,7 +159,8 @@
     label:                              'S'
     base:                               's'
     shift, capslock:                    'S'
-    ctrl, alt, meta:                    none
+    alt:                                '\u00df'
+    ctrl, meta:                         none
 }
 
 key T {
@@ -168,7 +174,8 @@
     label:                              'U'
     base:                               'u'
     shift, capslock:                    'U'
-    ctrl, alt, meta:                    none
+    alt:                                '\u0308'
+    ctrl, meta:                         none
 }
 
 key V {
@@ -253,6 +260,7 @@
     base:                               '6'
     shift:                              '^'
     ctrl, alt, meta:                    none
+    alt+shift:                          '\u0302'
 }
 
 key 7 {
@@ -279,7 +287,8 @@
 key SPACE {
     label:                              ' '
     base:                               ' '
-    ctrl, alt, meta:                    none
+    ctrl, alt:                          none
+    meta:                               fallback SEARCH
 }
 
 key ENTER {
@@ -291,7 +300,8 @@
 key TAB {
     label:                              '\t'
     base:                               '\t'
-    ctrl, alt, meta:                    none
+    ctrl, alt:                          none
+    meta:                               fallback APP_SWITCH
 }
 
 key COMMA {
@@ -319,7 +329,9 @@
     label, number:                      '`'
     base:                               '`'
     shift:                              '~'
-    ctrl, alt, meta:                    none
+    alt:                                '\u0300'
+    alt+shift:                          '\u0303'
+    ctrl, meta:                         none
 }
 
 key MINUS {
@@ -525,3 +537,11 @@
     label, number:                      '+'
     base:                               '+'
 }
+
+### Non-printing keys ###
+
+key ESCAPE {
+    base:                               fallback BACK
+    meta:                               fallback HOME
+    alt:                                fallback MENU
+}
diff --git a/data/keyboards/Vendor_05ac_Product_0239.kl b/data/keyboards/Vendor_05ac_Product_0239.kl
index 5234d58..6bd3753 100644
--- a/data/keyboards/Vendor_05ac_Product_0239.kl
+++ b/data/keyboards/Vendor_05ac_Product_0239.kl
@@ -104,7 +104,7 @@
 key 113   VOLUME_MUTE
 key 114   VOLUME_DOWN
 key 115   VOLUME_UP
-# key 120  switch applications
+key 120   APP_SWITCH
 key 125   META_LEFT
 key 126   META_RIGHT
 key 161   MEDIA_EJECT
diff --git a/data/keyboards/Vendor_22b8_Product_093d.kl b/data/keyboards/Vendor_22b8_Product_093d.kl
index 87b3c32..2749c5b 100644
--- a/data/keyboards/Vendor_22b8_Product_093d.kl
+++ b/data/keyboards/Vendor_22b8_Product_093d.kl
@@ -12,6 +12,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+#
+# Motorola Bluetooth Wireless Keyboard.
+#
+
 key 1     BACK
 key 2     1
 key 3     2
diff --git a/data/keyboards/Virtual.kcm b/data/keyboards/Virtual.kcm
index 8d3c7ac..0ce4a68 100644
--- a/data/keyboards/Virtual.kcm
+++ b/data/keyboards/Virtual.kcm
@@ -39,7 +39,9 @@
     label:                              'C'
     base:                               'c'
     shift, capslock:                    'C'
-    ctrl, alt, meta:                    none
+    alt:                                '\u00e7'
+    shift+alt:                          '\u00c7'
+    ctrl, meta:                         none
 }
 
 key D {
@@ -53,7 +55,8 @@
     label:                              'E'
     base:                               'e'
     shift, capslock:                    'E'
-    ctrl, alt, meta:                    none
+    alt:                                '\u0301'
+    ctrl, meta:                         none
 }
 
 key F {
@@ -81,7 +84,8 @@
     label:                              'I'
     base:                               'i'
     shift, capslock:                    'I'
-    ctrl, alt, meta:                    none
+    alt:                                '\u0302'
+    ctrl, meta:                         none
 }
 
 key J {
@@ -116,7 +120,8 @@
     label:                              'N'
     base:                               'n'
     shift, capslock:                    'N'
-    ctrl, alt, meta:                    none
+    alt:                                '\u0303'
+    ctrl, meta:                         none
 }
 
 key O {
@@ -151,7 +156,8 @@
     label:                              'S'
     base:                               's'
     shift, capslock:                    'S'
-    ctrl, alt, meta:                    none
+    alt:                                '\u00df'
+    ctrl, meta:                         none
 }
 
 key T {
@@ -165,7 +171,8 @@
     label:                              'U'
     base:                               'u'
     shift, capslock:                    'U'
-    ctrl, alt, meta:                    none
+    alt:                                '\u0308'
+    ctrl, meta:                         none
 }
 
 key V {
@@ -250,6 +257,7 @@
     base:                               '6'
     shift:                              '^'
     ctrl, alt, meta:                    none
+    alt+shift:                          '\u0302'
 }
 
 key 7 {
@@ -276,7 +284,8 @@
 key SPACE {
     label:                              ' '
     base:                               ' '
-    ctrl, alt, meta:                    none
+    ctrl, alt:                          none
+    meta:                               fallback SEARCH
 }
 
 key ENTER {
@@ -288,7 +297,8 @@
 key TAB {
     label:                              '\t'
     base:                               '\t'
-    ctrl, alt, meta:                    none
+    ctrl, alt:                          none
+    meta:                               fallback APP_SWITCH
 }
 
 key COMMA {
@@ -316,7 +326,9 @@
     label, number:                      '`'
     base:                               '`'
     shift:                              '~'
-    ctrl, alt, meta:                    none
+    alt:                                '\u0300'
+    alt+shift:                          '\u0303'
+    ctrl, meta:                         none
 }
 
 key MINUS {
@@ -522,3 +534,11 @@
     label, number:                      '+'
     base:                               '+'
 }
+
+### Non-printing keys ###
+
+key ESCAPE {
+    base:                               fallback BACK
+    meta:                               fallback HOME
+    alt:                                fallback MENU
+}
diff --git a/graphics/java/android/graphics/BitmapFactory.java b/graphics/java/android/graphics/BitmapFactory.java
index 8450c3a..66f8f70 100644
--- a/graphics/java/android/graphics/BitmapFactory.java
+++ b/graphics/java/android/graphics/BitmapFactory.java
@@ -210,7 +210,6 @@
          * expense of the decoding speed. Currently the field only affects JPEG
          * decode, in the case of which a more accurate, but slightly slower,
          * IDCT method will be used instead.
-         * @hide
          */
         public boolean inPreferQualityOverSpeed;
 
diff --git a/include/media/IStreamSource.h b/include/media/IStreamSource.h
index 6291124..4b698e6 100644
--- a/include/media/IStreamSource.h
+++ b/include/media/IStreamSource.h
@@ -22,6 +22,7 @@
 
 namespace android {
 
+struct AMessage;
 struct IMemory;
 struct IStreamListener;
 
@@ -38,13 +39,14 @@
     DECLARE_META_INTERFACE(StreamListener);
 
     enum Command {
-        FLUSH,
+        EOS,
         DISCONTINUITY,
-        EOS
     };
 
     virtual void queueBuffer(size_t index, size_t size) = 0;
-    virtual void queueCommand(Command cmd) = 0;
+
+    virtual void issueCommand(
+            Command cmd, bool synchronous, const sp<AMessage> &msg = NULL) = 0;
 };
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/include/media/stagefright/OMXCodec.h b/include/media/stagefright/OMXCodec.h
index 0aba347..d37c22d 100644
--- a/include/media/stagefright/OMXCodec.h
+++ b/include/media/stagefright/OMXCodec.h
@@ -121,10 +121,16 @@
         kOutputBuffersAreUnreadable           = 8192,
     };
 
+    enum BufferStatus {
+        OWNED_BY_US,
+        OWNED_BY_COMPONENT,
+        OWNED_BY_NATIVE_WINDOW,
+        OWNED_BY_CLIENT,
+    };
+
     struct BufferInfo {
         IOMX::buffer_id mBuffer;
-        bool mOwnedByComponent;
-        bool mOwnedByNativeWindow;
+        BufferStatus mStatus;
         sp<IMemory> mMem;
         size_t mSize;
         void *mData;
@@ -248,9 +254,9 @@
 
     status_t freeBuffer(OMX_U32 portIndex, size_t bufIndex);
 
-    void drainInputBuffer(IOMX::buffer_id buffer);
+    bool drainInputBuffer(IOMX::buffer_id buffer);
     void fillOutputBuffer(IOMX::buffer_id buffer);
-    void drainInputBuffer(BufferInfo *info);
+    bool drainInputBuffer(BufferInfo *info);
     void fillOutputBuffer(BufferInfo *info);
 
     void drainInputBuffers();
diff --git a/include/media/stagefright/foundation/AMessage.h b/include/media/stagefright/foundation/AMessage.h
index c674cba..2fbdddc 100644
--- a/include/media/stagefright/foundation/AMessage.h
+++ b/include/media/stagefright/foundation/AMessage.h
@@ -26,10 +26,14 @@
 namespace android {
 
 struct AString;
+struct Parcel;
 
 struct AMessage : public RefBase {
     AMessage(uint32_t what = 0, ALooper::handler_id target = 0);
 
+    static sp<AMessage> FromParcel(const Parcel &parcel);
+    void writeToParcel(Parcel *parcel) const;
+
     void setWhat(uint32_t what);
     uint32_t what() const;
 
diff --git a/include/ui/GraphicBuffer.h b/include/ui/GraphicBuffer.h
index c446633..aa65d93 100644
--- a/include/ui/GraphicBuffer.h
+++ b/include/ui/GraphicBuffer.h
@@ -91,12 +91,15 @@
     status_t lock(uint32_t usage, const Rect& rect, void** vaddr);
     status_t lock(GGLSurface* surface, uint32_t usage);
     status_t unlock();
-    
+
     android_native_buffer_t* getNativeBuffer() const;
     
     void setIndex(int index);
     int getIndex() const;
 
+    // for debugging
+    static void dumpAllocationsToSystemLog();
+
 private:
     virtual ~GraphicBuffer();
 
diff --git a/include/ui/GraphicBufferAllocator.h b/include/ui/GraphicBufferAllocator.h
index 54b8236..dffa788 100644
--- a/include/ui/GraphicBufferAllocator.h
+++ b/include/ui/GraphicBufferAllocator.h
@@ -68,6 +68,7 @@
     status_t free(buffer_handle_t handle);
 
     void dump(String8& res) const;
+    static void dumpToSystemLog();
 
 private:
     struct alloc_rec_t {
diff --git a/include/ui/InputDispatcher.h b/include/ui/InputDispatcher.h
index b621680..7305601 100644
--- a/include/ui/InputDispatcher.h
+++ b/include/ui/InputDispatcher.h
@@ -306,9 +306,10 @@
     virtual bool interceptKeyBeforeDispatching(const sp<InputChannel>& inputChannel,
             const KeyEvent* keyEvent, uint32_t policyFlags) = 0;
 
-    /* Allows the policy a chance to perform default processing for an unhandled key. */
+    /* Allows the policy a chance to perform default processing for an unhandled key.
+     * Returns an alternate keycode to redispatch as a fallback, or 0 to give up. */
     virtual bool dispatchUnhandledKey(const sp<InputChannel>& inputChannel,
-            const KeyEvent* keyEvent, uint32_t policyFlags) = 0;
+            const KeyEvent* keyEvent, uint32_t policyFlags, KeyEvent* outFallbackKeyEvent) = 0;
 
     /* Notifies the policy about switch events.
      */
@@ -735,6 +736,7 @@
             CANCEL_ALL_EVENTS = 0,
             CANCEL_POINTER_EVENTS = 1,
             CANCEL_NON_POINTER_EVENTS = 2,
+            CANCEL_FALLBACK_EVENTS = 3,
         };
 
         InputState();
@@ -771,6 +773,7 @@
             int32_t source;
             int32_t keyCode;
             int32_t scanCode;
+            int32_t flags;
             nsecs_t downTime;
         };
 
@@ -790,7 +793,10 @@
         Vector<KeyMemento> mKeyMementos;
         Vector<MotionMemento> mMotionMementos;
 
-        static bool shouldCancelEvent(int32_t eventSource, CancelationOptions options);
+        static bool shouldCancelKey(const KeyMemento& memento,
+                CancelationOptions options);
+        static bool shouldCancelMotion(const MotionMemento& memento,
+                CancelationOptions options);
     };
 
     /* Manages the dispatch state associated with a single input channel. */
diff --git a/include/ui/InputReader.h b/include/ui/InputReader.h
index 8ec5421..b466ff1 100644
--- a/include/ui/InputReader.h
+++ b/include/ui/InputReader.h
@@ -402,7 +402,6 @@
     } mLocked;
 
     void initializeLocked();
-    void initializeLedStateLocked(LockedState::LedState& ledState, int32_t led);
 
     void configureParameters();
     void dumpParameters(String8& dump);
@@ -414,6 +413,8 @@
 
     ssize_t findKeyDownLocked(int32_t scanCode);
 
+    void resetLedStateLocked();
+    void initializeLedStateLocked(LockedState::LedState& ledState, int32_t led);
     void updateLedStateLocked(bool reset);
     void updateLedStateForModifierLocked(LockedState::LedState& ledState, int32_t led,
             int32_t modifier, bool reset);
diff --git a/include/ui/InputTransport.h b/include/ui/InputTransport.h
index 7efb6cc..119db81 100644
--- a/include/ui/InputTransport.h
+++ b/include/ui/InputTransport.h
@@ -256,7 +256,7 @@
      * Returns WOULD_BLOCK if there is no signal present.
      * Other errors probably indicate that the channel is broken.
      */
-    status_t receiveFinishedSignal(bool& outHandled);
+    status_t receiveFinishedSignal(bool* outHandled);
 
 private:
     sp<InputChannel> mChannel;
diff --git a/include/ui/KeyCharacterMap.h b/include/ui/KeyCharacterMap.h
index a1ccb37..10a3810 100644
--- a/include/ui/KeyCharacterMap.h
+++ b/include/ui/KeyCharacterMap.h
@@ -44,6 +44,12 @@
         KEYBOARD_TYPE_SPECIAL_FUNCTION = 5,
     };
 
+    // Substitute key code and meta state for fallback action.
+    struct FallbackAction {
+        int32_t keyCode;
+        int32_t metaState;
+    };
+
     ~KeyCharacterMap();
 
     static status_t load(const String8& filename, KeyCharacterMap** outMap);
@@ -67,6 +73,13 @@
      */
     char16_t getCharacter(int32_t keyCode, int32_t metaState) const;
 
+    /* Gets the fallback action to use by default if the application does not
+     * handle the specified key.
+     * Returns true if an action was available, false if none.
+     */
+    bool getFallbackAction(int32_t keyCode, int32_t metaState,
+            FallbackAction* outFallbackAction) const;
+
     /* Gets the first matching Unicode character that can be generated by the key,
      * preferring the one with the specified meta key modifiers.
      * Returns 0 if no matching character is generated.
@@ -155,6 +168,10 @@
 
     KeyCharacterMap();
 
+    bool getKey(int32_t keyCode, const Key** outKey) const;
+    bool getKeyBehavior(int32_t keyCode, int32_t metaState,
+            const Key** outKey, const Behavior** outBehavior) const;
+
     bool findKey(char16_t ch, int32_t* outKeyCode, int32_t* outMetaState) const;
 
     static void addKey(Vector<KeyEvent>& outEvents,
diff --git a/include/ui/KeycodeLabels.h b/include/ui/KeycodeLabels.h
index be7db1f..9b1a897 100755
--- a/include/ui/KeycodeLabels.h
+++ b/include/ui/KeycodeLabels.h
@@ -211,6 +211,7 @@
     { "PROG_GREEN", 184 },
     { "PROG_YELLOW", 185 },
     { "PROG_BLUE", 186 },
+    { "APP_SWITCH", 187 },
 
     // NOTE: If you add a new keycode here you must also add it to several other files.
     //       Refer to frameworks/base/core/java/android/view/KeyEvent.java for the full list.
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index fc14777..1a89ca0 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -954,11 +954,11 @@
                 mSnapshot->region && mesh->hasEmptyQuads) {
             const size_t count = mesh->quads.size();
             for (size_t i = 0; i < count; i++) {
-                Rect bounds = mesh->quads.itemAt(i);
+                const Rect& bounds = mesh->quads.itemAt(i);
                 if (pureTranslate) {
                     const float x = (int) floorf(bounds.left + 0.5f);
                     const float y = (int) floorf(bounds.top + 0.5f);
-                    dirtyLayer(x, y, x + bounds.getWidth(), y + bounds.getBottom(),
+                    dirtyLayer(x, y, x + bounds.getWidth(), y + bounds.getHeight(),
                             *mSnapshot->transform);
                 } else {
                     dirtyLayer(bounds.left, bounds.top, bounds.right, bounds.bottom,
diff --git a/libs/hwui/Patch.cpp b/libs/hwui/Patch.cpp
index 17b1d86..e5cb67b 100644
--- a/libs/hwui/Patch.cpp
+++ b/libs/hwui/Patch.cpp
@@ -35,7 +35,7 @@
         mXCount(xCount), mYCount(yCount), mEmptyQuads(emptyQuads) {
     // Initialized with the maximum number of vertices we will need
     // 2 triangles per patch, 3 vertices per triangle
-    const int maxVertices = ((xCount + 1) * (yCount + 1) - emptyQuads) * 2 * 3;
+    uint32_t maxVertices = ((xCount + 1) * (yCount + 1) - emptyQuads) * 2 * 3;
     mVertices = new TextureVertex[maxVertices];
     mUploaded = false;
 
@@ -160,7 +160,7 @@
         float y2 = 0.0f;
         if (i & 1) {
             const float segment = stepY - previousStepY;
-            y2 = y1 + segment * stretchY;
+            y2 = y1 + floorf(segment * stretchY + 0.5f);
         } else {
             y2 = y1 + stepY - previousStepY;
         }
@@ -206,7 +206,7 @@
         float x2 = 0.0f;
         if (i & 1) {
             const float segment = stepX - previousStepX;
-            x2 = x1 + segment * stretchX;
+            x2 = x1 + floorf(segment * stretchX + 0.5f);
         } else {
             x2 = x1 + stepX - previousStepX;
         }
@@ -226,7 +226,7 @@
 void Patch::generateQuad(TextureVertex*& vertex, float x1, float y1, float x2, float y2,
             float u1, float v1, float u2, float v2, uint32_t& quadCount) {
     const uint32_t oldQuadCount = quadCount;
-    const bool valid = fabs(x2 - x1) > 0.9999f && fabs(y2 - y1) > 0.9999f;
+    const bool valid = x2 - x1 > 0.9999f && y2 - y1 > 0.9999f;
     if (valid) {
         quadCount++;
     }
diff --git a/libs/hwui/Patch.h b/libs/hwui/Patch.h
index 16ad86d..0f0ffa2 100644
--- a/libs/hwui/Patch.h
+++ b/libs/hwui/Patch.h
@@ -52,9 +52,7 @@
     GLuint meshBuffer;
     uint32_t verticesCount;
     bool hasEmptyQuads;
-#if RENDER_LAYERS_AS_REGIONS
     Vector<Rect> quads;
-#endif
 
 private:
     TextureVertex* mVertices;
diff --git a/libs/hwui/Program.cpp b/libs/hwui/Program.cpp
index baed5fd7..2187f24 100644
--- a/libs/hwui/Program.cpp
+++ b/libs/hwui/Program.cpp
@@ -26,39 +26,53 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 Program::Program(const char* vertex, const char* fragment) {
+    mInitialized = false;
+
     vertexShader = buildShader(vertex, GL_VERTEX_SHADER);
-    fragmentShader = buildShader(fragment, GL_FRAGMENT_SHADER);
+    if (vertexShader) {
 
-    id = glCreateProgram();
-    glAttachShader(id, vertexShader);
-    glAttachShader(id, fragmentShader);
-    glLinkProgram(id);
+        fragmentShader = buildShader(fragment, GL_FRAGMENT_SHADER);
+        if (fragmentShader) {
 
-    GLint status;
-    glGetProgramiv(id, GL_LINK_STATUS, &status);
-    if (status != GL_TRUE) {
-        GLint infoLen = 0;
-        glGetProgramiv(id, GL_INFO_LOG_LENGTH, &infoLen);
-        if (infoLen > 1) {
-            GLchar log[infoLen];
-            glGetProgramInfoLog(id, infoLen, 0, &log[0]);
-            LOGE("Error while linking shaders: %s", log);
+            id = glCreateProgram();
+            glAttachShader(id, vertexShader);
+            glAttachShader(id, fragmentShader);
+            glLinkProgram(id);
+
+            GLint status;
+            glGetProgramiv(id, GL_LINK_STATUS, &status);
+            if (status != GL_TRUE) {
+                LOGE("Error while linking shaders:");
+                GLint infoLen = 0;
+                glGetProgramiv(id, GL_INFO_LOG_LENGTH, &infoLen);
+                if (infoLen > 1) {
+                    GLchar log[infoLen];
+                    glGetProgramInfoLog(id, infoLen, 0, &log[0]);
+                    LOGE("%s", log);
+                }
+                glDeleteShader(vertexShader);
+                glDeleteShader(fragmentShader);
+                glDeleteProgram(id);
+            } else {
+                mInitialized = true;
+            }
         }
-        glDeleteShader(vertexShader);
-        glDeleteShader(fragmentShader);
-        glDeleteProgram(id);
     }
 
     mUse = false;
 
-    position = addAttrib("position");
-    transform = addUniform("transform");
+    if (mInitialized) {
+        position = addAttrib("position");
+        transform = addUniform("transform");
+    }
 }
 
 Program::~Program() {
-    glDeleteShader(vertexShader);
-    glDeleteShader(fragmentShader);
-    glDeleteProgram(id);
+    if (mInitialized) {
+        glDeleteShader(vertexShader);
+        glDeleteShader(fragmentShader);
+        glDeleteProgram(id);
+    }
 }
 
 int Program::addAttrib(const char* name) {
@@ -103,6 +117,7 @@
         glGetShaderInfoLog(shader, sizeof(log), 0, &log[0]);
         LOGE("Error while compiling shader: %s", log);
         glDeleteShader(shader);
+        return 0;
     }
 
     return shader;
diff --git a/libs/hwui/Program.h b/libs/hwui/Program.h
index 5981662..afc6f3d 100644
--- a/libs/hwui/Program.h
+++ b/libs/hwui/Program.h
@@ -70,6 +70,13 @@
     }
 
     /**
+     * Indicates whether this program was correctly compiled and linked.
+     */
+    inline bool isInitialized() const {
+        return mInitialized;
+    }
+
+    /**
      * Binds the program with the specified projection, modelView and
      * transform matrices.
      */
@@ -126,6 +133,7 @@
     KeyedVector<const char*, int> uniforms;
 
     bool mUse;
+    bool mInitialized;
 }; // class Program
 
 }; // namespace uirenderer
diff --git a/libs/hwui/ProgramCache.cpp b/libs/hwui/ProgramCache.cpp
index f2f1adb..0b6c7b5 100644
--- a/libs/hwui/ProgramCache.cpp
+++ b/libs/hwui/ProgramCache.cpp
@@ -298,6 +298,8 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 void ProgramCache::clear() {
+    PROGRAM_LOGD("Clearing program cache");
+
     size_t count = mCache.size();
     for (size_t i = 0; i < count; i++) {
         delete mCache.valueAt(i);
diff --git a/libs/rs/rsScriptC.cpp b/libs/rs/rsScriptC.cpp
index 6587b51..d4edafd 100644
--- a/libs/rs/rsScriptC.cpp
+++ b/libs/rs/rsScriptC.cpp
@@ -378,6 +378,12 @@
 static BCCvoid* symbolLookup(BCCvoid* pContext, const BCCchar* name) {
     const ScriptCState::SymbolTable_t *sym;
     ScriptC *s = (ScriptC *)pContext;
+    if (!strcmp(name, "__isThreadable")) {
+      return (BCCvoid*) s->mEnviroment.mIsThreadable;
+    } else if (!strcmp(name, "__clearThreadable")) {
+      s->mEnviroment.mIsThreadable = false;
+      return NULL;
+    }
     sym = ScriptCState::lookupSymbol(name);
     if (!sym) {
         sym = ScriptCState::lookupSymbolCL(name);
diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp
index 436e064..97312a6 100644
--- a/libs/ui/GraphicBuffer.cpp
+++ b/libs/ui/GraphicBuffer.cpp
@@ -114,6 +114,11 @@
     return mInitCheck;
 }
 
+void GraphicBuffer::dumpAllocationsToSystemLog()
+{
+    GraphicBufferAllocator::dumpToSystemLog();
+}
+
 android_native_buffer_t* GraphicBuffer::getNativeBuffer() const
 {
     return static_cast<android_native_buffer_t*>(
diff --git a/libs/ui/GraphicBufferAllocator.cpp b/libs/ui/GraphicBufferAllocator.cpp
index d51664d..fa46ab7 100644
--- a/libs/ui/GraphicBufferAllocator.cpp
+++ b/libs/ui/GraphicBufferAllocator.cpp
@@ -73,6 +73,13 @@
     result.append(buffer);
 }
 
+void GraphicBufferAllocator::dumpToSystemLog()
+{
+    String8 s;
+    GraphicBufferAllocator::getInstance().dump(s);
+    LOGD("%s", s.string());
+}
+
 status_t GraphicBufferAllocator::alloc(uint32_t w, uint32_t h, PixelFormat format,
         int usage, buffer_handle_t* handle, int32_t* stride)
 {
@@ -104,10 +111,6 @@
         rec.usage = usage;
         rec.size = h * stride[0] * bytesPerPixel(format);
         list.add(*handle, rec);
-    } else {
-        String8 s;
-        dump(s);
-        LOGD("%s", s.string());
     }
 
     return err;
diff --git a/libs/ui/InputDispatcher.cpp b/libs/ui/InputDispatcher.cpp
index f1223f1..1f6a920 100644
--- a/libs/ui/InputDispatcher.cpp
+++ b/libs/ui/InputDispatcher.cpp
@@ -1884,7 +1884,7 @@
         }
 
         bool handled = false;
-        status_t status = connection->inputPublisher.receiveFinishedSignal(handled);
+        status_t status = connection->inputPublisher.receiveFinishedSignal(&handled);
         if (status) {
             LOGE("channel '%s' ~ Failed to receive finished signal.  status=%d",
                     connection->getInputChannelName(), status);
@@ -3039,21 +3039,57 @@
     sp<Connection> connection = commandEntry->connection;
     bool handled = commandEntry->handled;
 
-    if (!handled && !connection->outboundQueue.isEmpty()) {
+    if (!connection->outboundQueue.isEmpty()) {
         DispatchEntry* dispatchEntry = connection->outboundQueue.headSentinel.next;
         if (dispatchEntry->inProgress
                 && dispatchEntry->hasForegroundTarget()
                 && dispatchEntry->eventEntry->type == EventEntry::TYPE_KEY) {
             KeyEntry* keyEntry = static_cast<KeyEntry*>(dispatchEntry->eventEntry);
-            KeyEvent event;
-            initializeKeyEvent(&event, keyEntry);
+            if (!(keyEntry->flags & AKEY_EVENT_FLAG_FALLBACK)) {
+                if (handled) {
+                    // If the application handled a non-fallback key, then immediately
+                    // cancel all fallback keys previously dispatched to the application.
+                    // This behavior will prevent chording with fallback keys (so they cannot
+                    // be used as modifiers) but it will ensure that fallback keys do not
+                    // get stuck.  This takes care of the case where the application does not handle
+                    // the original DOWN so we generate a fallback DOWN but it does handle
+                    // the original UP in which case we would not generate the fallback UP.
+                    synthesizeCancelationEventsForConnectionLocked(connection,
+                            InputState::CANCEL_FALLBACK_EVENTS,
+                            "Application handled a non-fallback event.");
+                } else {
+                    // If the application did not handle a non-fallback key, then ask
+                    // the policy what to do with it.  We might generate a fallback key
+                    // event here.
+                    KeyEvent event;
+                    initializeKeyEvent(&event, keyEntry);
 
-            mLock.unlock();
+                    mLock.unlock();
 
-            mPolicy->dispatchUnhandledKey(connection->inputChannel,
-                    &event, keyEntry->policyFlags);
+                    bool fallback = mPolicy->dispatchUnhandledKey(connection->inputChannel,
+                            &event, keyEntry->policyFlags, &event);
 
-            mLock.lock();
+                    mLock.lock();
+
+                    if (fallback) {
+                        // Restart the dispatch cycle using the fallback key.
+                        keyEntry->eventTime = event.getEventTime();
+                        keyEntry->deviceId = event.getDeviceId();
+                        keyEntry->source = event.getSource();
+                        keyEntry->flags = event.getFlags() | AKEY_EVENT_FLAG_FALLBACK;
+                        keyEntry->keyCode = event.getKeyCode();
+                        keyEntry->scanCode = event.getScanCode();
+                        keyEntry->metaState = event.getMetaState();
+                        keyEntry->repeatCount = event.getRepeatCount();
+                        keyEntry->downTime = event.getDownTime();
+                        keyEntry->syntheticRepeat = false;
+
+                        dispatchEntry->inProgress = false;
+                        startDispatchCycleLocked(now(), connection);
+                        return;
+                    }
+                }
+            }
         }
     }
 
@@ -3371,6 +3407,7 @@
         memento.source = entry->source;
         memento.keyCode = entry->keyCode;
         memento.scanCode = entry->scanCode;
+        memento.flags = entry->flags;
         memento.downTime = entry->downTime;
         return CONSISTENT;
     }
@@ -3453,10 +3490,10 @@
         CancelationOptions options) {
     for (size_t i = 0; i < mKeyMementos.size(); ) {
         const KeyMemento& memento = mKeyMementos.itemAt(i);
-        if (shouldCancelEvent(memento.source, options)) {
+        if (shouldCancelKey(memento, options)) {
             outEvents.push(allocator->obtainKeyEntry(currentTime,
                     memento.deviceId, memento.source, 0,
-                    AKEY_EVENT_ACTION_UP, AKEY_EVENT_FLAG_CANCELED,
+                    AKEY_EVENT_ACTION_UP, memento.flags | AKEY_EVENT_FLAG_CANCELED,
                     memento.keyCode, memento.scanCode, 0, 0, memento.downTime));
             mKeyMementos.removeAt(i);
         } else {
@@ -3466,7 +3503,7 @@
 
     for (size_t i = 0; i < mMotionMementos.size(); ) {
         const MotionMemento& memento = mMotionMementos.itemAt(i);
-        if (shouldCancelEvent(memento.source, options)) {
+        if (shouldCancelMotion(memento, options)) {
             outEvents.push(allocator->obtainMotionEntry(currentTime,
                     memento.deviceId, memento.source, 0,
                     AMOTION_EVENT_ACTION_CANCEL, 0, 0, 0,
@@ -3502,15 +3539,30 @@
     }
 }
 
-bool InputDispatcher::InputState::shouldCancelEvent(int32_t eventSource,
+bool InputDispatcher::InputState::shouldCancelKey(const KeyMemento& memento,
         CancelationOptions options) {
     switch (options) {
-    case CANCEL_POINTER_EVENTS:
-        return eventSource & AINPUT_SOURCE_CLASS_POINTER;
+    case CANCEL_ALL_EVENTS:
     case CANCEL_NON_POINTER_EVENTS:
-        return !(eventSource & AINPUT_SOURCE_CLASS_POINTER);
-    default:
         return true;
+    case CANCEL_FALLBACK_EVENTS:
+        return memento.flags & AKEY_EVENT_FLAG_FALLBACK;
+    default:
+        return false;
+    }
+}
+
+bool InputDispatcher::InputState::shouldCancelMotion(const MotionMemento& memento,
+        CancelationOptions options) {
+    switch (options) {
+    case CANCEL_ALL_EVENTS:
+        return true;
+    case CANCEL_POINTER_EVENTS:
+        return memento.source & AINPUT_SOURCE_CLASS_POINTER;
+    case CANCEL_NON_POINTER_EVENTS:
+        return !(memento.source & AINPUT_SOURCE_CLASS_POINTER);
+    default:
+        return false;
     }
 }
 
diff --git a/libs/ui/InputReader.cpp b/libs/ui/InputReader.cpp
index 9cc96ad..51ed09f 100644
--- a/libs/ui/InputReader.cpp
+++ b/libs/ui/InputReader.cpp
@@ -745,17 +745,6 @@
 void KeyboardInputMapper::initializeLocked() {
     mLocked.metaState = AMETA_NONE;
     mLocked.downTime = 0;
-
-    initializeLedStateLocked(mLocked.capsLockLedState, LED_CAPSL);
-    initializeLedStateLocked(mLocked.numLockLedState, LED_NUML);
-    initializeLedStateLocked(mLocked.scrollLockLedState, LED_SCROLLL);
-
-    updateLedStateLocked(true);
-}
-
-void KeyboardInputMapper::initializeLedStateLocked(LockedState::LedState& ledState, int32_t led) {
-    ledState.avail = getEventHub()->hasLed(getDeviceId(), led);
-    ledState.on = false;
 }
 
 uint32_t KeyboardInputMapper::getSources() {
@@ -786,6 +775,12 @@
 
     // Configure basic parameters.
     configureParameters();
+
+    // Reset LEDs.
+    {
+        AutoMutex _l(mLock);
+        resetLedStateLocked();
+    }
 }
 
 void KeyboardInputMapper::configureParameters() {
@@ -813,6 +808,7 @@
             // Synthesize key up event on reset if keys are currently down.
             if (mLocked.keyDowns.isEmpty()) {
                 initializeLocked();
+                resetLedStateLocked();
                 break; // done
             }
 
@@ -953,6 +949,19 @@
     } // release lock
 }
 
+void KeyboardInputMapper::resetLedStateLocked() {
+    initializeLedStateLocked(mLocked.capsLockLedState, LED_CAPSL);
+    initializeLedStateLocked(mLocked.numLockLedState, LED_NUML);
+    initializeLedStateLocked(mLocked.scrollLockLedState, LED_SCROLLL);
+
+    updateLedStateLocked(true);
+}
+
+void KeyboardInputMapper::initializeLedStateLocked(LockedState::LedState& ledState, int32_t led) {
+    ledState.avail = getEventHub()->hasLed(getDeviceId(), led);
+    ledState.on = false;
+}
+
 void KeyboardInputMapper::updateLedStateLocked(bool reset) {
     updateLedStateForModifierLocked(mLocked.capsLockLedState, LED_CAPSL,
             AMETA_CAPS_LOCK_ON, reset);
@@ -966,7 +975,7 @@
         int32_t led, int32_t modifier, bool reset) {
     if (ledState.avail) {
         bool desiredState = (mLocked.metaState & modifier) != 0;
-        if (ledState.on != desiredState) {
+        if (reset || ledState.on != desiredState) {
             getEventHub()->setLedState(getDeviceId(), led, desiredState);
             ledState.on = desiredState;
         }
diff --git a/libs/ui/InputTransport.cpp b/libs/ui/InputTransport.cpp
index 1885691..83d9556 100644
--- a/libs/ui/InputTransport.cpp
+++ b/libs/ui/InputTransport.cpp
@@ -501,7 +501,7 @@
     return mChannel->sendSignal(INPUT_SIGNAL_DISPATCH);
 }
 
-status_t InputPublisher::receiveFinishedSignal(bool& outHandled) {
+status_t InputPublisher::receiveFinishedSignal(bool* outHandled) {
 #if DEBUG_TRANSPORT_ACTIONS
     LOGD("channel '%s' publisher ~ receiveFinishedSignal",
             mChannel->getName().string());
@@ -510,13 +510,13 @@
     char signal;
     status_t result = mChannel->receiveSignal(& signal);
     if (result) {
-        outHandled = false;
+        *outHandled = false;
         return result;
     }
     if (signal == INPUT_SIGNAL_FINISHED_HANDLED) {
-        outHandled = true;
+        *outHandled = true;
     } else if (signal == INPUT_SIGNAL_FINISHED_UNHANDLED) {
-        outHandled = false;
+        *outHandled = false;
     } else {
         LOGE("channel '%s' publisher ~ Received unexpected signal '%c' from consumer",
                 mChannel->getName().string(), signal);
diff --git a/libs/ui/KeyCharacterMap.cpp b/libs/ui/KeyCharacterMap.cpp
index e689c4b..9bfa8f6 100644
--- a/libs/ui/KeyCharacterMap.cpp
+++ b/libs/ui/KeyCharacterMap.cpp
@@ -141,9 +141,8 @@
 
 char16_t KeyCharacterMap::getDisplayLabel(int32_t keyCode) const {
     char16_t result = 0;
-    ssize_t index = mKeys.indexOfKey(keyCode);
-    if (index >= 0) {
-        const Key* key = mKeys.valueAt(index);
+    const Key* key;
+    if (getKey(keyCode, &key)) {
         result = key->label;
     }
 #if DEBUG_MAPPING
@@ -154,9 +153,8 @@
 
 char16_t KeyCharacterMap::getNumber(int32_t keyCode) const {
     char16_t result = 0;
-    ssize_t index = mKeys.indexOfKey(keyCode);
-    if (index >= 0) {
-        const Key* key = mKeys.valueAt(index);
+    const Key* key;
+    if (getKey(keyCode, &key)) {
         result = key->number;
     }
 #if DEBUG_MAPPING
@@ -167,15 +165,10 @@
 
 char16_t KeyCharacterMap::getCharacter(int32_t keyCode, int32_t metaState) const {
     char16_t result = 0;
-    ssize_t index = mKeys.indexOfKey(keyCode);
-    if (index >= 0) {
-        const Key* key = mKeys.valueAt(index);
-        for (const Behavior* behavior = key->firstBehavior; behavior; behavior = behavior->next) {
-            if ((behavior->metaState & metaState) == behavior->metaState) {
-                result = behavior->character;
-                break;
-            }
-        }
+    const Key* key;
+    const Behavior* behavior;
+    if (getKeyBehavior(keyCode, metaState, &key, &behavior)) {
+        result = behavior->character;
     }
 #if DEBUG_MAPPING
     LOGD("getCharacter: keyCode=%d, metaState=0x%08x ~ Result %d.", keyCode, metaState, result);
@@ -183,13 +176,33 @@
     return result;
 }
 
+bool KeyCharacterMap::getFallbackAction(int32_t keyCode, int32_t metaState,
+        FallbackAction* outFallbackAction) const {
+    outFallbackAction->keyCode = 0;
+    outFallbackAction->metaState = 0;
+
+    bool result = false;
+    const Key* key;
+    const Behavior* behavior;
+    if (getKeyBehavior(keyCode, metaState, &key, &behavior)) {
+        outFallbackAction->keyCode = behavior->fallbackKeyCode;
+        outFallbackAction->metaState = metaState & ~behavior->metaState;
+        result = true;
+    }
+#if DEBUG_MAPPING
+    LOGD("getFallbackKeyCode: keyCode=%d, metaState=0x%08x ~ Result %s, "
+            "fallback keyCode=%d, fallback metaState=0x%08x.",
+            keyCode, metaState, result ? "true" : "false",
+            outFallbackAction->keyCode, outFallbackAction->metaState);
+#endif
+    return result;
+}
+
 char16_t KeyCharacterMap::getMatch(int32_t keyCode, const char16_t* chars, size_t numChars,
         int32_t metaState) const {
     char16_t result = 0;
-    ssize_t index = mKeys.indexOfKey(keyCode);
-    if (index >= 0) {
-        const Key* key = mKeys.valueAt(index);
-
+    const Key* key;
+    if (getKey(keyCode, &key)) {
         // Try to find the most general behavior that maps to this character.
         // For example, the base key behavior will usually be last in the list.
         // However, if we find a perfect meta state match for one behavior then use that one.
@@ -238,7 +251,7 @@
     }
 #if DEBUG_MAPPING
     LOGD("getEvents: deviceId=%d, chars=[%s] ~ Generated %d events.",
-            deviceId, toString(chars, numChars).string(), outEvents.size());
+            deviceId, toString(chars, numChars).string(), int32_t(outEvents.size()));
     for (size_t i = 0; i < outEvents.size(); i++) {
         LOGD("  Key: keyCode=%d, metaState=0x%08x, %s.",
                 outEvents[i].getKeyCode(), outEvents[i].getMetaState(),
@@ -248,6 +261,32 @@
     return true;
 }
 
+bool KeyCharacterMap::getKey(int32_t keyCode, const Key** outKey) const {
+    ssize_t index = mKeys.indexOfKey(keyCode);
+    if (index >= 0) {
+        *outKey = mKeys.valueAt(index);
+        return true;
+    }
+    return false;
+}
+
+bool KeyCharacterMap::getKeyBehavior(int32_t keyCode, int32_t metaState,
+        const Key** outKey, const Behavior** outBehavior) const {
+    const Key* key;
+    if (getKey(keyCode, &key)) {
+        const Behavior* behavior = key->firstBehavior;
+        while (behavior) {
+            if ((behavior->metaState & metaState) == behavior->metaState) {
+                *outKey = key;
+                *outBehavior = behavior;
+                return true;
+            }
+            behavior = behavior->next;
+        }
+    }
+    return false;
+}
+
 bool KeyCharacterMap::findKey(char16_t ch, int32_t* outKeyCode, int32_t* outMetaState) const {
     if (!ch) {
         return false;
diff --git a/libs/ui/tests/InputDispatcher_test.cpp b/libs/ui/tests/InputDispatcher_test.cpp
index 68f9037..7e17c57 100644
--- a/libs/ui/tests/InputDispatcher_test.cpp
+++ b/libs/ui/tests/InputDispatcher_test.cpp
@@ -66,7 +66,7 @@
     }
 
     virtual bool dispatchUnhandledKey(const sp<InputChannel>& inputChannel,
-            const KeyEvent* keyEvent, uint32_t policyFlags) {
+            const KeyEvent* keyEvent, uint32_t policyFlags, KeyEvent* outFallbackKeyEvent) {
         return false;
     }
 
diff --git a/libs/ui/tests/InputPublisherAndConsumer_test.cpp b/libs/ui/tests/InputPublisherAndConsumer_test.cpp
index c6eac25..903fcaf 100644
--- a/libs/ui/tests/InputPublisherAndConsumer_test.cpp
+++ b/libs/ui/tests/InputPublisherAndConsumer_test.cpp
@@ -123,7 +123,7 @@
             << "consumer sendFinishedSignal should return OK";
 
     bool handled = false;
-    status = mPublisher->receiveFinishedSignal(handled);
+    status = mPublisher->receiveFinishedSignal(&handled);
     ASSERT_EQ(OK, status)
             << "publisher receiveFinishedSignal should return OK";
     ASSERT_TRUE(handled)
@@ -287,7 +287,7 @@
             << "consumer sendFinishedSignal should return OK";
 
     bool handled = true;
-    status = mPublisher->receiveFinishedSignal(handled);
+    status = mPublisher->receiveFinishedSignal(&handled);
     ASSERT_EQ(OK, status)
             << "publisher receiveFinishedSignal should return OK";
     ASSERT_FALSE(handled)
diff --git a/libs/ui/tests/InputReader_test.cpp b/libs/ui/tests/InputReader_test.cpp
index d6c2cbd..97cbc25 100644
--- a/libs/ui/tests/InputReader_test.cpp
+++ b/libs/ui/tests/InputReader_test.cpp
@@ -1137,6 +1137,7 @@
         mFakeDispatcher = new FakeInputDispatcher();
         mFakeContext = new FakeInputReaderContext(mFakeEventHub, mFakePolicy, mFakeDispatcher);
 
+        mFakeEventHub->addDevice(DEVICE_ID, String8(DEVICE_NAME), 0);
         mDevice = new InputDevice(mFakeContext, DEVICE_ID, String8(DEVICE_NAME));
     }
 
@@ -1753,7 +1754,7 @@
     process(mapper, ARBITRARY_TIME, DEVICE_ID,
             EV_KEY, KEY_CAPSLOCK, AKEYCODE_CAPS_LOCK, 1, 0);
     process(mapper, ARBITRARY_TIME, DEVICE_ID,
-            EV_KEY, KEY_CAPSLOCK, AKEYCODE_CAPS_LOCK, 1, 0);
+            EV_KEY, KEY_CAPSLOCK, AKEYCODE_CAPS_LOCK, 0, 0);
     ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_CAPSL));
     ASSERT_TRUE(mFakeEventHub->getLedState(DEVICE_ID, LED_NUML));
     ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_SCROLLL));
@@ -2225,19 +2226,19 @@
 }
 
 
-TEST_F(SingleTouchInputMapperTest, GetSources_WhenDisplayTypeIsTouchPad_ReturnsTouchPad) {
+TEST_F(SingleTouchInputMapperTest, GetSources_WhenDeviceTypeIsTouchPad_ReturnsTouchPad) {
     SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
     prepareAxes(POSITION);
-    addConfigurationProperty("touch.displayType", "touchPad");
+    addConfigurationProperty("touch.deviceType", "touchPad");
     addMapperAndConfigure(mapper);
 
     ASSERT_EQ(AINPUT_SOURCE_TOUCHPAD, mapper->getSources());
 }
 
-TEST_F(SingleTouchInputMapperTest, GetSources_WhenDisplayTypeIsTouchScreen_ReturnsTouchScreen) {
+TEST_F(SingleTouchInputMapperTest, GetSources_WhenDeviceTypeIsTouchScreen_ReturnsTouchScreen) {
     SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
     prepareAxes(POSITION);
-    addConfigurationProperty("touch.displayType", "touchScreen");
+    addConfigurationProperty("touch.deviceType", "touchScreen");
     addMapperAndConfigure(mapper);
 
     ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, mapper->getSources());
diff --git a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
index d3a71b3..d539833 100755
--- a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
+++ b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
@@ -28,6 +28,8 @@
 import android.os.RemoteException;
 import android.util.Log;
 
+import com.android.internal.R;
+
 /**
  * A GPS Network-initiated Handler class used by LocationManager.
  *
@@ -182,8 +184,8 @@
             return;
         }
 
-        String title = getNotifTitle(notif);
-        String message = getNotifMessage(notif);
+        String title = getNotifTitle(notif, mContext);
+        String message = getNotifMessage(notif, mContext);
 
         if (DEBUG) Log.d(TAG, "setNiNotification, notifyId: " + notif.notificationId +
                 ", title: " + title +
@@ -203,7 +205,7 @@
         }        
 
         mNiNotification.flags = Notification.FLAG_ONGOING_EVENT;
-        mNiNotification.tickerText = getNotifTicker(notif);
+        mNiNotification.tickerText = getNotifTicker(notif, mContext);
 
         // if not to popup dialog immediately, pending intent will open the dialog
         Intent intent = !mPopupImmediately ? getDlgIntent(notif) : new Intent();
@@ -234,8 +236,8 @@
     private Intent getDlgIntent(GpsNiNotification notif)
     {
         Intent intent = new Intent();
-        String title = getDialogTitle(notif);
-        String message = getDialogMessage(notif);
+        String title = getDialogTitle(notif, mContext);
+        String message = getDialogMessage(notif, mContext);
 
         // directly bring up the NI activity
         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
@@ -412,41 +414,40 @@
     }
 
     // change this to configure notification display
-    static private String getNotifTicker(GpsNiNotification notif)
+    static private String getNotifTicker(GpsNiNotification notif, Context context)
     {
-        String ticker = String.format("Position request! ReqId: [%s] ClientName: [%s]",
+        String ticker = String.format(context.getString(R.string.gpsNotifTicker),
                 decodeString(notif.requestorId, mIsHexInput, notif.requestorIdEncoding),
                 decodeString(notif.text, mIsHexInput, notif.textEncoding));
         return ticker;
     }
 
     // change this to configure notification display
-    static private String getNotifTitle(GpsNiNotification notif)
+    static private String getNotifTitle(GpsNiNotification notif, Context context)
     {
-        String title = String.format("Position Request");
+        String title = String.format(context.getString(R.string.gpsNotifTitle));
         return title;
     }
 
     // change this to configure notification display
-    static private String getNotifMessage(GpsNiNotification notif)
+    static private String getNotifMessage(GpsNiNotification notif, Context context)
     {
-        String message = String.format(
-                "NI Request received from [%s] for client [%s]!",
+        String message = String.format(context.getString(R.string.gpsNotifMessage),
                 decodeString(notif.requestorId, mIsHexInput, notif.requestorIdEncoding),
                 decodeString(notif.text, mIsHexInput, notif.textEncoding));
         return message;
     }       
 
     // change this to configure dialog display (for verification)
-    static public String getDialogTitle(GpsNiNotification notif)
+    static public String getDialogTitle(GpsNiNotification notif, Context context)
     {
-        return getNotifTitle(notif);
+        return getNotifTitle(notif, context);
     }
 
     // change this to configure dialog display (for verification)
-    static private String getDialogMessage(GpsNiNotification notif)
+    static private String getDialogMessage(GpsNiNotification notif, Context context)
     {
-        return getNotifMessage(notif);
+        return getNotifMessage(notif, context);
     }
 
 }
diff --git a/media/java/android/media/MtpDatabase.java b/media/java/android/media/MtpDatabase.java
index 139a6ea..6056a0f 100644
--- a/media/java/android/media/MtpDatabase.java
+++ b/media/java/android/media/MtpDatabase.java
@@ -31,6 +31,8 @@
 import android.provider.MediaStore.Images;
 import android.provider.MediaStore.MediaColumns;
 import android.util.Log;
+import android.view.Display;
+import android.view.WindowManager;
 
 import java.io.File;
 import java.util.HashMap;
@@ -460,6 +462,7 @@
         return new int[] {
             MtpConstants.DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER,
             MtpConstants.DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME,
+            MtpConstants.DEVICE_PROPERTY_IMAGE_SIZE,
         };
     }
 
@@ -592,9 +595,21 @@
                         c.close();
                     }
                 }
-        }
 
-        return MtpConstants.RESPONSE_DEVICE_PROP_NOT_SUPPORTED;
+            case MtpConstants.DEVICE_PROPERTY_IMAGE_SIZE:
+                // use screen size as max image size
+                Display display = ((WindowManager)mContext.getSystemService(
+                        Context.WINDOW_SERVICE)).getDefaultDisplay();
+                int width = display.getWidth();
+                int height = display.getHeight();
+                String imageSize = Integer.toString(width) + "x" +  Integer.toString(height);
+                imageSize.getChars(0, imageSize.length(), outStringValue, 0);
+                outStringValue[imageSize.length()] = 0;
+                return MtpConstants.RESPONSE_OK;
+
+            default:
+                return MtpConstants.RESPONSE_DEVICE_PROP_NOT_SUPPORTED;
+        }
     }
 
     private int setDeviceProperty(int property, long intValue, String stringValue) {
diff --git a/media/jni/android_media_MtpDatabase.cpp b/media/jni/android_media_MtpDatabase.cpp
index 1909e6a..9bb93fd 100644
--- a/media/jni/android_media_MtpDatabase.cpp
+++ b/media/jni/android_media_MtpDatabase.cpp
@@ -860,8 +860,9 @@
 };
 
 static const PropertyTableEntry   kDevicePropertyTable[] = {
-    {   MTP_DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER,     MTP_TYPE_STR },
-    {   MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME,        MTP_TYPE_STR },
+    {   MTP_DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER,    MTP_TYPE_STR },
+    {   MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME,       MTP_TYPE_STR },
+    {   MTP_DEVICE_PROPERTY_IMAGE_SIZE,                 MTP_TYPE_STR },
 };
 
 bool MyMtpDatabase::getObjectPropertyInfo(MtpObjectProperty property, int& type) {
@@ -932,6 +933,9 @@
     MtpProperty* result = NULL;
     switch (property) {
         case MTP_PROPERTY_OBJECT_FORMAT:
+            // use format as default value
+            result = new MtpProperty(property, MTP_TYPE_UINT16, false, format);
+            break;
         case MTP_PROPERTY_PROTECTION_STATUS:
         case MTP_PROPERTY_TRACK:
             result = new MtpProperty(property, MTP_TYPE_UINT16);
@@ -973,31 +977,35 @@
 }
 
 MtpProperty* MyMtpDatabase::getDevicePropertyDesc(MtpDeviceProperty property) {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
     MtpProperty* result = NULL;
+    bool writable = false;
+
     switch (property) {
         case MTP_DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER:
         case MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME:
-        {
-            // writeable string properties
-            result = new MtpProperty(property, MTP_TYPE_STR, true);
+            writable = true;
+            // fall through
+        case MTP_DEVICE_PROPERTY_IMAGE_SIZE:
+            result = new MtpProperty(property, MTP_TYPE_STR, writable);
 
-            // set current value
-            JNIEnv* env = AndroidRuntime::getJNIEnv();
+            // get current value
             jint ret = env->CallIntMethod(mDatabase, method_getDeviceProperty,
                         (jint)property, mLongBuffer, mStringBuffer);
             if (ret == MTP_RESPONSE_OK) {
                 jchar* str = env->GetCharArrayElements(mStringBuffer, 0);
                 result->setCurrentValue(str);
+                // for read-only properties it is safe to assume current value is default value
+                if (!writable)
+                    result->setDefaultValue(str);
                 env->ReleaseCharArrayElements(mStringBuffer, str, 0);
             } else {
                 LOGE("unable to read device property, response: %04X", ret);
             }
-
-            checkAndClearExceptionFromCallback(env, __FUNCTION__);
             break;
-        }
     }
 
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
     return result;
 }
 
diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk
index 731c09d..74fb531 100644
--- a/media/libmedia/Android.mk
+++ b/media/libmedia/Android.mk
@@ -36,7 +36,8 @@
     fixedfft.cpp.arm
 
 LOCAL_SHARED_LIBRARIES := \
-	libui libcutils libutils libbinder libsonivox libicuuc libexpat libsurfaceflinger_client libcamera_client
+	libui libcutils libutils libbinder libsonivox libicuuc libexpat \
+        libsurfaceflinger_client libcamera_client libstagefright_foundation
 
 LOCAL_MODULE:= libmedia
 
diff --git a/media/libmedia/IStreamSource.cpp b/media/libmedia/IStreamSource.cpp
index 89f2b44..5069002 100644
--- a/media/libmedia/IStreamSource.cpp
+++ b/media/libmedia/IStreamSource.cpp
@@ -19,6 +19,7 @@
 #include <utils/Log.h>
 
 #include <media/IStreamSource.h>
+#include <media/stagefright/foundation/AMessage.h>
 
 #include <binder/IMemory.h>
 #include <binder/Parcel.h>
@@ -33,7 +34,7 @@
 
     // IStreamListener
     QUEUE_BUFFER,
-    QUEUE_COMMAND,
+    ISSUE_COMMAND,
 };
 
 struct BpStreamSource : public BpInterface<IStreamSource> {
@@ -125,12 +126,21 @@
         remote()->transact(QUEUE_BUFFER, data, &reply, IBinder::FLAG_ONEWAY);
     }
 
-    virtual void queueCommand(Command cmd) {
+    virtual void issueCommand(
+            Command cmd, bool synchronous, const sp<AMessage> &msg) {
         Parcel data, reply;
         data.writeInterfaceToken(IStreamListener::getInterfaceDescriptor());
         data.writeInt32(static_cast<int32_t>(cmd));
+        data.writeInt32(static_cast<int32_t>(synchronous));
 
-        remote()->transact(QUEUE_COMMAND, data, &reply, IBinder::FLAG_ONEWAY);
+        if (msg != NULL) {
+            data.writeInt32(1);
+            msg->writeToParcel(&data);
+        } else {
+            data.writeInt32(0);
+        }
+
+        remote()->transact(ISSUE_COMMAND, data, &reply, IBinder::FLAG_ONEWAY);
     }
 };
 
@@ -149,12 +159,20 @@
             break;
         }
 
-        case QUEUE_COMMAND:
+        case ISSUE_COMMAND:
         {
             CHECK_INTERFACE(IStreamListener, data, reply);
             Command cmd = static_cast<Command>(data.readInt32());
 
-            queueCommand(cmd);
+            bool synchronous = static_cast<bool>(data.readInt32());
+
+            sp<AMessage> msg;
+
+            if (data.readInt32()) {
+                msg = AMessage::FromParcel(data);
+            }
+
+            issueCommand(cmd, synchronous, msg);
             break;
         }
 
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index 2743a3a..7613d04 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -50,6 +50,7 @@
 #include <surfaceflinger/Surface.h>
 
 #include <media/stagefright/foundation/ALooper.h>
+#include <media/stagefright/foundation/AMessage.h>
 #include "include/LiveSession.h"
 
 #define USE_SURFACE_ALLOC 1
@@ -170,7 +171,9 @@
     void clearOwner();
 
     virtual void queueBuffer(size_t index, size_t size);
-    virtual void queueCommand(Command cmd);
+
+    virtual void issueCommand(
+            Command cmd, bool synchronous, const sp<AMessage> &msg);
 
 private:
     Mutex mLock;
@@ -188,7 +191,11 @@
     virtual ssize_t readAt(off64_t offset, void *data, size_t size);
 
     virtual void queueBuffer(size_t index, size_t size);
-    virtual void queueCommand(IStreamListener::Command cmd);
+
+    virtual void issueCommand(
+            IStreamListener::Command cmd,
+            bool synchronous,
+            const sp<AMessage> &msg);
 
 protected:
     virtual ~QueueDataSource();
@@ -198,7 +205,12 @@
         kNumBuffers = 16
     };
 
-    struct BufferInfo {
+    struct QueueEntry {
+        bool mIsCommand;
+
+        IStreamListener::Command mCommand;
+        sp<AMessage> mCommandMessage;
+
         size_t mIndex;
         size_t mOffset;
         size_t mSize;
@@ -212,7 +224,7 @@
     sp<MemoryDealer> mDealer;
     Vector<sp<IMemory> > mBuffers;
 
-    List<BufferInfo> mFilledBuffers;
+    List<QueueEntry> mQueue;
 
     off64_t mPosition;
     bool mEOS;
@@ -227,7 +239,7 @@
     mListener = new QueueListener(this);
     mSource->setListener(mListener);
 
-    static const size_t kBufferSize = 8192;
+    static const size_t kBufferSize = (8192 / 188) * 188;
 
     mDealer = new MemoryDealer(kNumBuffers * kBufferSize);
     for (size_t i = 0; i < kNumBuffers; ++i) {
@@ -246,10 +258,6 @@
 QueueDataSource::~QueueDataSource() {
     Mutex::Autolock autoLock(mLock);
 
-    while (mFilledBuffers.size() < kNumBuffers && !mEOS) {
-        mCondition.wait(mLock);
-    }
-
     mListener->clearOwner();
 }
 
@@ -264,40 +272,69 @@
 
     Mutex::Autolock autoLock(mLock);
 
+    if (mEOS) {
+        return ERROR_END_OF_STREAM;
+    }
+
     size_t sizeDone = 0;
 
     while (sizeDone < size) {
-        while (mFilledBuffers.empty() && !mEOS) {
+        while (mQueue.empty()) {
             mCondition.wait(mLock);
         }
 
-        if (mFilledBuffers.empty()) {
-            if (sizeDone > 0) {
-                mPosition += sizeDone;
-                return sizeDone;
+        QueueEntry &entry = *mQueue.begin();
+
+        if (entry.mIsCommand) {
+            switch (entry.mCommand) {
+                case IStreamListener::EOS:
+                {
+                    mEOS = true;
+
+                    if (sizeDone > 0) {
+                        offset += sizeDone;
+                        return sizeDone;
+                    } else {
+                        return ERROR_END_OF_STREAM;
+                    }
+                    break;
+                }
+
+                case IStreamListener::DISCONTINUITY:
+                {
+                    CHECK_EQ(size, 188u);
+                    CHECK_EQ(sizeDone, 0u);
+
+                    memset(data, 0, size);
+                    sizeDone = size;
+                    break;
+                }
+
+                default:
+                    break;
             }
-            return ERROR_END_OF_STREAM;
+
+            mQueue.erase(mQueue.begin());
+            continue;
         }
 
-        BufferInfo &info = *mFilledBuffers.begin();
-
         size_t copy = size - sizeDone;
-        if (copy > info.mSize) {
-            copy = info.mSize;
+        if (copy > entry.mSize) {
+            copy = entry.mSize;
         }
 
         memcpy((uint8_t *)data + sizeDone,
-               (const uint8_t *)mBuffers.itemAt(info.mIndex)->pointer()
-                    + info.mOffset,
+               (const uint8_t *)mBuffers.itemAt(entry.mIndex)->pointer()
+                    + entry.mOffset,
                copy);
 
-        info.mSize -= copy;
-        info.mOffset += copy;
+        entry.mSize -= copy;
+        entry.mOffset += copy;
         sizeDone += copy;
 
-        if (info.mSize == 0) {
-            mSource->onBufferAvailable(info.mIndex);
-            mFilledBuffers.erase(mFilledBuffers.begin());
+        if (entry.mSize == 0) {
+            mSource->onBufferAvailable(entry.mIndex);
+            mQueue.erase(mQueue.begin());
         }
     }
 
@@ -312,22 +349,31 @@
     CHECK_LT(index, mBuffers.size());
     CHECK_LE(size, mBuffers.itemAt(index)->size());
 
-    BufferInfo info;
-    info.mIndex = index;
-    info.mSize = size;
-    info.mOffset = 0;
+    QueueEntry entry;
+    entry.mIsCommand = false;
+    entry.mIndex = index;
+    entry.mSize = size;
+    entry.mOffset = 0;
 
-    mFilledBuffers.push_back(info);
+    mQueue.push_back(entry);
     mCondition.signal();
 }
 
-void QueueDataSource::queueCommand(IStreamListener::Command cmd) {
+void QueueDataSource::issueCommand(
+        IStreamListener::Command cmd,
+        bool synchronous,
+        const sp<AMessage> &msg) {
     Mutex::Autolock autoLock(mLock);
 
-    if (cmd == IStreamListener::EOS) {
-        mEOS = true;
-        mCondition.signal();
-    }
+    CHECK(!synchronous);
+
+    QueueEntry entry;
+    entry.mIsCommand = true;
+    entry.mCommand = cmd;
+    entry.mCommandMessage = msg;
+    mQueue.push_back(entry);
+
+    mCondition.signal();
 }
 
 void QueueListener::clearOwner() {
@@ -343,12 +389,13 @@
     mOwner->queueBuffer(index, size);
 }
 
-void QueueListener::queueCommand(Command cmd) {
+void QueueListener::issueCommand(
+        Command cmd, bool synchronous, const sp<AMessage> &msg) {
     Mutex::Autolock autoLock(mLock);
     if (mOwner == NULL) {
         return;
     }
-    mOwner->queueCommand(cmd);
+    mOwner->issueCommand(cmd, synchronous, msg);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -469,18 +516,9 @@
     reset_l();
 
     sp<DataSource> dataSource = new QueueDataSource(source);
-
-#if 0
-    sp<MediaExtractor> extractor =
-        MediaExtractor::Create(dataSource, MEDIA_MIMETYPE_CONTAINER_MPEG2TS);
+    sp<MediaExtractor> extractor = new MPEG2TSExtractor(dataSource);
 
     return setDataSource_l(extractor);
-#else
-    sp<NuCachedSource2> cached = new NuCachedSource2(dataSource);
-    dataSource = cached;
-
-    return setDataSource_l(dataSource);
-#endif
 }
 
 status_t AwesomePlayer::setDataSource_l(
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 3108e4e..4bf922f 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -1650,8 +1650,7 @@
         }
 
         info.mBuffer = buffer;
-        info.mOwnedByComponent = false;
-        info.mOwnedByNativeWindow = false;
+        info.mStatus = OWNED_BY_US;
         info.mMem = mem;
         info.mMediaBuffer = NULL;
 
@@ -1759,8 +1758,7 @@
         info.mData = NULL;
         info.mSize = def.nBufferSize;
         info.mBuffer = bufferId;
-        info.mOwnedByComponent = false;
-        info.mOwnedByNativeWindow = false;
+        info.mStatus = OWNED_BY_US;
         info.mMem = NULL;
         info.mMediaBuffer = new MediaBuffer(graphicBuffer);
         info.mMediaBuffer->setObserver(this);
@@ -1794,7 +1792,7 @@
 }
 
 status_t OMXCodec::cancelBufferToNativeWindow(BufferInfo *info) {
-    CHECK(!info->mOwnedByNativeWindow);
+    CHECK_EQ((int)info->mStatus, (int)OWNED_BY_US);
     CODEC_LOGV("Calling cancelBuffer on buffer %p", info->mBuffer);
     int err = mNativeWindow->cancelBuffer(
         mNativeWindow.get(), info->mMediaBuffer->graphicBuffer().get());
@@ -1804,7 +1802,7 @@
       setState(ERROR);
       return err;
     }
-    info->mOwnedByNativeWindow = true;
+    info->mStatus = OWNED_BY_NATIVE_WINDOW;
     return OK;
 }
 
@@ -1839,8 +1837,8 @@
     }
 
     // The native window no longer owns the buffer.
-    CHECK(bufInfo->mOwnedByNativeWindow);
-    bufInfo->mOwnedByNativeWindow = false;
+    CHECK_EQ((int)bufInfo->mStatus, (int)OWNED_BY_NATIVE_WINDOW);
+    bufInfo->mStatus = OWNED_BY_US;
 
     return bufInfo;
 }
@@ -1871,13 +1869,13 @@
             }
 
             CHECK(i < buffers->size());
-            if (!(*buffers)[i].mOwnedByComponent) {
+            if ((*buffers)[i].mStatus != OWNED_BY_COMPONENT) {
                 LOGW("We already own input buffer %p, yet received "
                      "an EMPTY_BUFFER_DONE.", buffer);
             }
 
             BufferInfo* info = &buffers->editItemAt(i);
-            info->mOwnedByComponent = false;
+            info->mStatus = OWNED_BY_US;
 
             // Buffer could not be released until empty buffer done is called.
             if (info->mMediaBuffer != NULL) {
@@ -1926,12 +1924,12 @@
             CHECK(i < buffers->size());
             BufferInfo *info = &buffers->editItemAt(i);
 
-            if (!info->mOwnedByComponent) {
+            if (info->mStatus != OWNED_BY_COMPONENT) {
                 LOGW("We already own output buffer %p, yet received "
                      "a FILL_BUFFER_DONE.", buffer);
             }
 
-            info->mOwnedByComponent = false;
+            info->mStatus = OWNED_BY_US;
 
             if (mPortStatus[kPortIndexOutput] == DISABLING) {
                 CODEC_LOGV("Port is disabled, freeing buffer %p", buffer);
@@ -2400,7 +2398,7 @@
 size_t OMXCodec::countBuffersWeOwn(const Vector<BufferInfo> &buffers) {
     size_t n = 0;
     for (size_t i = 0; i < buffers.size(); ++i) {
-        if (!buffers[i].mOwnedByComponent) {
+        if (buffers[i].mStatus != OWNED_BY_COMPONENT) {
             ++n;
         }
     }
@@ -2417,11 +2415,12 @@
     for (size_t i = buffers->size(); i-- > 0;) {
         BufferInfo *info = &buffers->editItemAt(i);
 
-        if (onlyThoseWeOwn && info->mOwnedByComponent) {
+        if (onlyThoseWeOwn && info->mStatus == OWNED_BY_COMPONENT) {
             continue;
         }
 
-        CHECK_EQ((int)info->mOwnedByComponent, (int)false);
+        CHECK(info->mStatus == OWNED_BY_US
+                || info->mStatus == OWNED_BY_NATIVE_WINDOW);
 
         CODEC_LOGV("freeing buffer %p on port %ld", info->mBuffer, portIndex);
 
@@ -2454,7 +2453,7 @@
 
         // Cancel the buffer if it belongs to an ANativeWindow.
         sp<GraphicBuffer> graphicBuffer = info->mMediaBuffer->graphicBuffer();
-        if (!info->mOwnedByNativeWindow && graphicBuffer != 0) {
+        if (info->mStatus == OWNED_BY_US && graphicBuffer != 0) {
             err = cancelBufferToNativeWindow(info);
         }
 
@@ -2559,7 +2558,7 @@
     Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput];
     for (size_t i = 0; i < buffers->size(); ++i) {
         BufferInfo *info = &buffers->editItemAt(i);
-        if (!info->mOwnedByNativeWindow) {
+        if (info->mStatus == OWNED_BY_US) {
             fillOutputBuffer(&buffers->editItemAt(i));
         }
     }
@@ -2570,15 +2569,17 @@
 
     Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexInput];
     for (size_t i = 0; i < buffers->size(); ++i) {
-        drainInputBuffer(&buffers->editItemAt(i));
+        if (!drainInputBuffer(&buffers->editItemAt(i))) {
+            break;
+        }
     }
 }
 
-void OMXCodec::drainInputBuffer(BufferInfo *info) {
-    CHECK_EQ((int)info->mOwnedByComponent, (int)false);
+bool OMXCodec::drainInputBuffer(BufferInfo *info) {
+    CHECK_EQ((int)info->mStatus, (int)OWNED_BY_US);
 
     if (mSignalledEOS) {
-        return;
+        return false;
     }
 
     if (mCodecSpecificDataIndex < mCodecSpecificData.size()) {
@@ -2614,14 +2615,14 @@
                 0);
         CHECK_EQ(err, (status_t)OK);
 
-        info->mOwnedByComponent = true;
+        info->mStatus = OWNED_BY_COMPONENT;
 
         ++mCodecSpecificDataIndex;
-        return;
+        return true;
     }
 
     if (mPaused) {
-        return;
+        return false;
     }
 
     status_t err;
@@ -2631,6 +2632,7 @@
 
     size_t offset = 0;
     int32_t n = 0;
+
     for (;;) {
         MediaBuffer *srcBuffer;
         MediaSource::ReadOptions options;
@@ -2689,7 +2691,7 @@
                 srcBuffer = NULL;
 
                 setState(ERROR);
-                return;
+                return false;
             }
 
             mLeftOverBuffer = srcBuffer;
@@ -2699,9 +2701,15 @@
         bool releaseBuffer = true;
         if (mIsEncoder && (mQuirks & kAvoidMemcopyInputRecordingFrames)) {
             CHECK(mOMXLivesLocally && offset == 0);
-            OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *) info->mBuffer;
+
+            OMX_BUFFERHEADERTYPE *header =
+                (OMX_BUFFERHEADERTYPE *)info->mBuffer;
+
             CHECK(header->pBuffer == info->mData);
-            header->pBuffer = (OMX_U8 *) srcBuffer->data() + srcBuffer->range_offset();
+
+            header->pBuffer =
+                (OMX_U8 *)srcBuffer->data() + srcBuffer->range_offset();
+
             releaseBuffer = false;
             info->mMediaBuffer = srcBuffer;
         } else {
@@ -2710,7 +2718,8 @@
                 info->mMediaBuffer = srcBuffer;
             }
             memcpy((uint8_t *)info->mData + offset,
-                    (const uint8_t *)srcBuffer->data() + srcBuffer->range_offset(),
+                    (const uint8_t *)srcBuffer->data()
+                        + srcBuffer->range_offset(),
                     srcBuffer->range_length());
         }
 
@@ -2766,10 +2775,10 @@
 
     if (err != OK) {
         setState(ERROR);
-        return;
+        return false;
     }
 
-    info->mOwnedByComponent = true;
+    info->mStatus = OWNED_BY_COMPONENT;
 
     // This component does not ever signal the EOS flag on output buffers,
     // Thanks for nothing.
@@ -2777,10 +2786,12 @@
         mNoMoreOutputData = true;
         mBufferFilled.signal();
     }
+
+    return true;
 }
 
 void OMXCodec::fillOutputBuffer(BufferInfo *info) {
-    CHECK_EQ((int)info->mOwnedByComponent, (int)false);
+    CHECK_EQ((int)info->mStatus, (int)OWNED_BY_US);
 
     if (mNoMoreOutputData) {
         CODEC_LOGV("There is no more output data available, not "
@@ -2793,7 +2804,6 @@
         if (graphicBuffer != 0) {
             // When using a native buffer we need to lock the buffer before
             // giving it to OMX.
-            CHECK(!info->mOwnedByNativeWindow);
             CODEC_LOGV("Calling lockBuffer on %p", info->mBuffer);
             int err = mNativeWindow->lockBuffer(mNativeWindow.get(),
                     graphicBuffer.get());
@@ -2816,19 +2826,20 @@
         return;
     }
 
-    info->mOwnedByComponent = true;
+    info->mStatus = OWNED_BY_COMPONENT;
 }
 
-void OMXCodec::drainInputBuffer(IOMX::buffer_id buffer) {
+bool OMXCodec::drainInputBuffer(IOMX::buffer_id buffer) {
     Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexInput];
     for (size_t i = 0; i < buffers->size(); ++i) {
         if ((*buffers)[i].mBuffer == buffer) {
-            drainInputBuffer(&buffers->editItemAt(i));
-            return;
+            return drainInputBuffer(&buffers->editItemAt(i));
         }
     }
 
     CHECK(!"should not be here.");
+
+    return false;
 }
 
 void OMXCodec::fillOutputBuffer(IOMX::buffer_id buffer) {
@@ -3374,6 +3385,9 @@
     mFilledBuffers.erase(mFilledBuffers.begin());
 
     BufferInfo *info = &mPortBuffers[kPortIndexOutput].editItemAt(index);
+    CHECK_EQ((int)info->mStatus, (int)OWNED_BY_US);
+    info->mStatus = OWNED_BY_CLIENT;
+
     info->mMediaBuffer->add_ref();
     *buffer = info->mMediaBuffer;
 
@@ -3389,6 +3403,10 @@
 
         if (info->mMediaBuffer == buffer) {
             CHECK_EQ((int)mPortStatus[kPortIndexOutput], (int)ENABLED);
+            CHECK_EQ((int)info->mStatus, (int)OWNED_BY_CLIENT);
+
+            info->mStatus = OWNED_BY_US;
+
             if (buffer->graphicBuffer() == 0) {
                 fillOutputBuffer(info);
             } else {
@@ -3402,10 +3420,10 @@
                     if (err < 0) {
                         return;
                     }
-                } else {
-                    info->mOwnedByNativeWindow = true;
                 }
 
+                info->mStatus = OWNED_BY_NATIVE_WINDOW;
+
                 // Dequeue the next buffer from the native window.
                 BufferInfo *nextBufInfo = dequeueBufferFromNativeWindow();
                 if (nextBufInfo == 0) {
diff --git a/media/libstagefright/foundation/AMessage.cpp b/media/libstagefright/foundation/AMessage.cpp
index 26c6d42..7da9cb8 100644
--- a/media/libstagefright/foundation/AMessage.cpp
+++ b/media/libstagefright/foundation/AMessage.cpp
@@ -23,6 +23,8 @@
 #include "ALooperRoster.h"
 #include "AString.h"
 
+#include <binder/Parcel.h>
+
 namespace android {
 
 AMessage::AMessage(uint32_t what, ALooper::handler_id target)
@@ -341,4 +343,136 @@
     return s;
 }
 
+// static
+sp<AMessage> AMessage::FromParcel(const Parcel &parcel) {
+    int32_t what = parcel.readInt32();
+    sp<AMessage> msg = new AMessage(what);
+
+    msg->mNumItems = static_cast<size_t>(parcel.readInt32());
+
+    for (size_t i = 0; i < msg->mNumItems; ++i) {
+        Item *item = &msg->mItems[i];
+
+        item->mName = AAtomizer::Atomize(parcel.readCString());
+        item->mType = static_cast<Type>(parcel.readInt32());
+
+        switch (item->mType) {
+            case kTypeInt32:
+            {
+                item->u.int32Value = parcel.readInt32();
+                break;
+            }
+
+            case kTypeInt64:
+            {
+                item->u.int64Value = parcel.readInt64();
+                break;
+            }
+
+            case kTypeSize:
+            {
+                item->u.sizeValue = static_cast<size_t>(parcel.readInt32());
+                break;
+            }
+
+            case kTypeFloat:
+            {
+                item->u.floatValue = parcel.readFloat();
+                break;
+            }
+
+            case kTypeDouble:
+            {
+                item->u.doubleValue = parcel.readDouble();
+                break;
+            }
+
+            case kTypeString:
+            {
+                item->u.stringValue = new AString(parcel.readCString());
+                break;
+            }
+
+            case kTypeMessage:
+            {
+                sp<AMessage> subMsg = AMessage::FromParcel(parcel);
+                subMsg->incStrong(msg.get());
+
+                item->u.refValue = subMsg.get();
+                break;
+            }
+
+            default:
+            {
+                LOGE("This type of object cannot cross process boundaries.");
+                TRESPASS();
+            }
+        }
+    }
+
+    return msg;
+}
+
+void AMessage::writeToParcel(Parcel *parcel) const {
+    parcel->writeInt32(static_cast<int32_t>(mWhat));
+    parcel->writeInt32(static_cast<int32_t>(mNumItems));
+
+    for (size_t i = 0; i < mNumItems; ++i) {
+        const Item &item = mItems[i];
+
+        parcel->writeCString(item.mName);
+        parcel->writeInt32(static_cast<int32_t>(item.mType));
+
+        switch (item.mType) {
+            case kTypeInt32:
+            {
+                parcel->writeInt32(item.u.int32Value);
+                break;
+            }
+
+            case kTypeInt64:
+            {
+                parcel->writeInt64(item.u.int64Value);
+                break;
+            }
+
+            case kTypeSize:
+            {
+                parcel->writeInt32(static_cast<int32_t>(item.u.sizeValue));
+                break;
+            }
+
+            case kTypeFloat:
+            {
+                parcel->writeFloat(item.u.floatValue);
+                break;
+            }
+
+            case kTypeDouble:
+            {
+                parcel->writeDouble(item.u.doubleValue);
+                break;
+            }
+
+            case kTypeString:
+            {
+                parcel->writeCString(item.u.stringValue->c_str());
+                break;
+            }
+
+            case kTypeMessage:
+            {
+                static_cast<AMessage *>(item.u.refValue)->writeToParcel(parcel);
+                break;
+            }
+
+            default:
+            {
+                LOGE("This type of object cannot cross process boundaries.");
+                TRESPASS();
+            }
+        }
+    }
+}
+
 }  // namespace android
diff --git a/media/libstagefright/foundation/Android.mk b/media/libstagefright/foundation/Android.mk
index ffa7db0..a4d4809 100644
--- a/media/libstagefright/foundation/Android.mk
+++ b/media/libstagefright/foundation/Android.mk
@@ -18,14 +18,7 @@
 
 LOCAL_SHARED_LIBRARIES := \
         libbinder         \
-        libmedia          \
         libutils          \
-        libcutils         \
-        libui             \
-        libsonivox        \
-        libvorbisidec     \
-        libsurfaceflinger_client \
-        libcamera_client
 
 LOCAL_CFLAGS += -Wno-multichar
 
diff --git a/media/mtp/Android.mk b/media/mtp/Android.mk
index b7e1a2a..e285847 100644
--- a/media/mtp/Android.mk
+++ b/media/mtp/Android.mk
@@ -47,3 +47,32 @@
 
 endif
 
+ifeq ($(HOST_OS),linux)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:=                                       \
+                  MtpClient.cpp                         \
+                  MtpDataPacket.cpp                     \
+                  MtpDebug.cpp                          \
+                  MtpDevice.cpp                         \
+                  MtpEventPacket.cpp                    \
+                  MtpDeviceInfo.cpp                     \
+                  MtpObjectInfo.cpp                     \
+                  MtpPacket.cpp                         \
+                  MtpProperty.cpp                       \
+                  MtpRequestPacket.cpp                  \
+                  MtpResponsePacket.cpp                 \
+                  MtpStorageInfo.cpp                    \
+                  MtpStringBuffer.cpp                   \
+                  MtpStorage.cpp                        \
+                  MtpUtils.cpp                          \
+                  PtpCursor.cpp                         \
+
+LOCAL_MODULE:= libmtp
+
+LOCAL_CFLAGS := -DMTP_HOST
+
+include $(BUILD_HOST_STATIC_LIBRARY)
+
+endif
diff --git a/media/mtp/MtpDevice.cpp b/media/mtp/MtpDevice.cpp
index 416ebfe..8ad39dc 100644
--- a/media/mtp/MtpDevice.cpp
+++ b/media/mtp/MtpDevice.cpp
@@ -63,17 +63,13 @@
     openSession();
     mDeviceInfo = getDeviceInfo();
     if (mDeviceInfo) {
-        mDeviceInfo->print();
-
         if (mDeviceInfo->mDeviceProperties) {
             int count = mDeviceInfo->mDeviceProperties->size();
             for (int i = 0; i < count; i++) {
                 MtpDeviceProperty propCode = (*mDeviceInfo->mDeviceProperties)[i];
                 MtpProperty* property = getDevicePropDesc(propCode);
-                if (property) {
-                    property->print();
+                if (property)
                     mDeviceProperties.push(property);
-                }
             }
         }
     }
@@ -87,6 +83,45 @@
     }
 }
 
+void MtpDevice::print() {
+    if (mDeviceInfo) {
+        mDeviceInfo->print();
+
+        if (mDeviceInfo->mDeviceProperties) {
+            LOGI("***** DEVICE PROPERTIES *****\n");
+            int count = mDeviceInfo->mDeviceProperties->size();
+            for (int i = 0; i < count; i++) {
+                MtpDeviceProperty propCode = (*mDeviceInfo->mDeviceProperties)[i];
+                MtpProperty* property = getDevicePropDesc(propCode);
+                if (property) {
+                    property->print();
+                }
+            }
+        }
+    }
+
+    if (mDeviceInfo->mPlaybackFormats) {
+            LOGI("***** OBJECT PROPERTIES *****\n");
+        int count = mDeviceInfo->mPlaybackFormats->size();
+        for (int i = 0; i < count; i++) {
+            MtpObjectFormat format = (*mDeviceInfo->mPlaybackFormats)[i];
+            LOGI("*** FORMAT: %s\n", MtpDebug::getFormatCodeName(format));
+            MtpObjectPropertyList* props = getObjectPropsSupported(format);
+            if (props) {
+                for (int j = 0; j < props->size(); j++) {
+                    MtpObjectProperty prop = (*props)[j];
+                    MtpProperty* property = getObjectPropDesc(prop, format);
+                    if (property)
+                        property->print();
+                    else
+                        LOGE("could not fetch property: %s",
+                                MtpDebug::getObjectPropCodeName(prop));
+                }
+            }
+        }
+    }
+}
+
 const char* MtpDevice::getDeviceName() {
     if (mDevice)
         return usb_device_get_name(mDevice);
@@ -330,6 +365,23 @@
         return -1;
 }
 
+MtpObjectPropertyList* MtpDevice::getObjectPropsSupported(MtpObjectFormat format) {
+    Mutex::Autolock autoLock(mMutex);
+
+    mRequest.reset();
+    mRequest.setParameter(1, format);
+    if (!sendRequest(MTP_OPERATION_GET_OBJECT_PROPS_SUPPORTED))
+        return NULL;
+    if (!readData())
+        return NULL;
+    MtpResponseCode ret = readResponse();
+    if (ret == MTP_RESPONSE_OK) {
+        return mData.getAUInt16();
+    }
+    return NULL;
+
+}
+
 MtpProperty* MtpDevice::getDevicePropDesc(MtpDeviceProperty code) {
     Mutex::Autolock autoLock(mMutex);
 
@@ -348,6 +400,25 @@
     return NULL;
 }
 
+MtpProperty* MtpDevice::getObjectPropDesc(MtpObjectProperty code, MtpObjectFormat format) {
+    Mutex::Autolock autoLock(mMutex);
+
+    mRequest.reset();
+    mRequest.setParameter(1, code);
+    mRequest.setParameter(2, format);
+    if (!sendRequest(MTP_OPERATION_GET_OBJECT_PROP_DESC))
+        return NULL;
+    if (!readData())
+        return NULL;
+    MtpResponseCode ret = readResponse();
+    if (ret == MTP_RESPONSE_OK) {
+        MtpProperty* property = new MtpProperty;
+        property->read(mData);
+        return property;
+    }
+    return NULL;
+}
+
 // reads the object's data and writes it to the specified file path
 bool MtpDevice::readObject(MtpObjectHandle handle, const char* destPath, int group, int perm) {
     LOGD("readObject: %s", destPath);
diff --git a/media/mtp/MtpDevice.h b/media/mtp/MtpDevice.h
index 21c85d5..6ffbd24 100644
--- a/media/mtp/MtpDevice.h
+++ b/media/mtp/MtpDevice.h
@@ -67,6 +67,7 @@
 
     void                    initialize();
     void                    close();
+    void                    print();
     const char*             getDeviceName();
 
     bool                    openSession();
@@ -85,7 +86,10 @@
     MtpObjectHandle         getParent(MtpObjectHandle handle);
     MtpObjectHandle         getStorageID(MtpObjectHandle handle);
 
+    MtpObjectPropertyList*  getObjectPropsSupported(MtpObjectFormat format);
+
     MtpProperty*            getDevicePropDesc(MtpDeviceProperty code);
+    MtpProperty*            getObjectPropDesc(MtpObjectProperty code, MtpObjectFormat format);
 
     bool                   readObject(MtpObjectHandle handle, const char* destPath, int group,
                                     int perm);
diff --git a/media/mtp/MtpProperty.cpp b/media/mtp/MtpProperty.cpp
index 4356a6f..b095ce1 100644
--- a/media/mtp/MtpProperty.cpp
+++ b/media/mtp/MtpProperty.cpp
@@ -17,6 +17,7 @@
 #define LOG_TAG "MtpProperty"
 
 #include "MtpDataPacket.h"
+#include "MtpDebug.h"
 #include "MtpProperty.h"
 #include "MtpStringBuffer.h"
 #include "MtpUtils.h"
@@ -121,9 +122,8 @@
 }
 
 void MtpProperty::read(MtpDataPacket& packet) {
-    bool deviceProp = isDeviceProperty();
-
     mCode = packet.getUInt16();
+    bool deviceProp = isDeviceProperty();
     mType = packet.getUInt16();
     mWriteable = (packet.getUInt8() == 1);
     switch (mType) {
@@ -317,9 +317,93 @@
 }
 
 void MtpProperty::print() {
-    LOGV("MtpProperty %04X\n", mCode);
-    LOGV("    type %04X\n", mType);
-    LOGV("    writeable %s\n", (mWriteable ? "true" : "false"));
+    MtpString buffer;
+    bool deviceProp = isDeviceProperty();
+    if (deviceProp)
+        LOGI("    %s (%04X)", MtpDebug::getDevicePropCodeName(mCode), mCode);
+    else
+        LOGI("    %s (%04X)", MtpDebug::getObjectPropCodeName(mCode), mCode);
+    LOGI("    type %04X", mType);
+    LOGI("    writeable %s", (mWriteable ? "true" : "false"));
+    buffer = "    default value: ";
+    print(mDefaultValue, buffer);
+    LOGI("%s", (const char *)buffer);
+    if (deviceProp) {
+        buffer = "    current value: ";
+        print(mCurrentValue, buffer);
+        LOGI("%s", (const char *)buffer);
+    }
+    switch (mFormFlag) {
+        case kFormNone:
+            break;
+        case kFormRange:
+            buffer = "    Range (";
+            print(mMinimumValue, buffer);
+            buffer += ", ";
+            print(mMaximumValue, buffer);
+            buffer += ", ";
+            print(mStepSize, buffer);
+            LOGI("%s", (const char *)buffer);
+            break;
+        case kFormEnum:
+            buffer = "    Enum { ";
+            for (int i = 0; i < mEnumLength; i++) {
+                print(mEnumValues[i], buffer);
+                buffer += " ";
+            }
+            buffer += "}";
+            LOGI("%s", (const char *)buffer);
+            break;
+        case kFormDateTime:
+            LOGI("    DateTime\n");
+            break;
+        default:
+            LOGI("    form %d\n", mFormFlag);
+            break;
+    }
+}
+
+void MtpProperty::print(MtpPropertyValue& value, MtpString& buffer) {
+    switch (mType) {
+        case MTP_TYPE_INT8:
+            buffer.appendFormat("%d", value.u.i8);
+            break;
+        case MTP_TYPE_UINT8:
+            buffer.appendFormat("%d", value.u.u8);
+            break;
+        case MTP_TYPE_INT16:
+            buffer.appendFormat("%d", value.u.i16);
+            break;
+        case MTP_TYPE_UINT16:
+            buffer.appendFormat("%d", value.u.u16);
+            break;
+        case MTP_TYPE_INT32:
+            buffer.appendFormat("%d", value.u.i32);
+            break;
+        case MTP_TYPE_UINT32:
+            buffer.appendFormat("%d", value.u.u32);
+            break;
+        case MTP_TYPE_INT64:
+            buffer.appendFormat("%lld", value.u.i64);
+            break;
+        case MTP_TYPE_UINT64:
+            buffer.appendFormat("%lld", value.u.u64);
+            break;
+        case MTP_TYPE_INT128:
+            buffer.appendFormat("%08X%08X%08X%08X", value.u.i128[0], value.u.i128[1],
+                    value.u.i128[2], value.u.i128[3]);
+            break;
+        case MTP_TYPE_UINT128:
+            buffer.appendFormat("%08X%08X%08X%08X", value.u.u128[0], value.u.u128[1],
+                    value.u.u128[2], value.u.u128[3]);
+            break;
+        case MTP_TYPE_STR:
+            buffer.appendFormat("%s", value.str);
+            break;
+        default:
+            LOGE("unsupported type for MtpProperty::print\n");
+            break;
+    }
 }
 
 void MtpProperty::readValue(MtpDataPacket& packet, MtpPropertyValue& value) {
diff --git a/media/mtp/MtpProperty.h b/media/mtp/MtpProperty.h
index f783a87..06ca56e 100644
--- a/media/mtp/MtpProperty.h
+++ b/media/mtp/MtpProperty.h
@@ -94,6 +94,7 @@
     void                setFormDateTime();
 
     void                print();
+    void                print(MtpPropertyValue& value, MtpString& buffer);
 
     inline bool         isDeviceProperty() const {
                             return (   ((mCode & 0xF000) == 0x5000)
diff --git a/media/mtp/MtpServer.cpp b/media/mtp/MtpServer.cpp
index de6cbac..5c1e02a 100644
--- a/media/mtp/MtpServer.cpp
+++ b/media/mtp/MtpServer.cpp
@@ -423,7 +423,7 @@
     if (!mSessionOpen)
         return MTP_RESPONSE_SESSION_NOT_OPEN;
     MtpObjectFormat format = mRequest.getParameter(1);
-    MtpDevicePropertyList* properties = mDatabase->getSupportedObjectProperties(format);
+    MtpObjectPropertyList* properties = mDatabase->getSupportedObjectProperties(format);
     mData.putAUInt16(properties);
     delete properties;
     return MTP_RESPONSE_OK;
diff --git a/native/include/android/input.h b/native/include/android/input.h
index 861ec8b..e196686 100644
--- a/native/include/android/input.h
+++ b/native/include/android/input.h
@@ -215,7 +215,15 @@
      * tracked from its initial down.  That is, somebody requested that tracking
      * started on the key down and a long press has not caused
      * the tracking to be canceled. */
-    AKEY_EVENT_FLAG_TRACKING = 0x200
+    AKEY_EVENT_FLAG_TRACKING = 0x200,
+
+    /* Set when a key event has been synthesized to implement default behavior
+     * for an event that the application did not handle.
+     * Fallback key events are generated by unhandled trackball motions
+     * (to emulate a directional keypad) and by certain unhandled key presses
+     * that are declared in the key map (such as special function numeric keypad
+     * keys when numlock is off). */
+    AKEY_EVENT_FLAG_FALLBACK = 0x400,
 };
 
 /*
diff --git a/native/include/android/keycodes.h b/native/include/android/keycodes.h
index 5f33ad5..b026a0c 100644
--- a/native/include/android/keycodes.h
+++ b/native/include/android/keycodes.h
@@ -230,6 +230,7 @@
     AKEYCODE_PROG_GREEN      = 184,
     AKEYCODE_PROG_YELLOW     = 185,
     AKEYCODE_PROG_BLUE       = 186,
+    AKEYCODE_APP_SWITCH      = 187,
 
     // NOTE: If you add a new keycode here you must also add it to several other files.
     //       Refer to frameworks/base/core/java/android/view/KeyEvent.java for the full list.
diff --git a/opengl/java/android/opengl/ETC1.java b/opengl/java/android/opengl/ETC1.java
index f3dac77..fb5f9b4 100644
--- a/opengl/java/android/opengl/ETC1.java
+++ b/opengl/java/android/opengl/ETC1.java
@@ -1,11 +1,11 @@
 /*
- *  Copyright 2009 Google Inc.
+ * Copyright (C) 2009 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *     http://www.apache.org/licenses/LICENSE-2.0
+ *      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,
diff --git a/opengl/java/android/opengl/ETC1Util.java b/opengl/java/android/opengl/ETC1Util.java
index dd28d1d..3629d41 100644
--- a/opengl/java/android/opengl/ETC1Util.java
+++ b/opengl/java/android/opengl/ETC1Util.java
@@ -1,11 +1,11 @@
 /*
- *  Copyright 2009 Google Inc.
+ * Copyright (C) 2009 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *     http://www.apache.org/licenses/LICENSE-2.0
+ *      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,
diff --git a/opengl/java/android/opengl/GLES10.java b/opengl/java/android/opengl/GLES10.java
index 790acbd..7c0f949 100644
--- a/opengl/java/android/opengl/GLES10.java
+++ b/opengl/java/android/opengl/GLES10.java
@@ -1,19 +1,18 @@
 /*
-**
-** Copyright 2009, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 
 // This source file is automatically generated
 
diff --git a/opengl/java/android/opengl/GLES10Ext.java b/opengl/java/android/opengl/GLES10Ext.java
index 81fc59e..116ab9d 100644
--- a/opengl/java/android/opengl/GLES10Ext.java
+++ b/opengl/java/android/opengl/GLES10Ext.java
@@ -1,19 +1,18 @@
 /*
-**
-** Copyright 2009, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and 
-** limitations under the License.
-*/
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 
 // This source file is automatically generated
 
diff --git a/opengl/java/android/opengl/GLES11.java b/opengl/java/android/opengl/GLES11.java
index 1ca179b..b24c043 100644
--- a/opengl/java/android/opengl/GLES11.java
+++ b/opengl/java/android/opengl/GLES11.java
@@ -1,19 +1,18 @@
 /*
-**
-** Copyright 2009, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 
 // This source file is automatically generated
 
diff --git a/opengl/java/android/opengl/GLES11Ext.java b/opengl/java/android/opengl/GLES11Ext.java
index 25d5467..a9a7a22 100644
--- a/opengl/java/android/opengl/GLES11Ext.java
+++ b/opengl/java/android/opengl/GLES11Ext.java
@@ -1,19 +1,18 @@
 /*
-**
-** Copyright 2009, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and 
-** limitations under the License.
-*/
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 
 // This source file is automatically generated
 
diff --git a/opengl/java/android/opengl/GLES20.java b/opengl/java/android/opengl/GLES20.java
index 635f811..700164b 100644
--- a/opengl/java/android/opengl/GLES20.java
+++ b/opengl/java/android/opengl/GLES20.java
@@ -1,19 +1,18 @@
 /*
-**
-** Copyright 2009, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License"); 
-** you may not use this file except in compliance with the License. 
-** You may obtain a copy of the License at 
-**
-**     http://www.apache.org/licenses/LICENSE-2.0 
-**
-** Unless required by applicable law or agreed to in writing, software 
-** distributed under the License is distributed on an "AS IS" BASIS, 
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
-** See the License for the specific language governing permissions and 
-** limitations under the License.
-*/
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 
 // This source file is automatically generated
 
diff --git a/opengl/java/com/google/android/gles_jni/EGLConfigImpl.java b/opengl/java/com/google/android/gles_jni/EGLConfigImpl.java
index b03392e..c2f4400 100644
--- a/opengl/java/com/google/android/gles_jni/EGLConfigImpl.java
+++ b/opengl/java/com/google/android/gles_jni/EGLConfigImpl.java
@@ -1,19 +1,18 @@
-/* 
-**
-** Copyright 2006, 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.
-*/
+/*
+ * Copyright (C) 2006 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.google.android.gles_jni;
 
diff --git a/opengl/java/com/google/android/gles_jni/EGLContextImpl.java b/opengl/java/com/google/android/gles_jni/EGLContextImpl.java
index f10c02f..9cf5de7 100644
--- a/opengl/java/com/google/android/gles_jni/EGLContextImpl.java
+++ b/opengl/java/com/google/android/gles_jni/EGLContextImpl.java
@@ -1,19 +1,18 @@
-/* 
-**
-** Copyright 2006, 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.
-*/
+/*
+ * Copyright (C) 2006 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.google.android.gles_jni;
 
diff --git a/opengl/java/com/google/android/gles_jni/EGLDisplayImpl.java b/opengl/java/com/google/android/gles_jni/EGLDisplayImpl.java
index 6321632..cb94888 100644
--- a/opengl/java/com/google/android/gles_jni/EGLDisplayImpl.java
+++ b/opengl/java/com/google/android/gles_jni/EGLDisplayImpl.java
@@ -1,19 +1,18 @@
-/* 
-**
-** Copyright 2006, 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.
-*/
+/*
+ * Copyright (C) 2006 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.google.android.gles_jni;
 
diff --git a/opengl/java/com/google/android/gles_jni/EGLImpl.java b/opengl/java/com/google/android/gles_jni/EGLImpl.java
index 3e06ded..8a7124d 100644
--- a/opengl/java/com/google/android/gles_jni/EGLImpl.java
+++ b/opengl/java/com/google/android/gles_jni/EGLImpl.java
@@ -1,19 +1,18 @@
 /*
-**
-** Copyright 2006, 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.
-*/
+ * Copyright (C) 2006 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.google.android.gles_jni;
 
diff --git a/opengl/java/com/google/android/gles_jni/EGLSurfaceImpl.java b/opengl/java/com/google/android/gles_jni/EGLSurfaceImpl.java
index 66cc200..f6b90ab 100644
--- a/opengl/java/com/google/android/gles_jni/EGLSurfaceImpl.java
+++ b/opengl/java/com/google/android/gles_jni/EGLSurfaceImpl.java
@@ -1,19 +1,18 @@
-/* 
-**
-** Copyright 2006, 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.
-*/
+/*
+ * Copyright (C) 2006 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.google.android.gles_jni;
 
diff --git a/opengl/java/com/google/android/gles_jni/GLImpl.java b/opengl/java/com/google/android/gles_jni/GLImpl.java
index 090c0cb7..50f6760 100644
--- a/opengl/java/com/google/android/gles_jni/GLImpl.java
+++ b/opengl/java/com/google/android/gles_jni/GLImpl.java
@@ -1,19 +1,18 @@
-/* //device/java/android/com/google/android/gles_jni/GLImpl.java
-**
-** Copyright 2006, 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.
-*/
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 
 // This source file is automatically generated
 
diff --git a/opengl/java/javax/microedition/khronos/egl/EGL.java b/opengl/java/javax/microedition/khronos/egl/EGL.java
index b743968..18f8ae6 100644
--- a/opengl/java/javax/microedition/khronos/egl/EGL.java
+++ b/opengl/java/javax/microedition/khronos/egl/EGL.java
@@ -1,19 +1,18 @@
-/* 
-**
-** Copyright 2006, 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.
-*/
+/*
+ * Copyright (C) 2006 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 javax.microedition.khronos.egl;
 
diff --git a/opengl/java/javax/microedition/khronos/egl/EGLConfig.java b/opengl/java/javax/microedition/khronos/egl/EGLConfig.java
index a1e496c..c8a9ba2 100644
--- a/opengl/java/javax/microedition/khronos/egl/EGLConfig.java
+++ b/opengl/java/javax/microedition/khronos/egl/EGLConfig.java
@@ -1,19 +1,18 @@
-/* 
-**
-** Copyright 2006, 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.
-*/
+/*
+ * Copyright (C) 2006 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 javax.microedition.khronos.egl;
 
diff --git a/opengl/java/javax/microedition/khronos/egl/EGLContext.java b/opengl/java/javax/microedition/khronos/egl/EGLContext.java
index fc94492..f8d745d 100644
--- a/opengl/java/javax/microedition/khronos/egl/EGLContext.java
+++ b/opengl/java/javax/microedition/khronos/egl/EGLContext.java
@@ -1,19 +1,18 @@
-/* 
-**
-** Copyright 2006, 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.
-*/
+/*
+ * Copyright (C) 2006 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 javax.microedition.khronos.egl;
 
diff --git a/opengl/java/javax/microedition/khronos/egl/EGLDisplay.java b/opengl/java/javax/microedition/khronos/egl/EGLDisplay.java
index cd8a755..5368b4b 100644
--- a/opengl/java/javax/microedition/khronos/egl/EGLDisplay.java
+++ b/opengl/java/javax/microedition/khronos/egl/EGLDisplay.java
@@ -1,19 +1,18 @@
-/* 
-**
-** Copyright 2006, 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.
-*/
+/*
+ * Copyright (C) 2006 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 javax.microedition.khronos.egl;
 
diff --git a/opengl/java/javax/microedition/khronos/egl/EGLSurface.java b/opengl/java/javax/microedition/khronos/egl/EGLSurface.java
index 5349bc1..e1d08d3 100644
--- a/opengl/java/javax/microedition/khronos/egl/EGLSurface.java
+++ b/opengl/java/javax/microedition/khronos/egl/EGLSurface.java
@@ -1,19 +1,18 @@
-/* 
-**
-** Copyright 2006, 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.
-*/
+/*
+ * Copyright (C) 2006 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 javax.microedition.khronos.egl;
 
diff --git a/opengl/java/javax/microedition/khronos/opengles/GL.java b/opengl/java/javax/microedition/khronos/opengles/GL.java
index 3b78f3d..d5b60c6 100644
--- a/opengl/java/javax/microedition/khronos/opengles/GL.java
+++ b/opengl/java/javax/microedition/khronos/opengles/GL.java
@@ -1,19 +1,18 @@
-/* //device/java/android/javax/microedition/khronos/opengles/GL.java
-**
-** Copyright 2006, 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.
-*/
+/*
+ * Copyright (C) 2006 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 javax.microedition.khronos.opengles;
 
diff --git a/opengl/java/javax/microedition/khronos/opengles/GL10.java b/opengl/java/javax/microedition/khronos/opengles/GL10.java
index 4fcfb52..f48ecde 100644
--- a/opengl/java/javax/microedition/khronos/opengles/GL10.java
+++ b/opengl/java/javax/microedition/khronos/opengles/GL10.java
@@ -1,19 +1,18 @@
-/* //device/java/android/javax/microedition/khronos/opengles/GL10.java
-**
-** Copyright 2006, 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.
-*/
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 
 // This source file is automatically generated
 
diff --git a/opengl/java/javax/microedition/khronos/opengles/GL10Ext.java b/opengl/java/javax/microedition/khronos/opengles/GL10Ext.java
index 562b20a..f3252ab 100644
--- a/opengl/java/javax/microedition/khronos/opengles/GL10Ext.java
+++ b/opengl/java/javax/microedition/khronos/opengles/GL10Ext.java
@@ -1,19 +1,18 @@
-/* //device/java/android/javax/microedition/khronos/opengles/GL10Ext.java
-**
-** Copyright 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License"); 
-** you may not use this file except in compliance with the License. 
-** You may obtain a copy of the License at 
-**
-**     http://www.apache.org/licenses/LICENSE-2.0 
-**
-** Unless required by applicable law or agreed to in writing, software 
-** distributed under the License is distributed on an "AS IS" BASIS, 
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
-** See the License for the specific language governing permissions and 
-** limitations under the License.
-*/
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 
 // This source file is automatically generated
 
diff --git a/opengl/java/javax/microedition/khronos/opengles/GL11.java b/opengl/java/javax/microedition/khronos/opengles/GL11.java
index 3ba110c..943a5be 100644
--- a/opengl/java/javax/microedition/khronos/opengles/GL11.java
+++ b/opengl/java/javax/microedition/khronos/opengles/GL11.java
@@ -1,19 +1,18 @@
-/* //device/java/android/javax/microedition/khronos/opengles/GL11.java
-**
-** Copyright 2006, 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.
-*/
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 
 // This source file is automatically generated
 
diff --git a/opengl/java/javax/microedition/khronos/opengles/GL11Ext.java b/opengl/java/javax/microedition/khronos/opengles/GL11Ext.java
index 459a1ab..842db7a 100644
--- a/opengl/java/javax/microedition/khronos/opengles/GL11Ext.java
+++ b/opengl/java/javax/microedition/khronos/opengles/GL11Ext.java
@@ -1,19 +1,18 @@
-/* //device/java/android/javax/microedition/khronos/opengles/GL11Ext.java
-**
-** Copyright 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License"); 
-** you may not use this file except in compliance with the License. 
-** You may obtain a copy of the License at 
-**
-**     http://www.apache.org/licenses/LICENSE-2.0 
-**
-** Unless required by applicable law or agreed to in writing, software 
-** distributed under the License is distributed on an "AS IS" BASIS, 
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
-** See the License for the specific language governing permissions and 
-** limitations under the License.
-*/
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 
 // This source file is automatically generated
 
diff --git a/opengl/java/javax/microedition/khronos/opengles/GL11ExtensionPack.java b/opengl/java/javax/microedition/khronos/opengles/GL11ExtensionPack.java
index 933c91e..97d5fd8 100644
--- a/opengl/java/javax/microedition/khronos/opengles/GL11ExtensionPack.java
+++ b/opengl/java/javax/microedition/khronos/opengles/GL11ExtensionPack.java
@@ -1,19 +1,18 @@
-/* //device/java/android/javax/microedition/khronos/opengles/GL11ExtensionPack.java
-**
-** Copyright 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License"); 
-** you may not use this file except in compliance with the License. 
-** You may obtain a copy of the License at 
-**
-**     http://www.apache.org/licenses/LICENSE-2.0 
-**
-** Unless required by applicable law or agreed to in writing, software 
-** distributed under the License is distributed on an "AS IS" BASIS, 
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
-** See the License for the specific language governing permissions and 
-** limitations under the License.
-*/
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 
 // This source file is automatically generated
 
diff --git a/opengl/tests/gl2_java/AndroidManifest.xml b/opengl/tests/gl2_java/AndroidManifest.xml
index 585b63f1..8bb6840 100644
--- a/opengl/tests/gl2_java/AndroidManifest.xml
+++ b/opengl/tests/gl2_java/AndroidManifest.xml
@@ -1,21 +1,17 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2009, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License"); 
-** you may not use this file except in compliance with the License. 
-** You may obtain a copy of the License at 
-**
-**     http://www.apache.org/licenses/LICENSE-2.0 
-**
-** Unless required by applicable law or agreed to in writing, software 
-** distributed under the License is distributed on an "AS IS" BASIS, 
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
-** See the License for the specific language governing permissions and 
-** limitations under the License.
-*/
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
 -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
diff --git a/opengl/tests/gl2_java/res/values/strings.xml b/opengl/tests/gl2_java/res/values/strings.xml
index d718b1d..06bd23c 100644
--- a/opengl/tests/gl2_java/res/values/strings.xml
+++ b/opengl/tests/gl2_java/res/values/strings.xml
@@ -1,21 +1,17 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2006, 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.
-*/
+<!-- Copyright (C) 2006 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
 -->
 
 <!-- This file contains resource definitions for displayed strings, allowing
diff --git a/opengl/tests/gl2_jni/AndroidManifest.xml b/opengl/tests/gl2_jni/AndroidManifest.xml
index a72a6a5..1827e5f 100644
--- a/opengl/tests/gl2_jni/AndroidManifest.xml
+++ b/opengl/tests/gl2_jni/AndroidManifest.xml
@@ -1,21 +1,17 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2009, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License"); 
-** you may not use this file except in compliance with the License. 
-** You may obtain a copy of the License at 
-**
-**     http://www.apache.org/licenses/LICENSE-2.0 
-**
-** Unless required by applicable law or agreed to in writing, software 
-** distributed under the License is distributed on an "AS IS" BASIS, 
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
-** See the License for the specific language governing permissions and 
-** limitations under the License.
-*/
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
 -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
diff --git a/opengl/tests/gl2_jni/res/values/strings.xml b/opengl/tests/gl2_jni/res/values/strings.xml
index e3f7331..a29c74b 100644
--- a/opengl/tests/gl2_jni/res/values/strings.xml
+++ b/opengl/tests/gl2_jni/res/values/strings.xml
@@ -1,21 +1,17 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2006, 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.
-*/
+<!-- Copyright (C) 2006 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
 -->
 
 <!-- This file contains resource definitions for displayed strings, allowing
diff --git a/opengl/tests/gl_jni/AndroidManifest.xml b/opengl/tests/gl_jni/AndroidManifest.xml
index 64bd6bf..5d0ec96 100644
--- a/opengl/tests/gl_jni/AndroidManifest.xml
+++ b/opengl/tests/gl_jni/AndroidManifest.xml
@@ -1,21 +1,17 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2009, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License"); 
-** you may not use this file except in compliance with the License. 
-** You may obtain a copy of the License at 
-**
-**     http://www.apache.org/licenses/LICENSE-2.0 
-**
-** Unless required by applicable law or agreed to in writing, software 
-** distributed under the License is distributed on an "AS IS" BASIS, 
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
-** See the License for the specific language governing permissions and 
-** limitations under the License.
-*/
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
 -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
diff --git a/opengl/tests/gl_jni/res/values/strings.xml b/opengl/tests/gl_jni/res/values/strings.xml
index 880f5c9..aee9fa0 100644
--- a/opengl/tests/gl_jni/res/values/strings.xml
+++ b/opengl/tests/gl_jni/res/values/strings.xml
@@ -1,21 +1,17 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2006, 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.
-*/
+<!-- Copyright (C) 2006 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
 -->
 
 <!-- This file contains resource definitions for displayed strings, allowing
diff --git a/opengl/tests/gl_perfapp/AndroidManifest.xml b/opengl/tests/gl_perfapp/AndroidManifest.xml
index 305d95f..ee4bd98 100644
--- a/opengl/tests/gl_perfapp/AndroidManifest.xml
+++ b/opengl/tests/gl_perfapp/AndroidManifest.xml
@@ -1,21 +1,17 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2009, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License"); 
-** you may not use this file except in compliance with the License. 
-** You may obtain a copy of the License at 
-**
-**     http://www.apache.org/licenses/LICENSE-2.0 
-**
-** Unless required by applicable law or agreed to in writing, software 
-** distributed under the License is distributed on an "AS IS" BASIS, 
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
-** See the License for the specific language governing permissions and 
-** limitations under the License.
-*/
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
 -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
diff --git a/opengl/tests/gl_perfapp/res/values/strings.xml b/opengl/tests/gl_perfapp/res/values/strings.xml
index dc21075..52cd961 100644
--- a/opengl/tests/gl_perfapp/res/values/strings.xml
+++ b/opengl/tests/gl_perfapp/res/values/strings.xml
@@ -1,21 +1,17 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2006, 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.
-*/
+<!-- Copyright (C) 2006 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
 -->
 
 <!-- This file contains resource definitions for displayed strings, allowing
diff --git a/opengl/tests/gldual/AndroidManifest.xml b/opengl/tests/gldual/AndroidManifest.xml
index 06f4c4d..a36f4f7 100644
--- a/opengl/tests/gldual/AndroidManifest.xml
+++ b/opengl/tests/gldual/AndroidManifest.xml
@@ -1,21 +1,17 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2009, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License"); 
-** you may not use this file except in compliance with the License. 
-** You may obtain a copy of the License at 
-**
-**     http://www.apache.org/licenses/LICENSE-2.0 
-**
-** Unless required by applicable law or agreed to in writing, software 
-** distributed under the License is distributed on an "AS IS" BASIS, 
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
-** See the License for the specific language governing permissions and 
-** limitations under the License.
-*/
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
 -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
diff --git a/opengl/tests/gldual/res/values/strings.xml b/opengl/tests/gldual/res/values/strings.xml
index 4267dff..b1f535d 100644
--- a/opengl/tests/gldual/res/values/strings.xml
+++ b/opengl/tests/gldual/res/values/strings.xml
@@ -1,21 +1,17 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2006, 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.
-*/
+<!-- Copyright (C) 2006 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
 -->
 
 <!-- This file contains resource definitions for displayed strings, allowing
diff --git a/opengl/tests/testFramerate/AndroidManifest.xml b/opengl/tests/testFramerate/AndroidManifest.xml
index e04342c..85617f4 100644
--- a/opengl/tests/testFramerate/AndroidManifest.xml
+++ b/opengl/tests/testFramerate/AndroidManifest.xml
@@ -1,21 +1,17 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2009, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
 -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
diff --git a/opengl/tests/testFramerate/res/values/strings.xml b/opengl/tests/testFramerate/res/values/strings.xml
index e6b3088..baadf0e 100644
--- a/opengl/tests/testFramerate/res/values/strings.xml
+++ b/opengl/tests/testFramerate/res/values/strings.xml
@@ -1,21 +1,17 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2006, 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.
-*/
+<!-- Copyright (C) 2006 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
 -->
 
 <!-- This file contains resource definitions for displayed strings, allowing
diff --git a/opengl/tests/testLatency/AndroidManifest.xml b/opengl/tests/testLatency/AndroidManifest.xml
index 741266e..59f2643 100644
--- a/opengl/tests/testLatency/AndroidManifest.xml
+++ b/opengl/tests/testLatency/AndroidManifest.xml
@@ -1,21 +1,17 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2009, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
 -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
diff --git a/opengl/tests/testLatency/res/values/strings.xml b/opengl/tests/testLatency/res/values/strings.xml
index 0309991..d80b77c 100644
--- a/opengl/tests/testLatency/res/values/strings.xml
+++ b/opengl/tests/testLatency/res/values/strings.xml
@@ -1,21 +1,17 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2006, 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.
-*/
+<!-- Copyright (C) 2006 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
 -->
 
 <!-- This file contains resource definitions for displayed strings, allowing
diff --git a/opengl/tests/testPauseResume/AndroidManifest.xml b/opengl/tests/testPauseResume/AndroidManifest.xml
index 3e8e7e7..1879bc3 100644
--- a/opengl/tests/testPauseResume/AndroidManifest.xml
+++ b/opengl/tests/testPauseResume/AndroidManifest.xml
@@ -1,21 +1,17 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2009, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License"); 
-** you may not use this file except in compliance with the License. 
-** You may obtain a copy of the License at 
-**
-**     http://www.apache.org/licenses/LICENSE-2.0 
-**
-** Unless required by applicable law or agreed to in writing, software 
-** distributed under the License is distributed on an "AS IS" BASIS, 
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
-** See the License for the specific language governing permissions and 
-** limitations under the License.
-*/
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
 -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
diff --git a/opengl/tests/testPauseResume/res/values/strings.xml b/opengl/tests/testPauseResume/res/values/strings.xml
index 208fe15..b4c98fe2 100644
--- a/opengl/tests/testPauseResume/res/values/strings.xml
+++ b/opengl/tests/testPauseResume/res/values/strings.xml
@@ -1,21 +1,17 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2006, 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.
-*/
+<!-- Copyright (C) 2006 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
 -->
 
 <!-- This file contains resource definitions for displayed strings, allowing
diff --git a/opengl/tests/testViewport/AndroidManifest.xml b/opengl/tests/testViewport/AndroidManifest.xml
index 90a9d2d..ba178bb 100644
--- a/opengl/tests/testViewport/AndroidManifest.xml
+++ b/opengl/tests/testViewport/AndroidManifest.xml
@@ -1,21 +1,17 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2009, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License"); 
-** you may not use this file except in compliance with the License. 
-** You may obtain a copy of the License at 
-**
-**     http://www.apache.org/licenses/LICENSE-2.0 
-**
-** Unless required by applicable law or agreed to in writing, software 
-** distributed under the License is distributed on an "AS IS" BASIS, 
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
-** See the License for the specific language governing permissions and 
-** limitations under the License.
-*/
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
 -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
diff --git a/opengl/tests/testViewport/res/values/strings.xml b/opengl/tests/testViewport/res/values/strings.xml
index f4b8bbb..c037a7c 100644
--- a/opengl/tests/testViewport/res/values/strings.xml
+++ b/opengl/tests/testViewport/res/values/strings.xml
@@ -1,21 +1,17 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2006, 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.
-*/
+<!-- Copyright (C) 2006 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
 -->
 
 <!-- This file contains resource definitions for displayed strings, allowing
diff --git a/opengl/tools/glgen/stubs/gles11/glGetString.java b/opengl/tools/glgen/stubs/gles11/glGetString.java
index d44a6dd..b02a0d1 100644
--- a/opengl/tools/glgen/stubs/gles11/glGetString.java
+++ b/opengl/tools/glgen/stubs/gles11/glGetString.java
@@ -1,21 +1,21 @@
-/*

- * Copyright (C) 2009 The Android Open Source Project

- *

- * Licensed under the Apache License, Version 2.0 (the "License");

- * you may not use this file except in compliance with the License.

- * You may obtain a copy of the License at

- *

- *      http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-

-    // C function const GLubyte * glGetString ( GLenum name )

-

-    public static native String glGetString(

-        int name

-    );

+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+    // C function const GLubyte * glGetString ( GLenum name )
+
+    public static native String glGetString(
+        int name
+    );
diff --git a/packages/DefaultContainerService/Android.mk b/packages/DefaultContainerService/Android.mk
index 986b6c8..56b8005 100755
--- a/packages/DefaultContainerService/Android.mk
+++ b/packages/DefaultContainerService/Android.mk
@@ -7,7 +7,7 @@
 
 LOCAL_PACKAGE_NAME := DefaultContainerService
 
-LOCAL_JNI_SHARED_LIBRARIES := libdefcontainer_jni
+LOCAL_REQUIRED_MODULES := libdefcontainer_jni
 
 LOCAL_CERTIFICATE := platform
 
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index c3112d88..e61dd6c 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -133,6 +133,7 @@
     static final boolean DEBUG = false;
     static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
     static final boolean DEBUG_LAYOUT = false;
+    static final boolean DEBUG_FALLBACK = false;
     static final boolean SHOW_STARTING_ANIMATIONS = true;
     static final boolean SHOW_PROCESSES_ON_ALT_MENU = false;
 
@@ -315,8 +316,8 @@
     Intent mHomeIntent;
     Intent mCarDockIntent;
     Intent mDeskDockIntent;
-    boolean mSearchKeyPressed;
-    boolean mConsumeSearchKeyUp;
+    int mShortcutKeyPressed = -1;
+    boolean mConsumeShortcutKeyUp;
     boolean mShowMenuKey = false; // track FLAG_NEEDS_MENU_KEY on frontmost window
 
     // support for activating the lock screen while the screen is on
@@ -345,6 +346,8 @@
     ShortcutManager mShortcutManager;
     PowerManager.WakeLock mBroadcastWakeLock;
 
+    final KeyCharacterMap.FallbackAction mFallbackAction = new KeyCharacterMap.FallbackAction();
+
     class SettingsObserver extends ContentObserver {
         SettingsObserver(Handler handler) {
             super(handler);
@@ -1228,56 +1231,44 @@
                     + repeatCount + " keyguardOn=" + keyguardOn + " mHomePressed=" + mHomePressed);
         }
 
-        // Clear a pending HOME longpress if the user releases Home
-        // TODO: This could probably be inside the next bit of logic, but that code
-        // turned out to be a bit fragile so I'm doing it here explicitly, for now.
-        if ((keyCode == KeyEvent.KEYCODE_HOME) && !down) {
-            mHandler.removeCallbacks(mHomeLongPress);
-        }
-
-        // If the HOME button is currently being held, then we do special
-        // chording with it.
-        if (mHomePressed) {
-            
-            // If we have released the home key, and didn't do anything else
-            // while it was pressed, then it is time to go home!
-            if (keyCode == KeyEvent.KEYCODE_HOME) {
-                if (!down) {
-                    mHomePressed = false;
-                    
-                    if (!canceled) {
-                        // If an incoming call is ringing, HOME is totally disabled.
-                        // (The user is already on the InCallScreen at this point,
-                        // and his ONLY options are to answer or reject the call.)
-                        boolean incomingRinging = false;
-                        try {
-                            ITelephony telephonyService = getTelephonyService();
-                            if (telephonyService != null) {
-                                incomingRinging = telephonyService.isRinging();
-                            }
-                        } catch (RemoteException ex) {
-                            Log.w(TAG, "RemoteException from getPhoneInterface()", ex);
-                        }
-        
-                        if (incomingRinging) {
-                            Log.i(TAG, "Ignoring HOME; there's a ringing incoming call.");
-                        } else {
-                            launchHomeFromHotKey();
-                        }
-                    } else {
-                        Log.i(TAG, "Ignoring HOME; event canceled.");
-                    }
-                }
-            }
-            
-            return true;
-        }
-        
         // First we always handle the home key here, so applications
         // can never break it, although if keyguard is on, we do let
         // it handle it, because that gives us the correct 5 second
         // timeout.
         if (keyCode == KeyEvent.KEYCODE_HOME) {
+            // Clear a pending HOME longpress if the user releases Home
+            if (!down) {
+                mHandler.removeCallbacks(mHomeLongPress);
+            }
+
+            // If we have released the home key, and didn't do anything else
+            // while it was pressed, then it is time to go home!
+            if (mHomePressed && !down) {
+                mHomePressed = false;
+                if (!canceled) {
+                    // If an incoming call is ringing, HOME is totally disabled.
+                    // (The user is already on the InCallScreen at this point,
+                    // and his ONLY options are to answer or reject the call.)
+                    boolean incomingRinging = false;
+                    try {
+                        ITelephony telephonyService = getTelephonyService();
+                        if (telephonyService != null) {
+                            incomingRinging = telephonyService.isRinging();
+                        }
+                    } catch (RemoteException ex) {
+                        Log.w(TAG, "RemoteException from getPhoneInterface()", ex);
+                    }
+
+                    if (incomingRinging) {
+                        Log.i(TAG, "Ignoring HOME; there's a ringing incoming call.");
+                    } else {
+                        launchHomeFromHotKey();
+                    }
+                } else {
+                    Log.i(TAG, "Ignoring HOME; event canceled.");
+                }
+                return true;
+            }
 
             // If a system window has focus, then it doesn't make sense
             // right now to interact with applications.
@@ -1334,21 +1325,28 @@
         } else if (keyCode == KeyEvent.KEYCODE_SEARCH) {
             if (down) {
                 if (repeatCount == 0) {
-                    mSearchKeyPressed = true;
+                    mShortcutKeyPressed = keyCode;
+                    mConsumeShortcutKeyUp = false;
                 }
-            } else {
-                mSearchKeyPressed = false;
+            } else if (keyCode == mShortcutKeyPressed) {
+                mShortcutKeyPressed = -1;
                 
-                if (mConsumeSearchKeyUp) {
+                if (mConsumeShortcutKeyUp) {
                     // Consume the up-event
-                    mConsumeSearchKeyUp = false;
+                    mConsumeShortcutKeyUp = false;
                     return true;
                 }
             }
+        } else if (keyCode == KeyEvent.KEYCODE_APP_SWITCH) {
+            if (!down) {
+                showRecentAppsDialog();
+            }
+            return true;
         }
         
-        // Shortcuts are invoked through Search+key, so intercept those here
-        if (mSearchKeyPressed) {
+        // Shortcuts are invoked through Search+key or Meta+key, so intercept those here
+        if ((mShortcutKeyPressed != -1 && !mConsumeShortcutKeyUp)
+                || (metaState & KeyEvent.META_META_ON) != 0) {
             if (down && repeatCount == 0 && !keyguardOn) {
                 Intent shortcutIntent = mShortcutManager.getIntent(event);
                 if (shortcutIntent != null) {
@@ -1359,7 +1357,9 @@
                      * We launched an app, so the up-event of the search key
                      * should be consumed
                      */
-                    mConsumeSearchKeyUp = true;
+                    if (mShortcutKeyPressed != -1) {
+                        mConsumeShortcutKeyUp = true;
+                    }
                     return true;
                 }
             }
@@ -1370,8 +1370,8 @@
 
     /** {@inheritDoc} */
     @Override
-    public boolean dispatchUnhandledKey(WindowState win, KeyEvent event, int policyFlags) {
-        if (false) {
+    public KeyEvent dispatchUnhandledKey(WindowState win, KeyEvent event, int policyFlags) {
+        if (DEBUG_FALLBACK) {
             Slog.d(TAG, "Unhandled key: win=" + win + ", action=" + event.getAction()
                     + ", flags=" + event.getFlags()
                     + ", keyCode=" + event.getKeyCode()
@@ -1380,7 +1380,42 @@
                     + ", repeatCount=" + event.getRepeatCount()
                     + ", policyFlags=" + policyFlags);
         }
-        return false;
+
+        if ((event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
+            final KeyCharacterMap kcm = event.getKeyCharacterMap();
+            boolean fallback = kcm.getFallbackAction(event.getKeyCode(), event.getMetaState(),
+                    mFallbackAction);
+
+            if (fallback) {
+                if (DEBUG_FALLBACK) {
+                    Slog.d(TAG, "Fallback: keyCode=" + mFallbackAction.keyCode
+                            + " metaState=" + Integer.toHexString(mFallbackAction.metaState));
+                }
+
+                int flags = event.getFlags() | KeyEvent.FLAG_FALLBACK;
+                KeyEvent fallbackEvent = KeyEvent.obtain(
+                        event.getDownTime(), event.getEventTime(),
+                        event.getAction(), mFallbackAction.keyCode,
+                        event.getRepeatCount(), mFallbackAction.metaState,
+                        event.getDeviceId(), event.getScanCode(),
+                        flags, event.getSource(), null);
+                int actions = interceptKeyBeforeQueueing(fallbackEvent, policyFlags, true);
+                if ((actions & ACTION_PASS_TO_USER) != 0) {
+                    if (!interceptKeyBeforeDispatching(win, fallbackEvent, policyFlags)) {
+                        if (DEBUG_FALLBACK) {
+                            Slog.d(TAG, "Performing fallback.");
+                        }
+                        return fallbackEvent;
+                    }
+                }
+                fallbackEvent.recycle();
+            }
+        }
+
+        if (DEBUG_FALLBACK) {
+            Slog.d(TAG, "No fallback.");
+        }
+        return null;
     }
 
     /**
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 535f07f..f1fa0ff 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -1015,7 +1015,10 @@
 
     sp<Client> client = getClientFromCookie(user);
     if (client == 0) return;
-    if (!client->lockIfMessageWanted(msgType)) return;
+    if (!client->lockIfMessageWanted(msgType)) {
+        client->releaseRecordingFrame(dataPtr);
+        return;
+    }
 
     if (dataPtr == 0) {
         LOGE("Null data returned in data with timestamp callback");
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index 758f9f3..9d11d87 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -387,7 +387,6 @@
          * the number of different network types is not going
          * to change very often.
          */
-        boolean noMobileData = !getMobileDataEnabled();
         for (int netType : mPriorityList) {
             switch (mNetAttributes[netType].mRadio) {
             case ConnectivityManager.TYPE_WIFI:
@@ -407,10 +406,6 @@
                 mNetTrackers[netType] = new MobileDataStateTracker(netType,
                         mNetAttributes[netType].mName);
                 mNetTrackers[netType].startMonitoring(context, mHandler);
-                if (noMobileData) {
-                    if (DBG) log("tearing down Mobile networks due to setting");
-                    mNetTrackers[netType].teardown();
-                }
                 break;
             case ConnectivityManager.TYPE_DUMMY:
                 mNetTrackers[netType] = new DummyDataStateTracker(netType,
@@ -691,10 +686,6 @@
         // TODO - move this into the MobileDataStateTracker
         int usedNetworkType = networkType;
         if(networkType == ConnectivityManager.TYPE_MOBILE) {
-            if (!getMobileDataEnabled()) {
-                if (DBG) log("requested special network with data disabled - rejected");
-                return Phone.APN_TYPE_NOT_AVAILABLE;
-            }
             if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_MMS)) {
                 usedNetworkType = ConnectivityManager.TYPE_MOBILE_MMS;
             } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_SUPL)) {
@@ -985,6 +976,9 @@
      * @see ConnectivityManager#getMobileDataEnabled()
      */
     public boolean getMobileDataEnabled() {
+        // TODO: This detail should probably be in DataConnectionTracker's
+        //       which is where we store the value and maybe make this
+        //       asynchronous.
         enforceAccessPermission();
         boolean retVal = Settings.Secure.getInt(mContext.getContentResolver(),
                 Settings.Secure.MOBILE_DATA, 1) == 1;
@@ -1004,42 +998,14 @@
     }
 
     private void handleSetMobileData(boolean enabled) {
-        if (getMobileDataEnabled() == enabled) return;
-
-        Settings.Secure.putInt(mContext.getContentResolver(),
-                Settings.Secure.MOBILE_DATA, enabled ? 1 : 0);
-
-        if (enabled) {
-            if (mNetTrackers[ConnectivityManager.TYPE_MOBILE] != null) {
-                if (DBG) {
-                    log("starting up " + mNetTrackers[ConnectivityManager.TYPE_MOBILE]);
-                }
-                mNetTrackers[ConnectivityManager.TYPE_MOBILE].reconnect();
+        if (mNetTrackers[ConnectivityManager.TYPE_MOBILE] != null) {
+            if (DBG) {
+                Slog.d(TAG, mNetTrackers[ConnectivityManager.TYPE_MOBILE].toString() + enabled);
             }
-        } else {
-            for (NetworkStateTracker nt : mNetTrackers) {
-                if (nt == null) continue;
-                int netType = nt.getNetworkInfo().getType();
-                if (mNetAttributes[netType].mRadio == ConnectivityManager.TYPE_MOBILE) {
-                    if (DBG) log("tearing down " + nt);
-                    nt.teardown();
-                }
-            }
+            mNetTrackers[ConnectivityManager.TYPE_MOBILE].setDataEnable(enabled);
         }
     }
 
-    private int getNumConnectedNetworks() {
-        int numConnectedNets = 0;
-
-        for (NetworkStateTracker nt : mNetTrackers) {
-            if (nt != null && nt.getNetworkInfo().isConnected() &&
-                    !nt.isTeardownRequested()) {
-                ++numConnectedNets;
-            }
-        }
-        return numConnectedNets;
-    }
-
     private void enforceAccessPermission() {
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.ACCESS_NETWORK_STATE,
@@ -1159,16 +1125,9 @@
 
             int newType = -1;
             int newPriority = -1;
-            boolean noMobileData = !getMobileDataEnabled();
             for (int checkType=0; checkType <= ConnectivityManager.MAX_NETWORK_TYPE; checkType++) {
                 if (checkType == prevNetType) continue;
                 if (mNetAttributes[checkType] == null) continue;
-                if (mNetAttributes[checkType].mRadio == ConnectivityManager.TYPE_MOBILE &&
-                        noMobileData) {
-                    loge("not failing over to mobile type " + checkType +
-                            " because Mobile Data Disabled");
-                    continue;
-                }
                 if (mNetAttributes[checkType].isDefault()) {
                     /* TODO - if we have multiple nets we could use
                      * we may want to put more thought into which we choose
diff --git a/services/java/com/android/server/InputManager.java b/services/java/com/android/server/InputManager.java
index 8634eec..4c499cd 100644
--- a/services/java/com/android/server/InputManager.java
+++ b/services/java/com/android/server/InputManager.java
@@ -402,7 +402,7 @@
         }
         
         @SuppressWarnings("unused")
-        public boolean dispatchUnhandledKey(InputChannel focus,
+        public KeyEvent dispatchUnhandledKey(InputChannel focus,
                 KeyEvent event, int policyFlags) {
             return mWindowManagerService.mInputMonitor.dispatchUnhandledKey(
                     focus, event, policyFlags);
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index 2d88b2f..f78ebb9 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -5844,7 +5844,7 @@
         
         /* Provides an opportunity for the window manager policy to process a key that
          * the application did not handle. */
-        public boolean dispatchUnhandledKey(
+        public KeyEvent dispatchUnhandledKey(
                 InputChannel focus, KeyEvent event, int policyFlags) {
             WindowState windowState = getWindowStateForInputChannel(focus);
             return mPolicy.dispatchUnhandledKey(windowState, event, policyFlags);
diff --git a/services/jni/com_android_server_InputManager.cpp b/services/jni/com_android_server_InputManager.cpp
index 1996dd0..9156249 100644
--- a/services/jni/com_android_server_InputManager.cpp
+++ b/services/jni/com_android_server_InputManager.cpp
@@ -183,7 +183,7 @@
     virtual bool interceptKeyBeforeDispatching(const sp<InputChannel>& inputChannel,
             const KeyEvent* keyEvent, uint32_t policyFlags);
     virtual bool dispatchUnhandledKey(const sp<InputChannel>& inputChannel,
-            const KeyEvent* keyEvent, uint32_t policyFlags);
+            const KeyEvent* keyEvent, uint32_t policyFlags, KeyEvent* outFallbackKeyEvent);
     virtual void pokeUserActivity(nsecs_t eventTime, int32_t eventType);
     virtual bool checkInjectEventsPermissionNonReentrant(
             int32_t injectorPid, int32_t injectorUid);
@@ -813,7 +813,7 @@
     // - Ignore untrusted events and pass them along.
     // - Filter normal events and trusted injected events through the window manager policy to
     //   handle the HOME key and the like.
-    bool result;
+    bool result = false;
     if (policyFlags & POLICY_FLAG_TRUSTED) {
         JNIEnv* env = jniEnv();
 
@@ -830,21 +830,17 @@
             result = consumed && !error;
         } else {
             LOGE("Failed to obtain key event object for interceptKeyBeforeDispatching.");
-            result = false;
         }
-
         env->DeleteLocalRef(inputChannelObj);
-    } else {
-        result = false;
     }
     return result;
 }
 
 bool NativeInputManager::dispatchUnhandledKey(const sp<InputChannel>& inputChannel,
-        const KeyEvent* keyEvent, uint32_t policyFlags) {
+        const KeyEvent* keyEvent, uint32_t policyFlags, KeyEvent* outFallbackKeyEvent) {
     // Policy:
     // - Ignore untrusted events and do not perform default handling.
-    bool result;
+    bool result = false;
     if (policyFlags & POLICY_FLAG_TRUSTED) {
         JNIEnv* env = jniEnv();
 
@@ -852,21 +848,26 @@
         jobject inputChannelObj = getInputChannelObjLocal(env, inputChannel);
         jobject keyEventObj = android_view_KeyEvent_fromNative(env, keyEvent);
         if (keyEventObj) {
-            jboolean handled = env->CallBooleanMethod(mCallbacksObj,
+            jobject fallbackKeyEventObj = env->CallObjectMethod(mCallbacksObj,
                     gCallbacksClassInfo.dispatchUnhandledKey,
                     inputChannelObj, keyEventObj, policyFlags);
-            bool error = checkAndClearExceptionFromCallback(env, "dispatchUnhandledKey");
+            checkAndClearExceptionFromCallback(env, "dispatchUnhandledKey");
             android_view_KeyEvent_recycle(env, keyEventObj);
             env->DeleteLocalRef(keyEventObj);
-            result = handled && !error;
+
+            if (fallbackKeyEventObj) {
+                // Note: outFallbackKeyEvent may be the same object as keyEvent.
+                if (!android_view_KeyEvent_toNative(env, fallbackKeyEventObj,
+                        outFallbackKeyEvent)) {
+                    result = true;
+                }
+                android_view_KeyEvent_recycle(env, fallbackKeyEventObj);
+                env->DeleteLocalRef(fallbackKeyEventObj);
+            }
         } else {
             LOGE("Failed to obtain key event object for dispatchUnhandledKey.");
-            result = false;
         }
-
         env->DeleteLocalRef(inputChannelObj);
-    } else {
-        result = false;
     }
     return result;
 }
@@ -1307,7 +1308,8 @@
             "(Landroid/view/InputChannel;Landroid/view/KeyEvent;I)Z");
 
     GET_METHOD_ID(gCallbacksClassInfo.dispatchUnhandledKey, gCallbacksClassInfo.clazz,
-            "dispatchUnhandledKey", "(Landroid/view/InputChannel;Landroid/view/KeyEvent;I)Z");
+            "dispatchUnhandledKey",
+            "(Landroid/view/InputChannel;Landroid/view/KeyEvent;I)Landroid/view/KeyEvent;");
 
     GET_METHOD_ID(gCallbacksClassInfo.checkInjectEventsPermission, gCallbacksClassInfo.clazz,
             "checkInjectEventsPermission", "(II)Z");
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 145618e..fe4379d 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -58,7 +58,7 @@
         mSecure(false),
         mTextureManager(),
         mBufferManager(mTextureManager),
-        mWidth(0), mHeight(0), mFixedSize(false)
+        mWidth(0), mHeight(0), mNeedsScaling(false), mFixedSize(false)
 {
 }
 
@@ -274,13 +274,10 @@
 
 void Layer::drawForSreenShot() const
 {
-    bool currentFixedSize = mFixedSize;
-    bool currentBlending = mNeedsBlending;
-    const_cast<Layer*>(this)->mFixedSize = false;
-    const_cast<Layer*>(this)->mFixedSize = true;
+    const bool currentFiltering = mNeedsFiltering;
+    const_cast<Layer*>(this)->mNeedsFiltering = true;
     LayerBase::drawForSreenShot();
-    const_cast<Layer*>(this)->mFixedSize = currentFixedSize;
-    const_cast<Layer*>(this)->mNeedsBlending = currentBlending;
+    const_cast<Layer*>(this)->mNeedsFiltering = currentFiltering;
 }
 
 void Layer::onDraw(const Region& clip) const
@@ -318,11 +315,10 @@
 bool Layer::needsFiltering() const
 {
     if (!(mFlags & DisplayHardware::SLOW_CONFIG)) {
-        // NOTE: there is a race here, because mFixedSize is updated in a
-        // binder transaction. however, it doesn't really matter since it is
-        // evaluated each time we draw. To be perfectly correct, this flag
-        // would have to be associated with a buffer.
-        if (mFixedSize)
+        // if our buffer is not the same size than ourselves,
+        // we need filtering.
+        Mutex::Autolock _l(mLock);
+        if (mNeedsScaling)
             return true;
     }
     return LayerBase::needsFiltering();
@@ -396,6 +392,7 @@
             mReqHeight = reqHeight;
             mReqFormat = reqFormat;
             mFixedSize = fixedSize;
+            mNeedsScaling = mWidth != mReqWidth || mHeight != mReqHeight;
 
             lcblk->reallocateAllExcept(index);
         }
@@ -409,6 +406,7 @@
     err = buffer->initCheck();
 
     if (err || buffer->handle == 0) {
+        GraphicBuffer::dumpAllocationsToSystemLog();
         LOGE_IF(err || buffer->handle == 0,
                 "Layer::requestBuffer(this=%p), index=%d, w=%d, h=%d failed (%s)",
                 this, index, w, h, strerror(-err));
@@ -518,6 +516,7 @@
     Mutex::Autolock _l(mLock);
     mWidth = w;
     mHeight = h;
+    mNeedsScaling = mWidth != mReqWidth || mHeight != mReqHeight;
 }
 
 bool Layer::isFixedSize() const {
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 07434cf..30021d3 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -233,6 +233,7 @@
     uint32_t mReqWidth;
     uint32_t mReqHeight;
     uint32_t mReqFormat;
+    bool mNeedsScaling;
     bool mFixedSize;
 };
 
diff --git a/services/surfaceflinger/LayerBase.cpp b/services/surfaceflinger/LayerBase.cpp
index df6aa51..28b02c9 100644
--- a/services/surfaceflinger/LayerBase.cpp
+++ b/services/surfaceflinger/LayerBase.cpp
@@ -216,14 +216,10 @@
         flags |= eVisibleRegion;
         this->contentDirty = true;
 
-        mNeedsFiltering = false;
-        if (!(mFlags & DisplayHardware::SLOW_CONFIG)) {
-            // we may use linear filtering, if the matrix scales us
-            const uint8_t type = temp.transform.getType();
-            if (!temp.transform.preserveRects() || (type >= Transform::SCALE)) {
-                mNeedsFiltering = true;
-            }
-        }
+        // we may use linear filtering, if the matrix scales us
+        const uint8_t type = temp.transform.getType();
+        mNeedsFiltering = (!temp.transform.preserveRects() ||
+                (type >= Transform::SCALE));
     }
 
     // Commit the transaction
diff --git a/services/surfaceflinger/LayerBase.h b/services/surfaceflinger/LayerBase.h
index bdee05b..135b3a6 100644
--- a/services/surfaceflinger/LayerBase.h
+++ b/services/surfaceflinger/LayerBase.h
@@ -37,6 +37,7 @@
 
 #include <hardware/hwcomposer.h>
 
+#include "DisplayHardware/DisplayHardware.h"
 #include "Transform.h"
 
 namespace android {
@@ -191,7 +192,9 @@
     /**
      * needsLinearFiltering - true if this surface needs filtering
      */
-    virtual bool needsFiltering() const { return mNeedsFiltering; }
+    virtual bool needsFiltering() const {
+        return (!(mFlags & DisplayHardware::SLOW_CONFIG)) && mNeedsFiltering;
+    }
 
     /**
      * isSecure - true if this surface is secure, that is if it prevents
diff --git a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
index 069e1b8..737342f 100644
--- a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
@@ -30,6 +30,7 @@
 import android.os.AsyncResult;
 import android.os.Handler;
 import android.os.Message;
+import android.os.Messenger;
 import android.os.ServiceManager;
 import android.preference.PreferenceManager;
 import android.provider.Settings;
@@ -81,6 +82,10 @@
         DORMANT
     }
 
+    public static String ACTION_DATA_CONNECTION_TRACKER_MESSENGER =
+        "com.android.internal.telephony";
+    public static String EXTRA_MESSENGER = "EXTRA_MESSENGER";
+
     /***** Event Codes *****/
     protected static final int EVENT_DATA_SETUP_COMPLETE = 1;
     protected static final int EVENT_RADIO_AVAILABLE = 3;
@@ -113,6 +118,8 @@
     protected static final int EVENT_SET_INTERNAL_DATA_ENABLE = 37;
     protected static final int EVENT_RESET_DONE = 38;
 
+    public static final int CMD_SET_DATA_ENABLE = 39;
+
     /***** Constants *****/
 
     protected static final int APN_INVALID_ID = -1;
@@ -123,13 +130,18 @@
     protected static final int APN_HIPRI_ID = 4;
     protected static final int APN_NUM_TYPES = 5;
 
-    protected static final int DISABLED = 0;
-    protected static final int ENABLED = 1;
+    public static final int DISABLED = 0;
+    public static final int ENABLED = 1;
 
     // responds to the setInternalDataEnabled call - used internally to turn off data
     // for example during emergency calls
     protected boolean mInternalDataEnabled = true;
 
+    // responds to public (user) API to enable/disable data use
+    // independent of mInternalDataEnabled and requests for APN access
+    // persisted
+    protected boolean mDataEnabled = true;
+
     protected boolean[] dataEnabled = new boolean[APN_NUM_TYPES];
 
     protected int enabledCount = 0;
@@ -289,6 +301,9 @@
         filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
         filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
 
+        mDataEnabled = Settings.Secure.getInt(mPhone.getContext().getContentResolver(),
+                Settings.Secure.MOBILE_DATA, 1) == 1;
+
         // TODO: Why is this registering the phone as the receiver of the intent
         //       and not its own handler?
         mPhone.getContext().registerReceiver(mIntentReceiver, filter, null, mPhone);
@@ -296,16 +311,8 @@
         // This preference tells us 1) initial condition for "dataEnabled",
         // and 2) whether the RIL will setup the baseband to auto-PS attach.
         SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mPhone.getContext());
-        boolean dataEnabledSetting = true;
-        try {
-            dataEnabledSetting = IConnectivityManager.Stub.asInterface(ServiceManager.
-                    getService(Context.CONNECTIVITY_SERVICE)).getMobileDataEnabled();
-        } catch (Exception e) {
-            // nothing to do - use the old behavior and leave data on
-        }
         dataEnabled[APN_DEFAULT_ID] =
-                !sp.getBoolean(PhoneBase.DATA_DISABLED_ON_BOOT_KEY, false) &&
-                dataEnabledSetting;
+                !sp.getBoolean(PhoneBase.DATA_DISABLED_ON_BOOT_KEY, false);
         if (dataEnabled[APN_DEFAULT_ID]) {
             enabledCount++;
         }
@@ -316,6 +323,12 @@
         mPhone.getContext().unregisterReceiver(this.mIntentReceiver);
     }
 
+    protected void broadcastMessenger() {
+        Intent intent = new Intent(ACTION_DATA_CONNECTION_TRACKER_MESSENGER);
+        intent.putExtra(EXTRA_MESSENGER, new Messenger(this));
+        mPhone.getContext().sendBroadcast(intent);
+    }
+
     public Activity getActivity() {
         return mActivity;
     }
@@ -490,14 +503,20 @@
                 onCleanUpConnection(tearDown, (String) msg.obj);
                 break;
 
-            case EVENT_SET_INTERNAL_DATA_ENABLE:
+            case EVENT_SET_INTERNAL_DATA_ENABLE: {
                 boolean enabled = (msg.arg1 == ENABLED) ? true : false;
                 onSetInternalDataEnabled(enabled);
                 break;
-
+            }
             case EVENT_RESET_DONE:
                 onResetDone((AsyncResult) msg.obj);
                 break;
+            case CMD_SET_DATA_ENABLE: {
+                log("CMD_SET_DATA_ENABLE msg=" + msg);
+                boolean enabled = (msg.arg1 == ENABLED) ? true : false;
+                onSetDataEnabled(enabled);
+                break;
+            }
 
             default:
                 Log.e("DATA", "Unidentified event = " + msg.what);
@@ -512,7 +531,7 @@
      *         {@code true} otherwise.
      */
     public synchronized boolean getAnyDataEnabled() {
-        return (mInternalDataEnabled && (enabledCount != 0));
+        return (mInternalDataEnabled && mDataEnabled && (enabledCount != 0));
     }
 
     protected abstract void startNetStatPoll();
@@ -828,11 +847,6 @@
      * Prevent mobile data connections from being established, or once again
      * allow mobile data connections. If the state toggles, then either tear
      * down or set up data, as appropriate to match the new state.
-     * <p>
-     * This operation only affects the default APN, and if the same APN is
-     * currently being used for MMS traffic, the teardown will not happen even
-     * when {@code enable} is {@code false}.
-     * </p>
      *
      * @param enable indicates whether to enable ({@code true}) or disable (
      *            {@code false}) data
@@ -849,15 +863,41 @@
     }
 
     protected void onSetInternalDataEnabled(boolean enable) {
+        boolean prevEnabled = getAnyDataEnabled();
         if (mInternalDataEnabled != enable) {
             synchronized (this) {
                 mInternalDataEnabled = enable;
             }
-            if (enable) {
-                mRetryMgr.resetRetryCount();
-                onTrySetupData(Phone.REASON_DATA_ENABLED);
-            } else {
-                onCleanUpConnection(true, Phone.REASON_DATA_DISABLED);
+            if (prevEnabled != getAnyDataEnabled()) {
+                if (!prevEnabled) {
+                    mRetryMgr.resetRetryCount();
+                    onTrySetupData(Phone.REASON_DATA_ENABLED);
+                } else {
+                    onCleanUpConnection(true, Phone.REASON_DATA_DISABLED);
+                }
+            }
+        }
+    }
+
+    public synchronized boolean getDataEnabled() {
+        return mDataEnabled;
+    }
+
+    protected void onSetDataEnabled(boolean enable) {
+        boolean prevEnabled = getAnyDataEnabled();
+        if (mDataEnabled != enable) {
+            synchronized (this) {
+                mDataEnabled = enable;
+            }
+            Settings.Secure.putInt(mPhone.getContext().getContentResolver(),
+                    Settings.Secure.MOBILE_DATA, enable ? 1 : 0);
+            if (prevEnabled != getAnyDataEnabled()) {
+                if (!prevEnabled) {
+                    mRetryMgr.resetRetryCount();
+                    onTrySetupData(Phone.REASON_DATA_ENABLED);
+                } else {
+                    onCleanUpConnection(true, Phone.REASON_DATA_DISABLED);
+                }
             }
         }
     }
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
index b005cd3..60df7df 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
@@ -113,6 +113,7 @@
         mDataConnectionTracker = this;
 
         createAllDataConnectionList();
+        broadcastMessenger();
     }
 
     @Override
diff --git a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
index 8accfd1..4911644 100644
--- a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
+++ b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
@@ -29,6 +29,7 @@
 import com.android.internal.telephony.cdma.sms.CdmaSmsSubaddress;
 import com.android.internal.telephony.cdma.sms.SmsEnvelope;
 import com.android.internal.telephony.cdma.sms.UserData;
+import com.android.internal.util.BitwiseInputStream;
 import com.android.internal.util.HexDump;
 
 import java.io.BufferedOutputStream;
@@ -68,6 +69,16 @@
     static final String LOG_TAG = "CDMA";
     static private final String LOGGABLE_TAG = "CDMA:SMS";
 
+    private final static byte TELESERVICE_IDENTIFIER                    = 0x00;
+    private final static byte SERVICE_CATEGORY                          = 0x01;
+    private final static byte ORIGINATING_ADDRESS                       = 0x02;
+    private final static byte ORIGINATING_SUB_ADDRESS                   = 0x03;
+    private final static byte DESTINATION_ADDRESS                       = 0x04;
+    private final static byte DESTINATION_SUB_ADDRESS                   = 0x05;
+    private final static byte BEARER_REPLY_OPTION                       = 0x06;
+    private final static byte CAUSE_CODES                               = 0x07;
+    private final static byte BEARER_DATA                               = 0x08;
+
     /**
      *  Status of a previously submitted SMS.
      *  This field applies to SMS Delivery Acknowledge messages. 0 indicates success;
@@ -263,6 +274,7 @@
             System.arraycopy(data, 2, pdu, 0, size);
             // the message has to be parsed before it can be displayed
             // see gsm.SmsMessage
+            msg.parsePduFromEfRecord(pdu);
             return msg;
         } catch (RuntimeException ex) {
             Log.e(LOG_TAG, "SMS PDU parsing failed: ", ex);
@@ -535,6 +547,143 @@
     }
 
     /**
+     * Decodes 3GPP2 sms stored in CSIM/RUIM cards As per 3GPP2 C.S0015-0
+     */
+    private void parsePduFromEfRecord(byte[] pdu) {
+        ByteArrayInputStream bais = new ByteArrayInputStream(pdu);
+        DataInputStream dis = new DataInputStream(bais);
+        SmsEnvelope env = new SmsEnvelope();
+        CdmaSmsAddress addr = new CdmaSmsAddress();
+        CdmaSmsSubaddress subAddr = new CdmaSmsSubaddress();
+
+        try {
+            env.messageType = dis.readByte();
+
+            while (dis.available() > 0) {
+                int parameterId = dis.readByte();
+                int parameterLen = dis.readByte();
+                byte[] parameterData = new byte[parameterLen];
+
+                switch (parameterId) {
+                    case TELESERVICE_IDENTIFIER:
+                        /*
+                         * 16 bit parameter that identifies which upper layer
+                         * service access point is sending or should receive
+                         * this message
+                         */
+                        env.teleService = dis.readUnsignedShort();
+                        Log.i(LOG_TAG, "teleservice = " + env.teleService);
+                        break;
+                    case SERVICE_CATEGORY:
+                        /*
+                         * 16 bit parameter that identifies type of service as
+                         * in 3GPP2 C.S0015-0 Table 3.4.3.2-1
+                         */
+                        env.serviceCategory = dis.readUnsignedShort();
+                        break;
+                    case ORIGINATING_ADDRESS:
+                    case DESTINATION_ADDRESS:
+                        dis.read(parameterData, 0, parameterLen);
+                        BitwiseInputStream addrBis = new BitwiseInputStream(parameterData);
+                        addr.digitMode = addrBis.read(1);
+                        addr.numberMode = addrBis.read(1);
+                        int numberType = 0;
+                        if (addr.digitMode == CdmaSmsAddress.DIGIT_MODE_8BIT_CHAR) {
+                            numberType = addrBis.read(3);
+                            addr.ton = numberType;
+
+                            if (addr.numberMode == CdmaSmsAddress.NUMBER_MODE_NOT_DATA_NETWORK)
+                                addr.numberPlan = addrBis.read(4);
+                        }
+
+                        addr.numberOfDigits = addrBis.read(8);
+
+                        byte[] data = new byte[addr.numberOfDigits];
+                        byte b = 0x00;
+
+                        if (addr.digitMode == CdmaSmsAddress.DIGIT_MODE_4BIT_DTMF) {
+                            /* As per 3GPP2 C.S0005-0 Table 2.7.1.3.2.4-4 */
+                            for (int index = 0; index < addr.numberOfDigits; index++) {
+                                b = (byte) (0xF & addrBis.read(4));
+                                // convert the value if it is 4-bit DTMF to 8
+                                // bit
+                                data[index] = convertDtmfToAscii(b);
+                            }
+                        } else if (addr.digitMode == CdmaSmsAddress.DIGIT_MODE_8BIT_CHAR) {
+                            if (addr.numberMode == CdmaSmsAddress.NUMBER_MODE_NOT_DATA_NETWORK) {
+                                for (int index = 0; index < addr.numberOfDigits; index++) {
+                                    b = (byte) (0xFF & addrBis.read(8));
+                                    data[index] = b;
+                                }
+
+                            } else if (addr.numberMode == CdmaSmsAddress.NUMBER_MODE_DATA_NETWORK) {
+                                if (numberType == 2)
+                                    Log.e(LOG_TAG, "TODO: Originating Addr is email id");
+                                else
+                                    Log.e(LOG_TAG,
+                                          "TODO: Originating Addr is data network address");
+                            } else {
+                                Log.e(LOG_TAG, "Originating Addr is of incorrect type");
+                            }
+                        } else {
+                            Log.e(LOG_TAG, "Incorrect Digit mode");
+                        }
+                        addr.origBytes = data;
+                        Log.i(LOG_TAG, "Originating Addr=" + addr.toString());
+                        break;
+                    case ORIGINATING_SUB_ADDRESS:
+                    case DESTINATION_SUB_ADDRESS:
+                        dis.read(parameterData, 0, parameterLen);
+                        BitwiseInputStream subAddrBis = new BitwiseInputStream(parameterData);
+                        subAddr.type = subAddrBis.read(3);
+                        subAddr.odd = subAddrBis.readByteArray(1)[0];
+                        int subAddrLen = subAddrBis.read(8);
+                        byte[] subdata = new byte[subAddrLen];
+                        for (int index = 0; index < subAddrLen; index++) {
+                            b = (byte) (0xFF & subAddrBis.read(4));
+                            // convert the value if it is 4-bit DTMF to 8 bit
+                            subdata[index] = convertDtmfToAscii(b);
+                        }
+                        subAddr.origBytes = subdata;
+                        break;
+                    case BEARER_REPLY_OPTION:
+                        dis.read(parameterData, 0, parameterLen);
+                        BitwiseInputStream replyOptBis = new BitwiseInputStream(parameterData);
+                        env.bearerReply = replyOptBis.read(6);
+                        break;
+                    case CAUSE_CODES:
+                        dis.read(parameterData, 0, parameterLen);
+                        BitwiseInputStream ccBis = new BitwiseInputStream(parameterData);
+                        env.replySeqNo = ccBis.readByteArray(6)[0];
+                        env.errorClass = ccBis.readByteArray(2)[0];
+                        if (env.errorClass != 0x00)
+                            env.causeCode = ccBis.readByteArray(8)[0];
+                        break;
+                    case BEARER_DATA:
+                        dis.read(parameterData, 0, parameterLen);
+                        env.bearerData = parameterData;
+                        break;
+                    default:
+                        throw new Exception("unsupported parameterId (" + parameterId + ")");
+                }
+            }
+            bais.close();
+            dis.close();
+        } catch (Exception ex) {
+            Log.e(LOG_TAG, "parsePduFromEfRecord: conversion from pdu to SmsMessage failed" + ex);
+        }
+
+        // link the filled objects to this SMS
+        originatingAddress = addr;
+        env.origAddress = addr;
+        env.origSubaddress = subAddr;
+        mEnvelope = env;
+        mPdu = pdu;
+
+        parseSms();
+    }
+
+    /**
      * Parses a SMS message from its BearerData stream. (mobile-terminated only)
      */
     protected void parseSms() {
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
index 4713c24..cd0d9e3 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
@@ -160,6 +160,7 @@
 
         /** Create the default connection */
         createDataConnection(Phone.APN_TYPE_DEFAULT);
+        broadcastMessenger();
     }
 
     @Override
diff --git a/tests/DumpRenderTree/AndroidManifest.xml b/tests/DumpRenderTree/AndroidManifest.xml
index 86b3f06..dc44b25 100644
--- a/tests/DumpRenderTree/AndroidManifest.xml
+++ b/tests/DumpRenderTree/AndroidManifest.xml
@@ -27,7 +27,7 @@
         </activity>
         <activity android:name="TestShellActivity"
           android:launchMode="singleTop"
-          android:hardwareAccelerated="false"
+          android:hardwareAccelerated="true"
           android:screenOrientation="portrait"
           android:theme="@android:style/Theme.Light"/>
         <activity android:name="ReliabilityTestActivity" android:screenOrientation="portrait"
diff --git a/tools/layoutlib/bridge/src/android/animation/PropertyValuesHolder_Delegate.java b/tools/layoutlib/bridge/src/android/animation/PropertyValuesHolder_Delegate.java
new file mode 100644
index 0000000..7d41d1c
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/animation/PropertyValuesHolder_Delegate.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.animation;
+
+import com.android.layoutlib.bridge.impl.DelegateManager;
+
+/**
+ * Delegate implementing the native methods of android.animation.PropertyValuesHolder
+ *
+ * Through the layoutlib_create tool, the original native methods of PropertyValuesHolder have been
+ * replaced by calls to methods of the same name in this delegate class.
+ *
+ * Because it's a stateless class to start with, there's no need to keep a {@link DelegateManager}
+ * around to map int to instance of the delegate.
+ *
+ * The main goal of this class' methods are to provide a native way to access setters and getters
+ * on some object. In this case we want to default to using Java reflection instead so the native
+ * methods do nothing.
+ *
+ */
+/*package*/ class PropertyValuesHolder_Delegate {
+
+    /*package*/ static int nGetIntMethod(Class<?> targetClass, String methodName) {
+        // return 0 to force PropertyValuesHolder to use Java reflection.
+        return 0;
+    }
+
+    /*package*/ static int nGetFloatMethod(Class<?> targetClass, String methodName) {
+        // return 0 to force PropertyValuesHolder to use Java reflection.
+        return 0;
+    }
+
+    /*package*/ static void nCallIntMethod(Object target, int methodID, int arg) {
+        // do nothing
+    }
+
+    /*package*/ static void nCallFloatMethod(Object target, int methodID, float arg) {
+        // do nothing
+    }
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/LayoutSceneImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/LayoutSceneImpl.java
index d58cde8..0130970 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/LayoutSceneImpl.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/LayoutSceneImpl.java
@@ -458,16 +458,10 @@
                 mCanvas.setDensity(mParams.getDensity());
             }
 
-            long preDrawTime = System.currentTimeMillis();
-
             mViewRoot.draw(mCanvas);
 
-            long drawTime = System.currentTimeMillis();
-
             mViewInfo = visit(((ViewGroup)mViewRoot).getChildAt(0), mContext);
 
-            System.out.println(String.format("rendering (ms): %03d", drawTime - preDrawTime));
-
             // success!
             return SceneStatus.SUCCESS.createResult();
         } catch (Throwable e) {
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
index 4440685..1d40d33 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
@@ -105,6 +105,7 @@
      * The list of classes on which to delegate all native methods.
      */
     private final static String[] DELEGATE_CLASS_NATIVES = new String[] {
+        "android.animation.PropertyValuesHolder",
         "android.graphics.Bitmap",
         "android.graphics.Canvas",
         "android.graphics.DashPathEffect",
diff --git a/wifi/java/android/net/wifi/WifiStateTracker.java b/wifi/java/android/net/wifi/WifiStateTracker.java
index d0231be..2aff7ec 100644
--- a/wifi/java/android/net/wifi/WifiStateTracker.java
+++ b/wifi/java/android/net/wifi/WifiStateTracker.java
@@ -170,6 +170,13 @@
     }
 
     /**
+     * @param enabled
+     */
+    public void setDataEnable(boolean enabled) {
+        android.util.Log.d(TAG, "setDataEnabled: IGNORING enabled=" + enabled);
+    }
+
+    /**
      * Check if private DNS route is set for the network
      */
     public boolean isPrivateDnsRouteSet() {