am d3a57029: am 1b0c9c95: am 81c1d8d3: Ensure install-during-restore is like install-then-restore

* commit 'd3a57029e80073aa3c7dfe1dbc8945d32968f6ae':
  Ensure install-during-restore is like install-then-restore
diff --git a/Android.mk b/Android.mk
index 954d0a9..c39f901 100644
--- a/Android.mk
+++ b/Android.mk
@@ -218,7 +218,6 @@
 	telephony/java/com/android/internal/telephony/ITelephony.aidl \
 	telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl \
 	telephony/java/com/android/internal/telephony/IWapPushManager.aidl \
-	telephony/java/com/android/internal/telephony/IExtendedNetworkService.aidl \
 	wifi/java/android/net/wifi/IWifiManager.aidl \
 	wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl \
 	voip/java/android/net/sip/ISipSession.aidl \
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 14b3681..f8ceff3 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -137,6 +137,9 @@
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/ImageProcessing_intermediates)
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/ImageProcessing2_intermediates)
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/ImageProcessing_intermediates)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/telephony/java/com/android/internal/telephony/IExtendedNetworkService.java)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/telephony/java/com/android/internal/telephony/IExtendedNetworkService.P)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/ImageProcessing_intermediates)
 # ************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
 # ************************************************
diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java
index bcb35d5..f490e79 100644
--- a/core/java/android/accounts/AccountManager.java
+++ b/core/java/android/accounts/AccountManager.java
@@ -1853,7 +1853,7 @@
      * <p>
      * The most common case is to call this with one account type, e.g.:
      * <p>
-     * <pre>  newChooseAccountsIntent(null, null, new String[]{"com.google"}, false, null,
+     * <pre>  newChooseAccountIntent(null, null, new String[]{"com.google"}, false, null,
      * null, null, null);</pre>
      * @param selectedAccount if specified, indicates that the {@link Account} is the currently
      * selected one, according to the caller's definition of selected.
diff --git a/core/java/android/app/ActionBar.java b/core/java/android/app/ActionBar.java
index 2337790..3602fc4 100644
--- a/core/java/android/app/ActionBar.java
+++ b/core/java/android/app/ActionBar.java
@@ -132,6 +132,12 @@
     public static final int DISPLAY_SHOW_CUSTOM = 0x10;
 
     /**
+     * Allow the title to wrap onto multiple lines if space is available
+     * @hide pending API approval
+     */
+    public static final int DISPLAY_TITLE_MULTIPLE_LINES = 0x20;
+
+    /**
      * Set the action bar into custom navigation mode, supplying a view
      * for custom navigation.
      *
@@ -680,6 +686,15 @@
     public Context getThemedContext() { return null; }
 
     /**
+     * Returns true if the Title field has been truncated during layout for lack
+     * of available space.
+     *
+     * @return true if the Title field has been truncated
+     * @hide pending API approval
+     */
+    public boolean isTitleTruncated() { return false; }
+
+    /**
      * Listener interface for ActionBar navigation events.
      */
     public interface OnNavigationListener {
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 67d3930..61b2067 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -1701,6 +1701,21 @@
             return true;
         }
 
+        case GET_INTENT_FOR_INTENT_SENDER_TRANSACTION: {
+            data.enforceInterface(IActivityManager.descriptor);
+            IIntentSender r = IIntentSender.Stub.asInterface(
+                data.readStrongBinder());
+            Intent intent = getIntentForIntentSender(r);
+            reply.writeNoException();
+            if (intent != null) {
+                reply.writeInt(1);
+                intent.writeToParcel(reply, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
+            } else {
+                reply.writeInt(0);
+            }
+            return true;
+        }
+
         case UPDATE_PERSISTENT_CONFIGURATION_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
             Configuration config = Configuration.CREATOR.createFromParcel(data);
@@ -3977,6 +3992,20 @@
         return res;
     }
 
+    public Intent getIntentForIntentSender(IIntentSender sender) throws RemoteException {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeInterfaceToken(IActivityManager.descriptor);
+        data.writeStrongBinder(sender.asBinder());
+        mRemote.transact(GET_INTENT_FOR_INTENT_SENDER_TRANSACTION, data, reply, 0);
+        reply.readException();
+        Intent res = reply.readInt() != 0
+                ? Intent.CREATOR.createFromParcel(reply) : null;
+        data.recycle();
+        reply.recycle();
+        return res;
+    }
+
     public void updatePersistentConfiguration(Configuration values) throws RemoteException
     {
         Parcel data = Parcel.obtain();
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 456d757..d880817 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -4421,12 +4421,14 @@
             new ArrayList<IActivityManager.ContentProviderHolder>();
 
         for (ProviderInfo cpi : providers) {
-            StringBuilder buf = new StringBuilder(128);
-            buf.append("Pub ");
-            buf.append(cpi.authority);
-            buf.append(": ");
-            buf.append(cpi.name);
-            Log.i(TAG, buf.toString());
+            if (DEBUG_PROVIDER) {
+                StringBuilder buf = new StringBuilder(128);
+                buf.append("Pub ");
+                buf.append(cpi.authority);
+                buf.append(": ");
+                buf.append(cpi.name);
+                Log.i(TAG, buf.toString());
+            }
             IActivityManager.ContentProviderHolder cph = installProvider(context, null, cpi,
                     false /*noisy*/, true /*noReleaseNeeded*/, true /*stable*/);
             if (cph != null) {
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 95b6bed..f895ccc 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -168,7 +168,7 @@
  * context object for Activity and other application components.
  */
 class ContextImpl extends Context {
-    private final static String TAG = "ApplicationContext";
+    private final static String TAG = "ContextImpl";
     private final static boolean DEBUG = false;
 
     private static final HashMap<String, SharedPreferencesImpl> sSharedPrefs =
@@ -1715,7 +1715,7 @@
     private void warnIfCallingFromSystemProcess() {
         if (Process.myUid() == Process.SYSTEM_UID) {
             Slog.w(TAG, "Calling a method in the system process without a qualified user: "
-                    + Debug.getCallers(3));
+                    + Debug.getCallers(5));
         }
     }
 
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index c5a382d..b6aeb84 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -1019,7 +1019,7 @@
     }
 
     /**
-     * Call {@link Activity#startActivity(Intent)} on the fragment's
+     * Call {@link Activity#startActivity(Intent)} from the fragment's
      * containing Activity.
      *
      * @param intent The intent to start.
@@ -1029,7 +1029,7 @@
     }
     
     /**
-     * Call {@link Activity#startActivity(Intent, Bundle)} on the fragment's
+     * Call {@link Activity#startActivity(Intent, Bundle)} from the fragment's
      * containing Activity.
      *
      * @param intent The intent to start.
@@ -1051,7 +1051,7 @@
     }
 
     /**
-     * Call {@link Activity#startActivityForResult(Intent, int)} on the fragment's
+     * Call {@link Activity#startActivityForResult(Intent, int)} from the fragment's
      * containing Activity.
      */
     public void startActivityForResult(Intent intent, int requestCode) {
@@ -1059,7 +1059,7 @@
     }
 
     /**
-     * Call {@link Activity#startActivityForResult(Intent, int, Bundle)} on the fragment's
+     * Call {@link Activity#startActivityForResult(Intent, int, Bundle)} from the fragment's
      * containing Activity.
      */
     public void startActivityForResult(Intent intent, int requestCode, Bundle options) {
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 8fc1c86..8af17a4 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -341,6 +341,8 @@
 
     public boolean isIntentSenderAnActivity(IIntentSender sender) throws RemoteException;
 
+    public Intent getIntentForIntentSender(IIntentSender sender) throws RemoteException;
+
     public void updatePersistentConfiguration(Configuration values) throws RemoteException;
 
     public long[] getProcessPss(int[] pids) throws RemoteException;
@@ -621,4 +623,5 @@
     int REQUEST_BUG_REPORT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+157;
     int INPUT_DISPATCHING_TIMED_OUT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+158;
     int CLEAR_PENDING_BACKUP_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+159;
+    int GET_INTENT_FOR_INTENT_SENDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+160;
 }
diff --git a/core/java/android/app/MediaRouteButton.java b/core/java/android/app/MediaRouteButton.java
index 3ecafc3..a1a147a 100644
--- a/core/java/android/app/MediaRouteButton.java
+++ b/core/java/android/app/MediaRouteButton.java
@@ -217,7 +217,8 @@
     void updateRemoteIndicator() {
         final RouteInfo selected = mRouter.getSelectedRoute(mRouteTypes);
         final boolean isRemote = selected != mRouter.getSystemAudioRoute();
-        final boolean isConnecting = selected.getStatusCode() == RouteInfo.STATUS_CONNECTING;
+        final boolean isConnecting = selected != null &&
+                selected.getStatusCode() == RouteInfo.STATUS_CONNECTING;
 
         boolean needsRefresh = false;
         if (mRemoteActive != isRemote) {
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 2c92d093..3f8e16c 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -322,7 +322,7 @@
     /**
      * Bit to be bitwise-ored into the {@link #flags} field that should be
      * set if the notification should be canceled when it is clicked by the
-     * user.  On tablets, the
+     * user.
 
      */
     public static final int FLAG_AUTO_CANCEL        = 0x00000010;
@@ -388,8 +388,8 @@
      * Priority is an indication of how much of the user's valuable attention should be consumed by
      * this notification. Low-priority notifications may be hidden from the user in certain
      * situations, while the user might be interrupted for a higher-priority notification. The
-     * system will make a determination about how to interpret notification priority as described in
-     * MUMBLE MUMBLE.
+     * system will make a determination about how to interpret this priority when presenting
+     * the notification.
      */
     public int priority;
 
@@ -846,7 +846,9 @@
         }
         // TODO(dsandler): defaults take precedence over local values, so reorder the branches below
         sb.append(" vibrate=");
-        if (this.vibrate != null) {
+        if ((this.defaults & DEFAULT_VIBRATE) != 0) {
+            sb.append("default");
+        } else if (this.vibrate != null) {
             int N = this.vibrate.length-1;
             sb.append("[");
             for (int i=0; i<N; i++) {
@@ -857,16 +859,14 @@
                 sb.append(this.vibrate[N]);
             }
             sb.append("]");
-        } else if ((this.defaults & DEFAULT_VIBRATE) != 0) {
-            sb.append("default");
         } else {
             sb.append("null");
         }
         sb.append(" sound=");
-        if (this.sound != null) {
-            sb.append(this.sound.toString());
-        } else if ((this.defaults & DEFAULT_SOUND) != 0) {
+        if ((this.defaults & DEFAULT_SOUND) != 0) {
             sb.append("default");
+        } else if (this.sound != null) {
+            sb.append(this.sound.toString());
         } else {
             sb.append("null");
         }
diff --git a/core/java/android/app/PendingIntent.java b/core/java/android/app/PendingIntent.java
index d36d99d..5c75aff 100644
--- a/core/java/android/app/PendingIntent.java
+++ b/core/java/android/app/PendingIntent.java
@@ -790,6 +790,20 @@
     }
 
     /**
+     * @hide
+     * Return the Intent of this PendingIntent.
+     */
+    public Intent getIntent() {
+        try {
+            return ActivityManagerNative.getDefault()
+                .getIntentForIntentSender(mTarget);
+        } catch (RemoteException e) {
+            // Should never happen.
+            return null;
+        }
+    }
+
+    /**
      * Comparison operator on two PendingIntent objects, such that true
      * is returned then they both represent the same operation from the
      * same package.  This allows you to use {@link #getActivity},
diff --git a/core/java/android/app/Presentation.java b/core/java/android/app/Presentation.java
index 16a0c57..bb45abb4 100644
--- a/core/java/android/app/Presentation.java
+++ b/core/java/android/app/Presentation.java
@@ -281,7 +281,7 @@
     private boolean isConfigurationStillValid() {
         DisplayMetrics dm = new DisplayMetrics();
         mDisplay.getMetrics(dm);
-        return dm.equals(getResources().getDisplayMetrics());
+        return dm.equalsPhysical(getResources().getDisplayMetrics());
     }
 
     private static Context createPresentationContext(
diff --git a/core/java/android/app/SearchManager.java b/core/java/android/app/SearchManager.java
index 43a163d..6382cee 100644
--- a/core/java/android/app/SearchManager.java
+++ b/core/java/android/app/SearchManager.java
@@ -858,6 +858,9 @@
      */
     public Intent getAssistIntent(Context context, int userHandle) {
         try {
+            if (mService == null) {
+                return null;
+            }
             ComponentName comp = mService.getAssistIntent(userHandle);
             if (comp == null) {
                 return null;
diff --git a/core/java/android/app/Service.java b/core/java/android/app/Service.java
index 02cf3aa..4fbca73 100644
--- a/core/java/android/app/Service.java
+++ b/core/java/android/app/Service.java
@@ -666,7 +666,9 @@
     
     /**
      * Print the Service's state into the given stream.  This gets invoked if
-     * you run "adb shell dumpsys activity service &lt;yourservicename&gt;".
+     * you run "adb shell dumpsys activity service &lt;yourservicename&gt;"
+     * (note that for this command to work, the service must be running, and
+     * you must specify a fully-qualified service name).
      * This is distinct from "dumpsys &lt;servicename&gt;", which only works for
      * named system services and which invokes the {@link IBinder#dump} method
      * on the {@link IBinder} interface registered with ServiceManager.
diff --git a/core/java/android/appwidget/AppWidgetHost.java b/core/java/android/appwidget/AppWidgetHost.java
index cb61a71..fa3bf4d 100644
--- a/core/java/android/appwidget/AppWidgetHost.java
+++ b/core/java/android/appwidget/AppWidgetHost.java
@@ -60,6 +60,7 @@
         public void updateAppWidget(int appWidgetId, RemoteViews views) {
             if (isLocalBinder() && views != null) {
                 views = views.clone();
+                views.setUser(mUser);
             }
             Message msg = mHandler.obtainMessage(HANDLE_UPDATE);
             msg.arg1 = appWidgetId;
@@ -123,6 +124,8 @@
     Callbacks mCallbacks = new Callbacks();
     final HashMap<Integer,AppWidgetHostView> mViews = new HashMap<Integer, AppWidgetHostView>();
     private OnClickHandler mOnClickHandler;
+    // Optionally set by lockscreen
+    private UserHandle mUser;
 
     public AppWidgetHost(Context context, int hostId) {
         this(context, hostId, null, context.getMainLooper());
@@ -137,9 +140,15 @@
         mOnClickHandler = handler;
         mHandler = new UpdateHandler(looper);
         mDisplayMetrics = context.getResources().getDisplayMetrics();
+        mUser = Process.myUserHandle();
         bindService();
     }
 
+    /** @hide */
+    public void setUserId(int userId) {
+        mUser = new UserHandle(userId);
+    }
+
     private static void bindService() {
         synchronized (sServiceLock) {
             if (sService == null) {
@@ -154,6 +163,15 @@
      * becomes visible, i.e. from onStart() in your Activity.
      */
     public void startListening() {
+        startListeningAsUser(UserHandle.myUserId());
+    }
+
+    /**
+     * Start receiving onAppWidgetChanged calls for your AppWidgets.  Call this when your activity
+     * becomes visible, i.e. from onStart() in your Activity.
+     * @hide
+     */
+    public void startListeningAsUser(int userId) {
         int[] updatedIds;
         ArrayList<RemoteViews> updatedViews = new ArrayList<RemoteViews>();
 
@@ -161,7 +179,8 @@
             if (mPackageName == null) {
                 mPackageName = mContext.getPackageName();
             }
-            updatedIds = sService.startListening(mCallbacks, mPackageName, mHostId, updatedViews);
+            updatedIds = sService.startListeningAsUser(
+                    mCallbacks, mPackageName, mHostId, updatedViews, userId);
         }
         catch (RemoteException e) {
             throw new RuntimeException("system server dead?", e);
@@ -169,6 +188,9 @@
 
         final int N = updatedIds.length;
         for (int i=0; i<N; i++) {
+            if (updatedViews.get(i) != null) {
+                updatedViews.get(i).setUser(new UserHandle(userId));
+            }
             updateAppWidgetView(updatedIds[i], updatedViews.get(i));
         }
     }
@@ -179,7 +201,7 @@
      */
     public void stopListening() {
         try {
-            sService.stopListening(mHostId);
+            sService.stopListeningAsUser(mHostId, UserHandle.myUserId());
         }
         catch (RemoteException e) {
             throw new RuntimeException("system server dead?", e);
@@ -187,6 +209,22 @@
     }
 
     /**
+     * Stop receiving onAppWidgetChanged calls for your AppWidgets.  Call this when your activity is
+     * no longer visible, i.e. from onStop() in your Activity.
+     * @hide
+     */
+    public void stopListeningAsUser(int userId) {
+        try {
+            sService.stopListeningAsUser(mHostId, userId);
+        }
+        catch (RemoteException e) {
+            throw new RuntimeException("system server dead?", e);
+        }
+        // Also clear the views
+        clearViews();
+    }
+
+    /**
      * Get a appWidgetId for a host in the calling process.
      *
      * @return a appWidgetId
@@ -224,6 +262,22 @@
         }
     }
 
+    /**
+     * Gets a list of all the appWidgetIds that are bound to the current host
+     *
+     * @hide
+     */
+    public int[] getAppWidgetIds() {
+        try {
+            if (sService == null) {
+                bindService();
+            }
+            return sService.getAppWidgetIdsForHost(mHostId);
+        } catch (RemoteException e) {
+            throw new RuntimeException("system server dead?", e);
+        }
+    }
+
     private static void checkCallerIsSystem() {
         int uid = Process.myUid();
         if (UserHandle.getAppId(uid) == Process.SYSTEM_UID || uid == 0) {
@@ -308,6 +362,7 @@
     public final AppWidgetHostView createView(Context context, int appWidgetId,
             AppWidgetProviderInfo appWidget) {
         AppWidgetHostView view = onCreateView(context, appWidgetId, appWidget);
+        view.setUserId(mUser.getIdentifier());
         view.setOnClickHandler(mOnClickHandler);
         view.setAppWidget(appWidgetId, appWidget);
         synchronized (mViews) {
@@ -316,6 +371,9 @@
         RemoteViews views;
         try {
             views = sService.getAppWidgetViews(appWidgetId);
+            if (views != null) {
+                views.setUser(mUser);
+            }
         } catch (RemoteException e) {
             throw new RuntimeException("system server dead?", e);
         }
diff --git a/core/java/android/appwidget/AppWidgetHostView.java b/core/java/android/appwidget/AppWidgetHostView.java
index 52771ee..700bba8 100644
--- a/core/java/android/appwidget/AppWidgetHostView.java
+++ b/core/java/android/appwidget/AppWidgetHostView.java
@@ -31,7 +31,9 @@
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.os.Process;
 import android.os.SystemClock;
+import android.os.UserHandle;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.util.SparseArray;
@@ -85,6 +87,7 @@
     Bitmap mOld;
     Paint mOldPaint = new Paint();
     private OnClickHandler mOnClickHandler;
+    private UserHandle mUser;
 
     /**
      * Create a host view.  Uses default fade animations.
@@ -112,12 +115,17 @@
     public AppWidgetHostView(Context context, int animationIn, int animationOut) {
         super(context);
         mContext = context;
-
+        mUser = Process.myUserHandle();
         // We want to segregate the view ids within AppWidgets to prevent
         // problems when those ids collide with view ids in the AppWidgetHost.
         setIsRootNamespace(true);
     }
 
+    /** @hide */
+    public void setUserId(int userId) {
+        mUser = new UserHandle(userId);
+    }
+
     /**
      * Pass the given handler to RemoteViews when updating this widget. Unless this
      * is done immediatly after construction, a call to {@link #updateAppWidget(RemoteViews)}
@@ -465,7 +473,8 @@
 
         try {
             // Return if cloned successfully, otherwise default
-            return mContext.createPackageContext(packageName, Context.CONTEXT_RESTRICTED);
+            return mContext.createPackageContextAsUser(packageName, Context.CONTEXT_RESTRICTED,
+                    mUser);
         } catch (NameNotFoundException e) {
             Log.e(TAG, "Package name " + packageName + " not found");
             return mContext;
@@ -539,8 +548,8 @@
 
         try {
             if (mInfo != null) {
-                Context theirContext = mContext.createPackageContext(
-                        mInfo.provider.getPackageName(), Context.CONTEXT_RESTRICTED);
+                Context theirContext = mContext.createPackageContextAsUser(
+                        mInfo.provider.getPackageName(), Context.CONTEXT_RESTRICTED, mUser);
                 mRemoteContext = theirContext;
                 LayoutInflater inflater = (LayoutInflater)
                         theirContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
diff --git a/core/java/android/appwidget/AppWidgetManager.java b/core/java/android/appwidget/AppWidgetManager.java
index 285bc0ce..6b1c3e2 100644
--- a/core/java/android/appwidget/AppWidgetManager.java
+++ b/core/java/android/appwidget/AppWidgetManager.java
@@ -23,6 +23,7 @@
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.UserHandle;
 import android.util.DisplayMetrics;
 import android.util.TypedValue;
 import android.widget.RemoteViews;
@@ -544,8 +545,19 @@
      * Return a list of the AppWidget providers that are currently installed.
      */
     public List<AppWidgetProviderInfo> getInstalledProviders() {
+        return getInstalledProviders(AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN);
+    }
+
+    /**
+     * Return a list of the AppWidget providers that are currently installed.
+     *
+     * @param categoryFilter Will only return providers which register as any of the specified
+     *        specified categories. See {@link AppWidgetProviderInfo#widgetCategory}.
+     * @hide
+     */
+    public List<AppWidgetProviderInfo> getInstalledProviders(int categoryFilter) {
         try {
-            List<AppWidgetProviderInfo> providers = sService.getInstalledProviders();
+            List<AppWidgetProviderInfo> providers = sService.getInstalledProviders(categoryFilter);
             for (AppWidgetProviderInfo info : providers) {
                 // Converting complex to dp.
                 info.minWidth =
@@ -738,11 +750,14 @@
      * @param intent        The intent of the service which will be providing the data to the
      *                      RemoteViewsAdapter.
      * @param connection    The callback interface to be notified when a connection is made or lost.
+     * @param userHandle    The user to bind to.
      * @hide
      */
-    public void bindRemoteViewsService(int appWidgetId, Intent intent, IBinder connection) {
+    public void bindRemoteViewsService(int appWidgetId, Intent intent, IBinder connection,
+            UserHandle userHandle) {
         try {
-            sService.bindRemoteViewsService(appWidgetId, intent, connection);
+            sService.bindRemoteViewsService(appWidgetId, intent, connection,
+                    userHandle.getIdentifier());
         }
         catch (RemoteException e) {
             throw new RuntimeException("system server dead?", e);
@@ -758,11 +773,12 @@
      * @param appWidgetId   The AppWidget instance for which to bind the RemoteViewsService.
      * @param intent        The intent of the service which will be providing the data to the
      *                      RemoteViewsAdapter.
+     * @param userHandle    The user to unbind from.
      * @hide
      */
-    public void unbindRemoteViewsService(int appWidgetId, Intent intent) {
+    public void unbindRemoteViewsService(int appWidgetId, Intent intent, UserHandle userHandle) {
         try {
-            sService.unbindRemoteViewsService(appWidgetId, intent);
+            sService.unbindRemoteViewsService(appWidgetId, intent, userHandle.getIdentifier());
         }
         catch (RemoteException e) {
             throw new RuntimeException("system server dead?", e);
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index f817fb4..6367e16 100755
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -1212,7 +1212,7 @@
     final private IBluetoothManagerCallback mManagerCallback =
         new IBluetoothManagerCallback.Stub() {
             public void onBluetoothServiceUp(IBluetooth bluetoothService) {
-                if (DBG) Log.d(TAG, "onBluetoothServiceUp: " + bluetoothService);
+                if (VDBG) Log.d(TAG, "onBluetoothServiceUp: " + bluetoothService);
                 synchronized (mManagerCallback) {
                     mService = bluetoothService;
                     for (IBluetoothManagerCallback cb : mProxyServiceStateCallbacks ){
@@ -1228,7 +1228,7 @@
             }
 
             public void onBluetoothServiceDown() {
-                if (DBG) Log.d(TAG, "onBluetoothServiceDown: " + mService);
+                if (VDBG) Log.d(TAG, "onBluetoothServiceDown: " + mService);
                 synchronized (mManagerCallback) {
                     mService = null;
                     for (IBluetoothManagerCallback cb : mProxyServiceStateCallbacks ){
diff --git a/core/java/android/bluetooth/BluetoothSocket.java b/core/java/android/bluetooth/BluetoothSocket.java
index 26bde19..8029a1a 100644
--- a/core/java/android/bluetooth/BluetoothSocket.java
+++ b/core/java/android/bluetooth/BluetoothSocket.java
@@ -300,7 +300,6 @@
         if (mDevice == null) throw new IOException("Connect is called on null device");
 
         try {
-            // TODO(BT) derive flag from auth and encrypt
             if (mSocketState == SocketState.CLOSED) throw new IOException("socket closed");
             IBluetooth bluetoothProxy = BluetoothAdapter.getDefaultAdapter().getBluetoothService(null);
             if (bluetoothProxy == null) throw new IOException("Bluetooth is off");
@@ -349,7 +348,6 @@
                     mUuid, mPort, getSecurityFlags());
         } catch (RemoteException e) {
             Log.e(TAG, Log.getStackTraceString(new Throwable()));
-            // TODO(BT) right error code?
             return -1;
         }
 
@@ -388,8 +386,13 @@
     /*package*/ BluetoothSocket accept(int timeout) throws IOException {
         BluetoothSocket acceptedSocket;
         if (mSocketState != SocketState.LISTENING) throw new IOException("bt socket is not in listen state");
-        // TODO(BT) wait on an incoming connection
+        if(timeout > 0) {
+            Log.d(TAG, "accept() set timeout (ms):" + timeout);
+           mSocket.setSoTimeout(timeout);
+        }
         String RemoteAddr = waitSocketSignal(mSocketIS);
+        if(timeout > 0)
+            mSocket.setSoTimeout(0);
         synchronized(this)
         {
             if (mSocketState != SocketState.LISTENING)
@@ -397,8 +400,6 @@
             acceptedSocket = acceptSocket(RemoteAddr);
             //quick drop the reference of the file handle
         }
-        // TODO(BT) rfcomm socket only supports one connection, return this?
-        // return this;
         return acceptedSocket;
     }
 
@@ -428,7 +429,7 @@
 
     @Override
     public void close() throws IOException {
-        Log.d(TAG, "close() in, this: " + this + ", channel: " + mPort + ", state: " + mSocketState);
+        if (VDBG) Log.d(TAG, "close() in, this: " + this + ", channel: " + mPort + ", state: " + mSocketState);
         if(mSocketState == SocketState.CLOSED)
             return;
         else
@@ -451,7 +452,6 @@
                     mPfd.detachFd();
            }
         }
-        // TODO(BT) unbind proxy,
     }
 
     /*package */ void removeChannel() {
@@ -471,6 +471,8 @@
         ByteBuffer bb = ByteBuffer.wrap(sig);
         bb.order(ByteOrder.nativeOrder());
         int size = bb.getShort();
+        if(size != SOCK_SIGNAL_SIZE)
+            throw new IOException("Connection failure, wrong signal size: " + size);
         byte [] addr = new byte[6];
         bb.get(addr);
         int channel = bb.getInt();
@@ -487,7 +489,7 @@
         while(left > 0) {
             int ret = is.read(b, b.length - left, left);
             if(ret <= 0)
-                 throw new IOException("read failed, socket might closed, read ret: " + ret);
+                 throw new IOException("read failed, socket might closed or timeout, read ret: " + ret);
             left -= ret;
             if(left != 0)
                 Log.w(TAG, "readAll() looping, read partial size: " + (b.length - left) +
diff --git a/core/java/android/content/SyncManager.java b/core/java/android/content/SyncManager.java
index 977b461..e4b4b97 100644
--- a/core/java/android/content/SyncManager.java
+++ b/core/java/android/content/SyncManager.java
@@ -58,6 +58,7 @@
 import android.util.Slog;
 
 import com.android.internal.R;
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.IndentingPrintWriter;
 import com.google.android.collect.Lists;
 import com.google.android.collect.Maps;
@@ -155,7 +156,7 @@
 
     private SyncStorageEngine mSyncStorageEngine;
 
-    // @GuardedBy("mSyncQueue")
+    @GuardedBy("mSyncQueue")
     private final SyncQueue mSyncQueue;
 
     protected final ArrayList<ActiveSyncContext> mActiveSyncContexts = Lists.newArrayList();
diff --git a/core/java/android/content/SyncStorageEngine.java b/core/java/android/content/SyncStorageEngine.java
index 10e7bff..1ecab09 100644
--- a/core/java/android/content/SyncStorageEngine.java
+++ b/core/java/android/content/SyncStorageEngine.java
@@ -16,6 +16,7 @@
 
 package android.content;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.FastXmlSerializer;
 
@@ -63,6 +64,7 @@
 public class SyncStorageEngine extends Handler {
 
     private static final String TAG = "SyncManager";
+    private static final boolean DEBUG = false;
     private static final boolean DEBUG_FILE = false;
 
     private static final String XML_ATTR_NEXT_AUTHORITY_ID = "nextAuthorityId";
@@ -74,7 +76,7 @@
 
     private static final long DEFAULT_POLL_FREQUENCY_SECONDS = 60 * 60 * 24; // One day
 
-    // @VisibleForTesting
+    @VisibleForTesting
     static final long MILLIS_IN_4WEEKS = 1000L * 60 * 60 * 24 * 7 * 4;
 
     /** Enum value for a sync start event. */
@@ -442,7 +444,7 @@
             mChangeListeners.finishBroadcast();
         }
 
-        if (Log.isLoggable(TAG, Log.VERBOSE)) {
+        if (DEBUG) {
             Log.v(TAG, "reportChange " + which + " to: " + reports);
         }
 
@@ -483,13 +485,17 @@
 
     public void setSyncAutomatically(Account account, int userId, String providerName,
             boolean sync) {
-        Log.d(TAG, "setSyncAutomatically: " + /* account + */" provider " + providerName
-                + ", user " + userId + " -> " + sync);
+        if (DEBUG) {
+            Log.d(TAG, "setSyncAutomatically: " + /* account + */" provider " + providerName
+                    + ", user " + userId + " -> " + sync);
+        }
         synchronized (mAuthorities) {
             AuthorityInfo authority = getOrCreateAuthorityLocked(account, userId, providerName, -1,
                     false);
             if (authority.enabled == sync) {
-                Log.d(TAG, "setSyncAutomatically: already set to " + sync + ", doing nothing");
+                if (DEBUG) {
+                    Log.d(TAG, "setSyncAutomatically: already set to " + sync + ", doing nothing");
+                }
                 return;
             }
             authority.enabled = sync;
@@ -531,13 +537,17 @@
         } else if (syncable < -1) {
             syncable = -1;
         }
-        Log.d(TAG, "setIsSyncable: " + account + ", provider " + providerName
-                + ", user " + userId + " -> " + syncable);
+        if (DEBUG) {
+            Log.d(TAG, "setIsSyncable: " + account + ", provider " + providerName
+                    + ", user " + userId + " -> " + syncable);
+        }
         synchronized (mAuthorities) {
             AuthorityInfo authority = getOrCreateAuthorityLocked(account, userId, providerName, -1,
                     false);
             if (authority.syncable == syncable) {
-                Log.d(TAG, "setIsSyncable: already set to " + syncable + ", doing nothing");
+                if (DEBUG) {
+                    Log.d(TAG, "setIsSyncable: already set to " + syncable + ", doing nothing");
+                }
                 return;
             }
             authority.syncable = syncable;
@@ -563,7 +573,7 @@
 
     public void setBackoff(Account account, int userId, String providerName,
             long nextSyncTime, long nextDelay) {
-        if (Log.isLoggable(TAG, Log.VERBOSE)) {
+        if (DEBUG) {
             Log.v(TAG, "setBackoff: " + account + ", provider " + providerName
                     + ", user " + userId
                     + " -> nextSyncTime " + nextSyncTime + ", nextDelay " + nextDelay);
@@ -614,7 +624,7 @@
                     for (AuthorityInfo authorityInfo : accountInfo.authorities.values()) {
                         if (authorityInfo.backoffTime != NOT_IN_BACKOFF_MODE
                                 || authorityInfo.backoffDelay != NOT_IN_BACKOFF_MODE) {
-                            if (Log.isLoggable(TAG, Log.VERBOSE)) {
+                            if (DEBUG) {
                                 Log.v(TAG, "clearAllBackoffs:"
                                         + " authority:" + authorityInfo.authority
                                         + " account:" + accountInfo.accountAndUser.account.name
@@ -640,7 +650,7 @@
 
     public void setDelayUntilTime(Account account, int userId, String providerName,
             long delayUntil) {
-        if (Log.isLoggable(TAG, Log.VERBOSE)) {
+        if (DEBUG) {
             Log.v(TAG, "setDelayUntil: " + account + ", provider " + providerName
                     + ", user " + userId + " -> delayUntil " + delayUntil);
         }
@@ -676,7 +686,7 @@
         if (extras == null) {
             extras = new Bundle();
         }
-        if (Log.isLoggable(TAG, Log.VERBOSE)) {
+        if (DEBUG) {
             Log.v(TAG, "addOrRemovePeriodicSync: " + account + ", user " + userId
                     + ", provider " + providerName
                     + " -> period " + period + ", extras " + extras);
@@ -832,7 +842,7 @@
 
     public PendingOperation insertIntoPending(PendingOperation op) {
         synchronized (mAuthorities) {
-            if (Log.isLoggable(TAG, Log.VERBOSE)) {
+            if (DEBUG) {
                 Log.v(TAG, "insertIntoPending: account=" + op.account
                         + " user=" + op.userId
                         + " auth=" + op.authority
@@ -864,7 +874,7 @@
     public boolean deleteFromPending(PendingOperation op) {
         boolean res = false;
         synchronized (mAuthorities) {
-            if (Log.isLoggable(TAG, Log.VERBOSE)) {
+            if (DEBUG) {
                 Log.v(TAG, "deleteFromPending: account=" + op.account
                     + " user=" + op.userId
                     + " auth=" + op.authority
@@ -883,7 +893,7 @@
                 AuthorityInfo authority = getAuthorityLocked(op.account, op.userId, op.authority,
                         "deleteFromPending");
                 if (authority != null) {
-                    if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "removing - " + authority);
+                    if (DEBUG) Log.v(TAG, "removing - " + authority);
                     final int N = mPendingOperations.size();
                     boolean morePending = false;
                     for (int i=0; i<N; i++) {
@@ -897,7 +907,7 @@
                     }
 
                     if (!morePending) {
-                        if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "no more pending!");
+                        if (DEBUG) Log.v(TAG, "no more pending!");
                         SyncStatusInfo status = getOrCreateSyncStatusLocked(authority.ident);
                         status.pending = false;
                     }
@@ -937,7 +947,7 @@
      */
     public void doDatabaseCleanup(Account[] accounts, int userId) {
         synchronized (mAuthorities) {
-            if (Log.isLoggable(TAG, Log.VERBOSE)) Log.w(TAG, "Updating for new accounts...");
+            if (DEBUG) Log.v(TAG, "Updating for new accounts...");
             SparseArray<AuthorityInfo> removing = new SparseArray<AuthorityInfo>();
             Iterator<AccountInfo> accIt = mAccounts.values().iterator();
             while (accIt.hasNext()) {
@@ -945,8 +955,8 @@
                 if (!ArrayUtils.contains(accounts, acc.accountAndUser.account)
                         && acc.accountAndUser.userId == userId) {
                     // This account no longer exists...
-                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                        Log.w(TAG, "Account removed: " + acc.accountAndUser);
+                    if (DEBUG) {
+                        Log.v(TAG, "Account removed: " + acc.accountAndUser);
                     }
                     for (AuthorityInfo auth : acc.authorities.values()) {
                         removing.put(auth.ident, auth);
@@ -992,7 +1002,7 @@
     public SyncInfo addActiveSync(SyncManager.ActiveSyncContext activeSyncContext) {
         final SyncInfo syncInfo;
         synchronized (mAuthorities) {
-            if (Log.isLoggable(TAG, Log.VERBOSE)) {
+            if (DEBUG) {
                 Log.v(TAG, "setActiveSync: account="
                     + activeSyncContext.mSyncOperation.account
                     + " auth=" + activeSyncContext.mSyncOperation.authority
@@ -1020,7 +1030,7 @@
      */
     public void removeActiveSync(SyncInfo syncInfo, int userId) {
         synchronized (mAuthorities) {
-            if (Log.isLoggable(TAG, Log.VERBOSE)) {
+            if (DEBUG) {
                 Log.v(TAG, "removeActiveSync: account=" + syncInfo.account
                         + " user=" + userId
                         + " auth=" + syncInfo.authority);
@@ -1045,7 +1055,7 @@
                                      long now, int source, boolean initialization) {
         long id;
         synchronized (mAuthorities) {
-            if (Log.isLoggable(TAG, Log.VERBOSE)) {
+            if (DEBUG) {
                 Log.v(TAG, "insertStartSyncEvent: account=" + accountName + "user=" + userId
                     + " auth=" + authorityName + " source=" + source);
             }
@@ -1067,7 +1077,7 @@
                 mSyncHistory.remove(mSyncHistory.size()-1);
             }
             id = item.historyId;
-            if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "returning historyId " + id);
+            if (DEBUG) Log.v(TAG, "returning historyId " + id);
         }
 
         reportChange(ContentResolver.SYNC_OBSERVER_TYPE_STATUS);
@@ -1095,7 +1105,7 @@
     public void stopSyncEvent(long historyId, long elapsedTime, String resultMessage,
             long downstreamActivity, long upstreamActivity) {
         synchronized (mAuthorities) {
-            if (Log.isLoggable(TAG, Log.VERBOSE)) {
+            if (DEBUG) {
                 Log.v(TAG, "stopSyncEvent: historyId=" + historyId);
             }
             SyncHistoryItem item = null;
@@ -1357,7 +1367,7 @@
         AccountInfo accountInfo = mAccounts.get(au);
         if (accountInfo == null) {
             if (tag != null) {
-                if (Log.isLoggable(TAG, Log.VERBOSE)) {
+                if (DEBUG) {
                     Log.v(TAG, tag + ": unknown account " + au);
                 }
             }
@@ -1366,7 +1376,7 @@
         AuthorityInfo authority = accountInfo.authorities.get(authorityName);
         if (authority == null) {
             if (tag != null) {
-                if (Log.isLoggable(TAG, Log.VERBOSE)) {
+                if (DEBUG) {
                     Log.v(TAG, tag + ": unknown authority " + authorityName);
                 }
             }
@@ -1391,7 +1401,7 @@
                 mNextAuthorityId++;
                 doWrite = true;
             }
-            if (Log.isLoggable(TAG, Log.VERBOSE)) {
+            if (DEBUG) {
                 Log.v(TAG, "created a new AuthorityInfo for " + accountName
                         + ", user " + userId
                         + ", provider " + authorityName);
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index b0ae5da..b9e432c 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -378,6 +378,7 @@
     VerifierDeviceIdentity getVerifierDeviceIdentity();
 
     boolean isFirstBoot();
+    boolean isOnlyCoreApps();
 
     void setPermissionEnforced(String permission, boolean enforced);
     boolean isPermissionEnforced(String permission);
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 8ba1988..2c31ea0 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -45,7 +45,7 @@
 
     /**
      * This exception is thrown when a given package, application, or component
-     * name can not be found.
+     * name cannot be found.
      */
     public static class NameNotFoundException extends AndroidException {
         public NameNotFoundException() {
@@ -259,7 +259,7 @@
      * user has explicitly disabled the application, regardless of what it has
      * specified in its manifest.  Because this is due to the user's request,
      * they may re-enable it if desired through the appropriate system UI.  This
-     * option currently <strong>can not</strong> be used with
+     * option currently <strong>cannot</strong> be used with
      * {@link #setComponentEnabledSetting(ComponentName, int, int)}.
      */
     public static final int COMPONENT_ENABLED_STATE_DISABLED_USER = 3;
@@ -1210,9 +1210,9 @@
      *         package. If flag GET_UNINSTALLED_PACKAGES is set and if the
      *         package is not found in the list of installed applications, the
      *         package information is retrieved from the list of uninstalled
-     *         applications(which includes installed applications as well as
-     *         applications with data directory ie applications which had been
-     *         deleted with DONT_DELTE_DATA flag set).
+     *         applications (which includes installed applications as well as
+     *         applications with data directory i.e. applications which had been
+     *         deleted with {@code DONT_DELETE_DATA} flag set).
      * @see #GET_ACTIVITIES
      * @see #GET_GIDS
      * @see #GET_CONFIGURATIONS
@@ -1253,7 +1253,7 @@
      * null if neither are found.
      *
      * <p>Throws {@link NameNotFoundException} if a package with the given
-     * name can not be found on the system.
+     * name cannot be found on the system.
      *
      * @param packageName The name of the package to inspect.
      *
@@ -1268,7 +1268,7 @@
      * assigned to a package.
      *
      * <p>Throws {@link NameNotFoundException} if a package with the given
-     * name can not be found on the system.
+     * name cannot be found on the system.
      *
      * @param packageName The full name (i.e. com.google.apps.contacts) of the
      *                    desired package.
@@ -1283,7 +1283,7 @@
      * Retrieve all of the information we know about a particular permission.
      *
      * <p>Throws {@link NameNotFoundException} if a permission with the given
-     * name can not be found on the system.
+     * name cannot be found on the system.
      *
      * @param name The fully qualified name (i.e. com.google.permission.LOGIN)
      *             of the permission you are interested in.
@@ -1319,7 +1319,7 @@
      * permissions.
      *
      * <p>Throws {@link NameNotFoundException} if a permission group with the given
-     * name can not be found on the system.
+     * name cannot be found on the system.
      *
      * @param name The fully qualified name (i.e. com.google.permission_group.APPS)
      *             of the permission you are interested in.
@@ -1348,7 +1348,7 @@
      * package/application.
      *
      * <p>Throws {@link NameNotFoundException} if an application with the given
-     * package name can not be found on the system.
+     * package name cannot be found on the system.
      *
      * @param packageName The full name (i.e. com.google.apps.contacts) of an
      *                    application.
@@ -1364,7 +1364,7 @@
      *         list of uninstalled applications(which includes
      *         installed applications as well as applications
      *         with data directory ie applications which had been
-     *         deleted with DONT_DELTE_DATA flag set).
+     *         deleted with {@code DONT_DELETE_DATA} flag set).
      *
      * @see #GET_META_DATA
      * @see #GET_SHARED_LIBRARY_FILES
@@ -1378,7 +1378,7 @@
      * class.
      *
      * <p>Throws {@link NameNotFoundException} if an activity with the given
-     * class name can not be found on the system.
+     * class name cannot be found on the system.
      *
      * @param component The full component name (i.e.
      * com.google.apps.contacts/com.google.apps.contacts.ContactsList) of an Activity
@@ -1401,7 +1401,7 @@
      * class.
      *
      * <p>Throws {@link NameNotFoundException} if a receiver with the given
-     * class name can not be found on the system.
+     * class name cannot be found on the system.
      *
      * @param component The full component name (i.e.
      * com.google.apps.calendar/com.google.apps.calendar.CalendarAlarm) of a Receiver
@@ -1424,7 +1424,7 @@
      * class.
      *
      * <p>Throws {@link NameNotFoundException} if a service with the given
-     * class name can not be found on the system.
+     * class name cannot be found on the system.
      *
      * @param component The full component name (i.e.
      * com.google.apps.media/com.google.apps.media.BackgroundPlayback) of a Service
@@ -1446,7 +1446,7 @@
      * provider class.
      *
      * <p>Throws {@link NameNotFoundException} if a provider with the given
-     * class name can not be found on the system.
+     * class name cannot be found on the system.
      *
      * @param component The full component name (i.e.
      * com.google.providers.media/com.google.providers.media.MediaProvider) of a
@@ -1483,7 +1483,7 @@
      *         installed on the device.  In the unlikely case of there being no
      *         installed packages, an empty list is returned.
      *         If flag GET_UNINSTALLED_PACKAGES is set, a list of all
-     *         applications including those deleted with DONT_DELETE_DATA
+     *         applications including those deleted with {@code DONT_DELETE_DATA}
      *         (partially installed apps with data directory) will be returned.
      *
      * @see #GET_ACTIVITIES
@@ -1521,7 +1521,7 @@
      *         installed on the device.  In the unlikely case of there being no
      *         installed packages, an empty list is returned.
      *         If flag GET_UNINSTALLED_PACKAGES is set, a list of all
-     *         applications including those deleted with DONT_DELETE_DATA
+     *         applications including those deleted with {@code DONT_DELETE_DATA}
      *         (partially installed apps with data directory) will be returned.
      *
      * @see #GET_ACTIVITIES
@@ -1726,7 +1726,7 @@
     /**
      * Return a List of all application packages that are installed on the
      * device. If flag GET_UNINSTALLED_PACKAGES has been set, a list of all
-     * applications including those deleted with DONT_DELETE_DATA(partially
+     * applications including those deleted with {@code DONT_DELETE_DATA} (partially
      * installed apps with data directory) will be returned.
      *
      * @param flags Additional option flags. Use any combination of
@@ -1737,7 +1737,7 @@
      *         is installed on the device.  In the unlikely case of there being
      *         no installed applications, an empty list is returned.
      *         If flag GET_UNINSTALLED_PACKAGES is set, a list of all
-     *         applications including those deleted with DONT_DELETE_DATA
+     *         applications including those deleted with {@code DONT_DELETE_DATA}
      *         (partially installed apps with data directory) will be returned.
      *
      * @see #GET_META_DATA
@@ -2043,7 +2043,7 @@
      * instrumentation class.
      *
      * <p>Throws {@link NameNotFoundException} if instrumentation with the
-     * given class name can not be found on the system.
+     * given class name cannot be found on the system.
      *
      * @param className The full name (i.e.
      *                  com.google.apps.contacts.InstrumentList) of an
@@ -2080,8 +2080,8 @@
      * icon.
      *
      * @param packageName The name of the package that this icon is coming from.
-     * Can not be null.
-     * @param resid The resource identifier of the desired image.  Can not be 0.
+     * Cannot be null.
+     * @param resid The resource identifier of the desired image.  Cannot be 0.
      * @param appInfo Overall information about <var>packageName</var>.  This
      * may be null, in which case the application information will be retrieved
      * for you if needed; if you already have this information around, it can
@@ -2097,7 +2097,7 @@
      * Retrieve the icon associated with an activity.  Given the full name of
      * an activity, retrieves the information about it and calls
      * {@link ComponentInfo#loadIcon ComponentInfo.loadIcon()} to return its icon.
-     * If the activity can not be found, NameNotFoundException is thrown.
+     * If the activity cannot be found, NameNotFoundException is thrown.
      *
      * @param activityName Name of the activity whose icon is to be retrieved.
      *
@@ -2116,7 +2116,7 @@
      * set, this simply returns the result of
      * getActivityIcon(intent.getClassName()).  Otherwise it resolves the intent's
      * component and returns the icon associated with the resolved component.
-     * If intent.getClassName() can not be found or the Intent can not be resolved
+     * If intent.getClassName() cannot be found or the Intent cannot be resolved
      * to a component, NameNotFoundException is thrown.
      *
      * @param intent The intent for which you would like to retrieve an icon.
@@ -2155,7 +2155,7 @@
     /**
      * Retrieve the icon associated with an application.  Given the name of the
      * application's package, retrieves the information about it and calls
-     * getApplicationIcon() to return its icon. If the application can not be
+     * getApplicationIcon() to return its icon. If the application cannot be
      * found, NameNotFoundException is thrown.
      *
      * @param packageName Name of the package whose application icon is to be
@@ -2175,7 +2175,7 @@
      * Retrieve the logo associated with an activity.  Given the full name of
      * an activity, retrieves the information about it and calls
      * {@link ComponentInfo#loadLogo ComponentInfo.loadLogo()} to return its logo.
-     * If the activity can not be found, NameNotFoundException is thrown.
+     * If the activity cannot be found, NameNotFoundException is thrown.
      *
      * @param activityName Name of the activity whose logo is to be retrieved.
      *
@@ -2195,7 +2195,7 @@
      * set, this simply returns the result of
      * getActivityLogo(intent.getClassName()).  Otherwise it resolves the intent's
      * component and returns the logo associated with the resolved component.
-     * If intent.getClassName() can not be found or the Intent can not be resolved
+     * If intent.getClassName() cannot be found or the Intent cannot be resolved
      * to a component, NameNotFoundException is thrown.
      *
      * @param intent The intent for which you would like to retrieve a logo.
@@ -2227,7 +2227,7 @@
     /**
      * Retrieve the logo associated with an application.  Given the name of the
      * application's package, retrieves the information about it and calls
-     * getApplicationLogo() to return its logo. If the application can not be
+     * getApplicationLogo() to return its logo. If the application cannot be
      * found, NameNotFoundException is thrown.
      *
      * @param packageName Name of the package whose application logo is to be
@@ -2251,8 +2251,8 @@
      * labels and other text.
      *
      * @param packageName The name of the package that this text is coming from.
-     * Can not be null.
-     * @param resid The resource identifier of the desired text.  Can not be 0.
+     * Cannot be null.
+     * @param resid The resource identifier of the desired text.  Cannot be 0.
      * @param appInfo Overall information about <var>packageName</var>.  This
      * may be null, in which case the application information will be retrieved
      * for you if needed; if you already have this information around, it can
@@ -2269,8 +2269,8 @@
      * retrieve XML meta data.
      *
      * @param packageName The name of the package that this xml is coming from.
-     * Can not be null.
-     * @param resid The resource identifier of the desired xml.  Can not be 0.
+     * Cannot be null.
+     * @param resid The resource identifier of the desired xml.  Cannot be 0.
      * @param appInfo Overall information about <var>packageName</var>.  This
      * may be null, in which case the application information will be retrieved
      * for you if needed; if you already have this information around, it can
@@ -2288,7 +2288,7 @@
      *
      * @return Returns the label associated with this application, or null if
      * it could not be found for any reason.
-     * @param info The application to get the label of
+     * @param info The application to get the label of.
      */
     public abstract CharSequence getApplicationLabel(ApplicationInfo info);
 
@@ -2296,7 +2296,7 @@
      * Retrieve the resources associated with an activity.  Given the full
      * name of an activity, retrieves the information about it and calls
      * getResources() to return its application's resources.  If the activity
-     * can not be found, NameNotFoundException is thrown.
+     * cannot be found, NameNotFoundException is thrown.
      *
      * @param activityName Name of the activity whose resources are to be
      *                     retrieved.
@@ -2327,7 +2327,7 @@
      * Retrieve the resources associated with an application.  Given the full
      * package name of an application, retrieves the information about it and
      * calls getResources() to return its application's resources.  If the
-     * appPackageName can not be found, NameNotFoundException is thrown.
+     * appPackageName cannot be found, NameNotFoundException is thrown.
      *
      * @param appPackageName Package name of the application whose resources
      *                       are to be retrieved.
@@ -2496,7 +2496,7 @@
      * {@link PackageManager#VERIFICATION_REJECT}.
      *
      * @param id pending package identifier as passed via the
-     *            {@link PackageManager#EXTRA_VERIFICATION_ID} Intent extra
+     *            {@link PackageManager#EXTRA_VERIFICATION_ID} Intent extra.
      * @param verificationCode either {@link PackageManager#VERIFICATION_ALLOW}
      *            or {@link PackageManager#VERIFICATION_REJECT}.
      * @throws SecurityException if the caller does not have the
@@ -2517,7 +2517,7 @@
      * will have no effect.
      *
      * @param id pending package identifier as passed via the
-     *            {@link PackageManager#EXTRA_VERIFICATION_ID} Intent extra
+     *            {@link PackageManager#EXTRA_VERIFICATION_ID} Intent extra.
      * @param verificationCodeAtTimeout either
      *            {@link PackageManager#VERIFICATION_ALLOW} or
      *            {@link PackageManager#VERIFICATION_REJECT}. If
@@ -2701,16 +2701,16 @@
 
     /**
      * @deprecated This function no longer does anything; it was an old
-     * approach to managing preferred activities, which has been superceeded
-     * (and conflicts with) the modern activity-based preferences.
+     * approach to managing preferred activities, which has been superseded
+     * by (and conflicts with) the modern activity-based preferences.
      */
     @Deprecated
     public abstract void addPackageToPreferred(String packageName);
 
     /**
      * @deprecated This function no longer does anything; it was an old
-     * approach to managing preferred activities, which has been superceeded
-     * (and conflicts with) the modern activity-based preferences.
+     * approach to managing preferred activities, which has been superseded
+     * by (and conflicts with) the modern activity-based preferences.
      */
     @Deprecated
     public abstract void removePackageFromPreferred(String packageName);
@@ -2749,7 +2749,7 @@
     /**
      * @deprecated This is a protected API that should not have been available
      * to third party applications.  It is the platform's responsibility for
-     * assigning preferred activities and this can not be directly modified.
+     * assigning preferred activities and this cannot be directly modified.
      *
      * Add a new preferred activity mapping to the system.  This will be used
      * to automatically select the given activity component when
@@ -2783,7 +2783,7 @@
     /**
      * @deprecated This is a protected API that should not have been available
      * to third party applications.  It is the platform's responsibility for
-     * assigning preferred activities and this can not be directly modified.
+     * assigning preferred activities and this cannot be directly modified.
      *
      * Replaces an existing preferred activity mapping to the system, and if that were not present
      * adds a new preferred activity.  This will be used
diff --git a/core/java/android/content/pm/RegisteredServicesCache.java b/core/java/android/content/pm/RegisteredServicesCache.java
index 6def4a1..aaa0917 100644
--- a/core/java/android/content/pm/RegisteredServicesCache.java
+++ b/core/java/android/content/pm/RegisteredServicesCache.java
@@ -34,6 +34,7 @@
 import android.util.SparseArray;
 import android.util.Xml;
 
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.FastXmlSerializer;
 import com.google.android.collect.Lists;
 import com.google.android.collect.Maps;
@@ -68,6 +69,7 @@
  */
 public abstract class RegisteredServicesCache<V> {
     private static final String TAG = "PackageManager";
+    private static final boolean DEBUG = false;
 
     public final Context mContext;
     private final String mInterfaceName;
@@ -77,15 +79,15 @@
 
     private final Object mServicesLock = new Object();
 
-    // @GuardedBy("mServicesLock")
+    @GuardedBy("mServicesLock")
     private boolean mPersistentServicesFileDidNotExist;
-    // @GuardedBy("mServicesLock")
+    @GuardedBy("mServicesLock")
     private final SparseArray<UserServices<V>> mUserServices = new SparseArray<UserServices<V>>();
 
     private static class UserServices<V> {
-        // @GuardedBy("mServicesLock")
+        @GuardedBy("mServicesLock")
         public final Map<V, Integer> persistentServices = Maps.newHashMap();
-        // @GuardedBy("mServicesLock")
+        @GuardedBy("mServicesLock")
         public Map<V, ServiceInfo<V>> services = null;
     }
 
@@ -194,7 +196,7 @@
     }
 
     private void notifyListener(final V type, final int userId, final boolean removed) {
-        if (Log.isLoggable(TAG, Log.VERBOSE)) {
+        if (DEBUG) {
             Log.d(TAG, "notifyListener: " + type + " is " + (removed ? "removed" : "added"));
         }
         RegisteredServicesCacheListener<V> listener;
@@ -290,7 +292,9 @@
      * given {@link UserHandle}.
      */
     private void generateServicesMap(int userId) {
-        Slog.d(TAG, "generateServicesMap() for " + userId);
+        if (DEBUG) {
+            Slog.d(TAG, "generateServicesMap() for " + userId);
+        }
 
         final PackageManager pm = mContext.getPackageManager();
         final ArrayList<ServiceInfo<V>> serviceInfos = new ArrayList<ServiceInfo<V>>();
@@ -321,6 +325,7 @@
             }
 
             StringBuilder changes = new StringBuilder();
+            boolean changed = false;
             for (ServiceInfo<V> info : serviceInfos) {
                 // four cases:
                 // - doesn't exist yet
@@ -333,33 +338,41 @@
                 //   - add, notify user that it was added
                 Integer previousUid = user.persistentServices.get(info.type);
                 if (previousUid == null) {
-                    changes.append("  New service added: ").append(info).append("\n");
+                    if (DEBUG) {
+                        changes.append("  New service added: ").append(info).append("\n");
+                    }
+                    changed = true;
                     user.services.put(info.type, info);
                     user.persistentServices.put(info.type, info.uid);
                     if (!(mPersistentServicesFileDidNotExist && firstScan)) {
                         notifyListener(info.type, userId, false /* removed */);
                     }
                 } else if (previousUid == info.uid) {
-                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
+                    if (DEBUG) {
                         changes.append("  Existing service (nop): ").append(info).append("\n");
                     }
                     user.services.put(info.type, info);
                 } else if (inSystemImage(info.uid)
                         || !containsTypeAndUid(serviceInfos, info.type, previousUid)) {
-                    if (inSystemImage(info.uid)) {
-                        changes.append("  System service replacing existing: ").append(info)
-                                .append("\n");
-                    } else {
-                        changes.append("  Existing service replacing a removed service: ")
-                                .append(info).append("\n");
+                    if (DEBUG) {
+                        if (inSystemImage(info.uid)) {
+                            changes.append("  System service replacing existing: ").append(info)
+                                    .append("\n");
+                        } else {
+                            changes.append("  Existing service replacing a removed service: ")
+                                    .append(info).append("\n");
+                        }
                     }
+                    changed = true;
                     user.services.put(info.type, info);
                     user.persistentServices.put(info.type, info.uid);
                     notifyListener(info.type, userId, false /* removed */);
                 } else {
                     // ignore
-                    changes.append("  Existing service with new uid ignored: ").append(info)
-                            .append("\n");
+                    if (DEBUG) {
+                        changes.append("  Existing service with new uid ignored: ").append(info)
+                                .append("\n");
+                    }
                 }
             }
 
@@ -370,22 +383,25 @@
                 }
             }
             for (V v1 : toBeRemoved) {
+                if (DEBUG) {
+                    changes.append("  Service removed: ").append(v1).append("\n");
+                }
+                changed = true;
                 user.persistentServices.remove(v1);
-                changes.append("  Service removed: ").append(v1).append("\n");
                 notifyListener(v1, userId, true /* removed */);
             }
-            if (changes.length() > 0) {
-                if (Log.isLoggable(TAG, Log.VERBOSE)) {
+            if (DEBUG) {
+                if (changes.length() > 0) {
                     Log.d(TAG, "generateServicesMap(" + mInterfaceName + "): " +
                             serviceInfos.size() + " services:\n" + changes);
-                }
-                writePersistentServicesLocked();
-            } else {
-                if (Log.isLoggable(TAG, Log.VERBOSE)) {
+                } else {
                     Log.d(TAG, "generateServicesMap(" + mInterfaceName + "): " +
                             serviceInfos.size() + " services unchanged");
                 }
             }
+            if (changed) {
+                writePersistentServicesLocked();
+            }
         }
     }
 
diff --git a/core/java/android/hardware/SensorEvent.java b/core/java/android/hardware/SensorEvent.java
index 51a17c1..6166d2c 100644
--- a/core/java/android/hardware/SensorEvent.java
+++ b/core/java/android/hardware/SensorEvent.java
@@ -334,8 +334,8 @@
      * </p>
      * 
      * <p>
-     * values[2]: Roll, rotation around y-axis (-90 to 90), with positive values
-     * when the x-axis moves <b>toward</b> the z-axis.
+     * values[2]: Roll, rotation around the x-axis (-90 to 90)
+     * increasing as the device moves clockwise.
      * </p>
      * </ul>
      * 
diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java
index b8ad818..08fba29 100644
--- a/core/java/android/hardware/SensorManager.java
+++ b/core/java/android/hardware/SensorManager.java
@@ -572,7 +572,10 @@
      *        are received faster. The value must be one of
      *        {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI},
      *        {@link #SENSOR_DELAY_GAME}, or {@link #SENSOR_DELAY_FASTEST}
-     *        or, the desired delay between events in microsecond.
+     *        or, the desired delay between events in microseconds.
+     *        Specifying the delay in microseconds only works from Android
+     *        2.3 (API level 9) onwards. For earlier releases, you must use
+     *        one of the {@code SENSOR_DELAY_*} constants.
      *
      * @return <code>true</code> if the sensor is supported and successfully
      *         enabled.
@@ -604,7 +607,10 @@
      *        are received faster. The value must be one of
      *        {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI},
      *        {@link #SENSOR_DELAY_GAME}, or {@link #SENSOR_DELAY_FASTEST}.
-     *        or, the desired delay between events in microsecond.
+     *        or, the desired delay between events in microseconds.
+     *        Specifying the delay in microseconds only works from Android
+     *        2.3 (API level 9) onwards. For earlier releases, you must use
+     *        one of the {@code SENSOR_DELAY_*} constants.
      *
      * @param handler
      *        The {@link android.os.Handler Handler} the
diff --git a/core/java/android/hardware/display/WifiDisplay.java b/core/java/android/hardware/display/WifiDisplay.java
index 0138b1c..2fd52b8 100644
--- a/core/java/android/hardware/display/WifiDisplay.java
+++ b/core/java/android/hardware/display/WifiDisplay.java
@@ -107,6 +107,15 @@
                 && Objects.equal(mDeviceAlias, other.mDeviceAlias);
     }
 
+    /**
+     * Returns true if the other display is not null and has the same address as this one.
+     * Can be used to perform identity comparisons on displays ignoring properties
+     * that might change during a connection such as the name or alias.
+     */
+    public boolean hasSameAddress(WifiDisplay other) {
+        return other != null && mDeviceAddress.equals(other.mDeviceAddress);
+    }
+
     @Override
     public int hashCode() {
         // The address on its own should be sufficiently unique for hashing purposes.
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index f07002e..6f1cc94 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -930,11 +930,13 @@
      */
     public void onConfigureWindow(Window win, boolean isFullscreen,
             boolean isCandidatesOnly) {
-        if (isFullscreen) {
-            mWindow.getWindow().setLayout(MATCH_PARENT, MATCH_PARENT);
-        } else {
-            mWindow.getWindow().setLayout(MATCH_PARENT, WRAP_CONTENT);
+        final int currentHeight = mWindow.getWindow().getAttributes().height;
+        final int newHeight = isFullscreen ? MATCH_PARENT : WRAP_CONTENT;
+        if (mIsInputViewShown && currentHeight != newHeight) {
+            Log.w(TAG, "Window size has been changed. This may cause jankiness of resizing window: "
+                    + currentHeight + " -> " + newHeight);
         }
+        mWindow.getWindow().setLayout(MATCH_PARENT, newHeight);
     }
     
     /**
@@ -997,10 +999,11 @@
     }
     
     void updateExtractFrameVisibility() {
-        int vis;
+        final int vis;
         if (isFullscreenMode()) {
             vis = mExtractViewHidden ? View.INVISIBLE : View.VISIBLE;
-            mExtractFrame.setVisibility(View.VISIBLE);
+            // "vis" should be applied for the extract frame as well in the fullscreen mode.
+            mExtractFrame.setVisibility(vis);
         } else {
             vis = View.VISIBLE;
             mExtractFrame.setVisibility(View.GONE);
diff --git a/core/java/android/net/DhcpStateMachine.java b/core/java/android/net/DhcpStateMachine.java
index 874e80a..8dc900e 100644
--- a/core/java/android/net/DhcpStateMachine.java
+++ b/core/java/android/net/DhcpStateMachine.java
@@ -351,6 +351,8 @@
         DhcpInfoInternal dhcpInfoInternal = new DhcpInfoInternal();
 
         if (dhcpAction == DhcpAction.START) {
+            /* Stop any existing DHCP daemon before starting new */
+            NetworkUtils.stopDhcp(mInterfaceName);
             if (DBG) Log.d(TAG, "DHCP request on " + mInterfaceName);
             success = NetworkUtils.runDhcp(mInterfaceName, dhcpInfoInternal);
             mDhcpInfo = dhcpInfoInternal;
diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java
index 446bbf0..c757605 100644
--- a/core/java/android/net/NetworkStats.java
+++ b/core/java/android/net/NetworkStats.java
@@ -21,6 +21,7 @@
 import android.os.SystemClock;
 import android.util.SparseBooleanArray;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.Objects;
 
@@ -190,14 +191,14 @@
         return clone;
     }
 
-    // @VisibleForTesting
+    @VisibleForTesting
     public NetworkStats addIfaceValues(
             String iface, long rxBytes, long rxPackets, long txBytes, long txPackets) {
         return addValues(
                 iface, UID_ALL, SET_DEFAULT, TAG_NONE, rxBytes, rxPackets, txBytes, txPackets, 0L);
     }
 
-    // @VisibleForTesting
+    @VisibleForTesting
     public NetworkStats addValues(String iface, int uid, int set, int tag, long rxBytes,
             long rxPackets, long txBytes, long txPackets, long operations) {
         return addValues(new Entry(
@@ -269,7 +270,7 @@
         return size;
     }
 
-    // @VisibleForTesting
+    @VisibleForTesting
     public int internalSize() {
         return iface.length;
     }
@@ -335,7 +336,7 @@
      * Find first stats index that matches the requested parameters, starting
      * search around the hinted index as an optimization.
      */
-    // @VisibleForTesting
+    @VisibleForTesting
     public int findIndexHinted(String iface, int uid, int set, int tag, int hintIndex) {
         for (int offset = 0; offset < size; offset++) {
             final int halfOffset = offset / 2;
diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java
index d8e53d5..d3839ad 100644
--- a/core/java/android/net/NetworkTemplate.java
+++ b/core/java/android/net/NetworkTemplate.java
@@ -33,6 +33,7 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.Objects;
 
 /**
@@ -63,7 +64,7 @@
 
     private static boolean sForceAllNetworkTypes = false;
 
-    // @VisibleForTesting
+    @VisibleForTesting
     public static void forceAllNetworkTypes() {
         sForceAllNetworkTypes = true;
     }
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 54f2fe3..9821824 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -18,6 +18,8 @@
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
 import java.util.Formatter;
 import java.util.List;
 import java.util.Map;
@@ -1127,8 +1129,10 @@
             if (totalTimeMillis != 0) {
                 sb.append(linePrefix);
                 formatTimeMs(sb, totalTimeMillis);
-                if (name != null) sb.append(name);
-                sb.append(' ');
+                if (name != null) {
+                    sb.append(name);
+                    sb.append(' ');
+                }
                 sb.append('(');
                 sb.append(count);
                 sb.append(" times)");
@@ -1440,8 +1444,21 @@
         }
     }
 
+    static final class TimerEntry {
+        final String mName;
+        final int mId;
+        final BatteryStats.Timer mTimer;
+        final long mTime;
+        TimerEntry(String name, int id, BatteryStats.Timer timer, long time) {
+            mName = name;
+            mId = id;
+            mTimer = timer;
+            mTime = time;
+        }
+    }
+
     @SuppressWarnings("unused")
-    public final void dumpLocked(PrintWriter pw, String prefix, int which, int reqUid) {
+    public final void dumpLocked(PrintWriter pw, String prefix, final int which, int reqUid) {
         final long rawUptime = SystemClock.uptimeMillis() * 1000;
         final long rawRealtime = SystemClock.elapsedRealtime() * 1000;
         final long batteryUptime = getBatteryUptime(rawUptime);
@@ -1516,19 +1533,43 @@
         long txTotal = 0;
         long fullWakeLockTimeTotalMicros = 0;
         long partialWakeLockTimeTotalMicros = 0;
-        
+
+        final Comparator<TimerEntry> timerComparator = new Comparator<TimerEntry>() {
+            @Override
+            public int compare(TimerEntry lhs, TimerEntry rhs) {
+                long lhsTime = lhs.mTime;
+                long rhsTime = rhs.mTime;
+                if (lhsTime < rhsTime) {
+                    return 1;
+                }
+                if (lhsTime > rhsTime) {
+                    return -1;
+                }
+                return 0;
+            }
+        };
+
         if (reqUid < 0) {
             Map<String, ? extends BatteryStats.Timer> kernelWakelocks = getKernelWakelockStats();
             if (kernelWakelocks.size() > 0) {
+                final ArrayList<TimerEntry> timers = new ArrayList<TimerEntry>();
                 for (Map.Entry<String, ? extends BatteryStats.Timer> ent : kernelWakelocks.entrySet()) {
-                    
+                    BatteryStats.Timer timer = ent.getValue();
+                    long totalTimeMillis = computeWakeLock(timer, batteryRealtime, which);
+                    if (totalTimeMillis > 0) {
+                        timers.add(new TimerEntry(ent.getKey(), 0, timer, totalTimeMillis));
+                    }
+                }
+                Collections.sort(timers, timerComparator);
+                for (int i=0; i<timers.size(); i++) {
+                    TimerEntry timer = timers.get(i);
                     String linePrefix = ": ";
                     sb.setLength(0);
                     sb.append(prefix);
                     sb.append("  Kernel Wake lock ");
-                    sb.append(ent.getKey());
-                    linePrefix = printWakeLock(sb, ent.getValue(), batteryRealtime, null, which, 
-                            linePrefix);
+                    sb.append(timer.mName);
+                    linePrefix = printWakeLock(sb, timer.mTimer, batteryRealtime, null,
+                            which, linePrefix);
                     if (!linePrefix.equals(": ")) {
                         sb.append(" realtime");
                         // Only print out wake locks that were held
@@ -1537,7 +1578,9 @@
                 }
             }
         }
-    
+
+        final ArrayList<TimerEntry> timers = new ArrayList<TimerEntry>();
+
         for (int iu = 0; iu < NU; iu++) {
             Uid u = uidStats.valueAt(iu);
             rxTotal += u.getTcpBytesReceived(which);
@@ -1557,8 +1600,18 @@
 
                     Timer partialWakeTimer = wl.getWakeTime(WAKE_TYPE_PARTIAL);
                     if (partialWakeTimer != null) {
-                        partialWakeLockTimeTotalMicros += partialWakeTimer.getTotalTimeLocked(
+                        long totalTimeMicros = partialWakeTimer.getTotalTimeLocked(
                                 batteryRealtime, which);
+                        if (totalTimeMicros > 0) {
+                            if (reqUid < 0) {
+                                // Only show the ordered list of all wake
+                                // locks if the caller is not asking for data
+                                // about a specific uid.
+                                timers.add(new TimerEntry(ent.getKey(), u.getUid(),
+                                        partialWakeTimer, totalTimeMicros));
+                            }
+                            partialWakeLockTimeTotalMicros += totalTimeMicros;
+                        }
                     }
                 }
             }
@@ -1571,7 +1624,7 @@
         sb.append(prefix);
                 sb.append("  Total full wakelock time: "); formatTimeMs(sb,
                         (fullWakeLockTimeTotalMicros + 500) / 1000);
-                sb.append(", Total partial waklock time: "); formatTimeMs(sb,
+                sb.append(", Total partial wakelock time: "); formatTimeMs(sb,
                         (partialWakeLockTimeTotalMicros + 500) / 1000);
         pw.println(sb.toString());
         
@@ -1676,9 +1729,26 @@
                     pw.println(getDischargeAmountScreenOnSinceCharge());
             pw.print(prefix); pw.print("    Amount discharged while screen off: ");
                     pw.println(getDischargeAmountScreenOffSinceCharge());
-            pw.println(" ");
+            pw.println();
         }
-        
+
+        if (timers.size() > 0) {
+            Collections.sort(timers, timerComparator);
+            pw.print(prefix); pw.println("  All partial wake locks:");
+            for (int i=0; i<timers.size(); i++) {
+                TimerEntry timer = timers.get(i);
+                sb.setLength(0);
+                sb.append("  Wake lock #");
+                sb.append(timer.mId);
+                sb.append(" ");
+                sb.append(timer.mName);
+                printWakeLock(sb, timer.mTimer, batteryRealtime, null, which, ": ");
+                sb.append(" realtime");
+                pw.println(sb.toString());
+            }
+            timers.clear();
+            pw.println();
+        }
 
         for (int iu=0; iu<NU; iu++) {
             final int uid = uidStats.keyAt(iu);
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
index 88529f8..1bada67 100644
--- a/core/java/android/os/Environment.java
+++ b/core/java/android/os/Environment.java
@@ -22,6 +22,8 @@
 import android.text.TextUtils;
 import android.util.Log;
 
+import com.android.internal.annotations.GuardedBy;
+
 import java.io.File;
 
 /**
@@ -47,7 +49,7 @@
 
     private static final Object sLock = new Object();
 
-    // @GuardedBy("sLock")
+    @GuardedBy("sLock")
     private static volatile StorageVolume sPrimaryVolume;
 
     private static StorageVolume getPrimaryVolume() {
diff --git a/core/java/android/os/ParcelFileDescriptor.java b/core/java/android/os/ParcelFileDescriptor.java
index 3e90dfc..ec660ee 100644
--- a/core/java/android/os/ParcelFileDescriptor.java
+++ b/core/java/android/os/ParcelFileDescriptor.java
@@ -15,6 +15,9 @@
  */
 
 package android.os;
+
+import dalvik.system.CloseGuard;
+
 import java.io.Closeable;
 import java.io.File;
 import java.io.FileDescriptor;
@@ -31,12 +34,16 @@
  */
 public class ParcelFileDescriptor implements Parcelable, Closeable {
     private final FileDescriptor mFileDescriptor;
-    private boolean mClosed;
-    //this field is to create wrapper for ParcelFileDescriptor using another
-    //PartialFileDescriptor but avoid invoking close twice
-    //consider ParcelFileDescriptor A(fileDescriptor fd),  ParcelFileDescriptor B(A)
-    //in this particular case fd.close might be invoked twice.
-    private final ParcelFileDescriptor mParcelDescriptor;
+
+    /**
+     * Wrapped {@link ParcelFileDescriptor}, if any. Used to avoid
+     * double-closing {@link #mFileDescriptor}.
+     */
+    private final ParcelFileDescriptor mWrapped;
+
+    private volatile boolean mClosed;
+
+    private final CloseGuard mGuard = CloseGuard.get();
 
     /**
      * For use with {@link #open}: if {@link #MODE_CREATE} has been supplied
@@ -289,13 +296,15 @@
         if (mClosed) {
             throw new IllegalStateException("Already closed");
         }
-        if (mParcelDescriptor != null) {
-            int fd = mParcelDescriptor.detachFd();
+        if (mWrapped != null) {
+            int fd = mWrapped.detachFd();
             mClosed = true;
+            mGuard.close();
             return fd;
         }
         int fd = getFd();
         mClosed = true;
+        mGuard.close();
         Parcel.clearFileDescriptor(mFileDescriptor);
         return fd;
     }
@@ -307,15 +316,16 @@
      * @throws IOException
      *             If an error occurs attempting to close this ParcelFileDescriptor.
      */
+    @Override
     public void close() throws IOException {
-        synchronized (this) {
-            if (mClosed) return;
-            mClosed = true;
-        }
-        if (mParcelDescriptor != null) {
+        if (mClosed) return;
+        mClosed = true;
+        mGuard.close();
+
+        if (mWrapped != null) {
             // If this is a proxy to another file descriptor, just call through to its
             // close method.
-            mParcelDescriptor.close();
+            mWrapped.close();
         } else {
             Parcel.closeFileDescriptor(mFileDescriptor);
         }
@@ -374,6 +384,9 @@
 
     @Override
     protected void finalize() throws Throwable {
+        if (mGuard != null) {
+            mGuard.warnIfOpen();
+        }
         try {
             if (!mClosed) {
                 close();
@@ -384,21 +397,22 @@
     }
 
     public ParcelFileDescriptor(ParcelFileDescriptor descriptor) {
-        super();
-        mParcelDescriptor = descriptor;
-        mFileDescriptor = mParcelDescriptor.mFileDescriptor;
+        mWrapped = descriptor;
+        mFileDescriptor = mWrapped.mFileDescriptor;
+        mGuard.open("close");
     }
 
-    /*package */ParcelFileDescriptor(FileDescriptor descriptor) {
-        super();
+    /** {@hide} */
+    public ParcelFileDescriptor(FileDescriptor descriptor) {
         if (descriptor == null) {
             throw new NullPointerException("descriptor must not be null");
         }
+        mWrapped = null;
         mFileDescriptor = descriptor;
-        mParcelDescriptor = null;
+        mGuard.open("close");
     }
 
-    /* Parcelable interface */
+    @Override
     public int describeContents() {
         return Parcelable.CONTENTS_FILE_DESCRIPTOR;
     }
@@ -408,6 +422,7 @@
      * If {@link Parcelable#PARCELABLE_WRITE_RETURN_VALUE} is set in flags,
      * the file descriptor will be closed after a copy is written to the Parcel.
      */
+    @Override
     public void writeToParcel(Parcel out, int flags) {
         out.writeFileDescriptor(mFileDescriptor);
         if ((flags&PARCELABLE_WRITE_RETURN_VALUE) != 0 && !mClosed) {
@@ -421,12 +436,14 @@
 
     public static final Parcelable.Creator<ParcelFileDescriptor> CREATOR
             = new Parcelable.Creator<ParcelFileDescriptor>() {
+        @Override
         public ParcelFileDescriptor createFromParcel(Parcel in) {
             return in.readFileDescriptor();
         }
+
+        @Override
         public ParcelFileDescriptor[] newArray(int size) {
             return new ParcelFileDescriptor[size];
         }
     };
-
 }
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 4a01113..736762f 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -182,6 +182,8 @@
      * </p><p>
      * Since not all devices have proximity sensors, use {@link #isWakeLockLevelSupported}
      * to determine whether this wake lock level is supported.
+     * </p><p>
+     * Cannot be used with {@link #ACQUIRE_CAUSES_WAKEUP}.
      * </p>
      *
      * {@hide}
diff --git a/core/java/android/os/Trace.java b/core/java/android/os/Trace.java
index ed51818..0ca9183 100644
--- a/core/java/android/os/Trace.java
+++ b/core/java/android/os/Trace.java
@@ -44,6 +44,7 @@
     public static final long TRACE_TAG_AUDIO = 1L << 8;
     public static final long TRACE_TAG_VIDEO = 1L << 9;
     public static final long TRACE_TAG_CAMERA = 1L << 10;
+    private static final long TRACE_TAG_NOT_READY = 1L << 63;
 
     public static final int TRACE_FLAGS_START_BIT = 1;
     public static final String[] TRACE_TAGS = {
@@ -53,11 +54,8 @@
 
     public static final String PROPERTY_TRACE_TAG_ENABLEFLAGS = "debug.atrace.tags.enableflags";
 
-    // This works as a "not ready" flag because TRACE_TAG_ALWAYS is always set.
-    private static final long TRACE_FLAGS_NOT_READY = 0;
-
     // Must be volatile to avoid word tearing.
-    private static volatile long sEnabledTags = TRACE_FLAGS_NOT_READY;
+    private static volatile long sEnabledTags = TRACE_TAG_NOT_READY;
 
     private static native long nativeGetEnabledTags();
     private static native void nativeTraceCounter(long tag, String name, int value);
@@ -99,7 +97,7 @@
      */
     private static long cacheEnabledTags() {
         long tags = nativeGetEnabledTags();
-        if (tags == TRACE_FLAGS_NOT_READY) {
+        if (tags == TRACE_TAG_NOT_READY) {
             Log.w(TAG, "Unexpected value from nativeGetEnabledTags: " + tags);
             // keep going
         }
@@ -115,7 +113,7 @@
      */
     public static boolean isTagEnabled(long traceTag) {
         long tags = sEnabledTags;
-        if (tags == TRACE_FLAGS_NOT_READY) {
+        if (tags == TRACE_TAG_NOT_READY) {
             tags = cacheEnabledTags();
         }
         return (tags & traceTag) != 0;
diff --git a/core/java/android/provider/CalendarContract.java b/core/java/android/provider/CalendarContract.java
index af6e88e9..0fa5799 100644
--- a/core/java/android/provider/CalendarContract.java
+++ b/core/java/android/provider/CalendarContract.java
@@ -106,16 +106,13 @@
      * {@link Activity#RESULT_OK} or {@link Activity#RESULT_CANCELED} to
      * acknowledge whether the action was handled or not.
      *
-     * The custom app should have an intent-filter like the following
+     * The custom app should have an intent filter like the following:
      * <pre>
-     * {@code
-     * <intent-filter>
-     *    <action android:name="android.provider.calendar.action.HANDLE_CUSTOM_EVENT" />
-     *    <category android:name="android.intent.category.DEFAULT" />
-     *    <data android:mimeType="vnd.android.cursor.item/event" />
-     * </intent-filter>
-     * }
-     * </pre>
+     * &lt;intent-filter&gt;
+     *    &lt;action android:name="android.provider.calendar.action.HANDLE_CUSTOM_EVENT" /&gt;
+     *    &lt;category android:name="android.intent.category.DEFAULT" /&gt;
+     *    &lt;data android:mimeType="vnd.android.cursor.item/event" /&gt;
+     * &lt;/intent-filter&gt;</pre>
      * <p>
      * Input: {@link Intent#getData} has the event URI. The extra
      * {@link #EXTRA_EVENT_BEGIN_TIME} has the start time of the instance. The
@@ -123,7 +120,7 @@
      * {@link EventsColumns#CUSTOM_APP_URI}.
      * <p>
      * Output: {@link Activity#RESULT_OK} if this was handled; otherwise
-     * {@link Activity#RESULT_CANCELED}
+     * {@link Activity#RESULT_CANCELED}.
      */
     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
     public static final String ACTION_HANDLE_CUSTOM_EVENT =
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index 8f54a38..965d38d 100755
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -1359,7 +1359,7 @@
      * status definitions. Automatically computed as the highest presence of all
      * constituent raw contacts. The provider may choose not to store this value
      * in persistent storage. The expectation is that presence status will be
-     * updated on a regular basic.</td>
+     * updated on a regular basis.</td>
      * </tr>
      * <tr>
      * <td>String</td>
@@ -4131,7 +4131,7 @@
      * all IM rows. See {@link StatusUpdates} for individual status definitions.
      * The provider may choose not to store this value
      * in persistent storage. The expectation is that presence status will be
-     * updated on a regular basic.
+     * updated on a regular basis.
      * </td>
      * </tr>
      * <tr>
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index b94f0b9..4dbc4b4 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -626,6 +626,21 @@
     public static final String ACTION_NFCSHARING_SETTINGS =
         "android.settings.NFCSHARING_SETTINGS";
 
+    /**
+     * Activity Action: Show Daydream settings.
+     * <p>
+     * In some cases, a matching Activity may not exist, so ensure you
+     * safeguard against this.
+     * <p>
+     * Input: Nothing.
+     * <p>
+     * Output: Nothing.
+     * @see android.service.dreams.DreamService
+     * @hide
+     */
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_DREAM_SETTINGS = "android.settings.DREAM_SETTINGS";
+
     // End of Intent actions for Settings
 
     /**
@@ -4281,6 +4296,13 @@
         public static final String POWER_SOUNDS_ENABLED = "power_sounds_enabled";
 
         /**
+         * URI for the "wireless charging started" sound.
+         * @hide
+         */
+        public static final String WIRELESS_CHARGING_STARTED_SOUND =
+                "wireless_charging_started_sound";
+
+        /**
          * Whether we keep the device on while the device is plugged in.
          * Supported values are:
          * <ul>
@@ -5315,6 +5337,12 @@
         public static final String DOCK_AUDIO_MEDIA_ENABLED = "dock_audio_media_enabled";
 
         /**
+         * Persisted safe headphone volume management state by AudioService
+         * @hide
+         */
+        public static final String AUDIO_SAFE_VOLUME_STATE = "audio_safe_volume_state";
+
+        /**
          * Settings to backup. This is here so that it's in the same place as the settings
          * keys and easy to update.
          *
diff --git a/core/java/android/server/search/SearchManagerService.java b/core/java/android/server/search/SearchManagerService.java
index 4a21374..46f2723 100644
--- a/core/java/android/server/search/SearchManagerService.java
+++ b/core/java/android/server/search/SearchManagerService.java
@@ -92,7 +92,7 @@
             Searchables searchables = mSearchables.get(userId);
 
             if (searchables == null) {
-                Log.i(TAG, "Building list of searchable activities for userId=" + userId);
+                //Log.i(TAG, "Building list of searchable activities for userId=" + userId);
                 searchables = new Searchables(mContext, userId);
                 searchables.buildSearchableList();
                 mSearchables.append(userId, searchables);
diff --git a/core/java/android/text/format/DateUtils.java b/core/java/android/text/format/DateUtils.java
index 1060bd8..bcce61d 100644
--- a/core/java/android/text/format/DateUtils.java
+++ b/core/java/android/text/format/DateUtils.java
@@ -607,6 +607,30 @@
     }
 
     /**
+     * Return given duration in a human-friendly format. For example, "4
+     * minutes" or "1 second". Returns only largest meaningful unit of time,
+     * from seconds up to hours.
+     *
+     * @hide
+     */
+    public static CharSequence formatDuration(long millis) {
+        final Resources res = Resources.getSystem();
+        if (millis >= HOUR_IN_MILLIS) {
+            final int hours = (int) ((millis + 1800000) / HOUR_IN_MILLIS);
+            return res.getQuantityString(
+                    com.android.internal.R.plurals.duration_hours, hours, hours);
+        } else if (millis >= MINUTE_IN_MILLIS) {
+            final int minutes = (int) ((millis + 30000) / MINUTE_IN_MILLIS);
+            return res.getQuantityString(
+                    com.android.internal.R.plurals.duration_minutes, minutes, minutes);
+        } else {
+            final int seconds = (int) ((millis + 500) / SECOND_IN_MILLIS);
+            return res.getQuantityString(
+                    com.android.internal.R.plurals.duration_seconds, seconds, seconds);
+        }
+    }
+
+    /**
      * Formats an elapsed time in the form "MM:SS" or "H:MM:SS"
      * for display on the call-in-progress screen.
      * @param elapsedSeconds the elapsed time in seconds.
diff --git a/core/java/android/util/AttributeSet.java b/core/java/android/util/AttributeSet.java
index 470526c..74942ba 100644
--- a/core/java/android/util/AttributeSet.java
+++ b/core/java/android/util/AttributeSet.java
@@ -151,7 +151,7 @@
      * Return the value of 'attribute' as a resource identifier.
      * 
      * <p>Note that this is different than {@link #getAttributeNameResource}
-     * in that it returns a the value contained in this attribute as a
+     * in that it returns the value contained in this attribute as a
      * resource identifier (i.e., a value originally of the form
      * "@package:type/resource"); the other method returns a resource
      * identifier that identifies the name of the attribute.
@@ -230,7 +230,7 @@
      * Return the value of attribute at 'index' as a resource identifier.
      * 
      * <p>Note that this is different than {@link #getAttributeNameResource}
-     * in that it returns a the value contained in this attribute as a
+     * in that it returns the value contained in this attribute as a
      * resource identifier (i.e., a value originally of the form
      * "@package:type/resource"); the other method returns a resource
      * identifier that identifies the name of the attribute.
diff --git a/core/java/android/util/DisplayMetrics.java b/core/java/android/util/DisplayMetrics.java
index 85e4b9d..e856501 100644
--- a/core/java/android/util/DisplayMetrics.java
+++ b/core/java/android/util/DisplayMetrics.java
@@ -232,19 +232,32 @@
      * @return True if the display metrics are equal.
      */
     public boolean equals(DisplayMetrics other) {
+        return equalsPhysical(other)
+                && scaledDensity == other.scaledDensity
+                && noncompatScaledDensity == other.noncompatScaledDensity;
+    }
+
+    /**
+     * Returns true if the physical aspects of the two display metrics
+     * are equal.  This ignores the scaled density, which is a logical
+     * attribute based on the current desired font size.
+     *
+     * @param other The display metrics with which to compare.
+     * @return True if the display metrics are equal.
+     * @hide
+     */
+    public boolean equalsPhysical(DisplayMetrics other) {
         return other != null
                 && widthPixels == other.widthPixels
                 && heightPixels == other.heightPixels
                 && density == other.density
                 && densityDpi == other.densityDpi
-                && scaledDensity == other.scaledDensity
                 && xdpi == other.xdpi
                 && ydpi == other.ydpi
                 && noncompatWidthPixels == other.noncompatWidthPixels
                 && noncompatHeightPixels == other.noncompatHeightPixels
                 && noncompatDensity == other.noncompatDensity
                 && noncompatDensityDpi == other.noncompatDensityDpi
-                && noncompatScaledDensity == other.noncompatScaledDensity
                 && noncompatXdpi == other.noncompatXdpi
                 && noncompatYdpi == other.noncompatYdpi;
     }
diff --git a/core/java/android/util/IntProperty.java b/core/java/android/util/IntProperty.java
index 459d6b2..17977ca 100644
--- a/core/java/android/util/IntProperty.java
+++ b/core/java/android/util/IntProperty.java
@@ -42,7 +42,7 @@
 
     @Override
     final public void set(T object, Integer value) {
-        set(object, value.intValue());
+        setValue(object, value.intValue());
     }
 
 }
\ No newline at end of file
diff --git a/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java
index f3841d5..305fd5c 100644
--- a/core/java/android/view/DisplayInfo.java
+++ b/core/java/android/view/DisplayInfo.java
@@ -285,6 +285,16 @@
         getMetricsWithSize(outMetrics, cih, logicalWidth, logicalHeight);
     }
 
+    public int getNaturalWidth() {
+        return rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180 ?
+                logicalWidth : logicalHeight;
+    }
+
+    public int getNaturalHeight() {
+        return rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180 ?
+                logicalHeight : logicalWidth;
+    }
+
     private void getMetricsWithSize(DisplayMetrics outMetrics, CompatibilityInfoHolder cih,
             int width, int height) {
         outMetrics.densityDpi = outMetrics.noncompatDensityDpi = logicalDensityDpi;
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index 1c613245..5b7a5af 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -1304,17 +1304,11 @@
                 }
             }
 
-            if ((status & DisplayList.STATUS_INVOKE) != 0) {
-                scheduleFunctors(attachInfo, true);
-            }
-        }
-
-        private void scheduleFunctors(View.AttachInfo attachInfo, boolean delayed) {
-            mFunctorsRunnable.attachInfo = attachInfo;
-            if (!attachInfo.mHandler.hasCallbacks(mFunctorsRunnable)) {
-                // delay the functor callback by a few ms so it isn't polled constantly
-                attachInfo.mHandler.postDelayed(mFunctorsRunnable,
-                                                delayed ? FUNCTOR_PROCESS_DELAY : 0);
+            if ((status & DisplayList.STATUS_INVOKE) != 0 ||
+                    attachInfo.mHandler.hasCallbacks(mFunctorsRunnable)) {
+                attachInfo.mHandler.removeCallbacks(mFunctorsRunnable);
+                mFunctorsRunnable.attachInfo = attachInfo;
+                attachInfo.mHandler.postDelayed(mFunctorsRunnable, FUNCTOR_PROCESS_DELAY);
             }
         }
 
@@ -1329,7 +1323,9 @@
         boolean attachFunctor(View.AttachInfo attachInfo, int functor) {
             if (mCanvas != null) {
                 mCanvas.attachFunctor(functor);
-                scheduleFunctors(attachInfo, false);
+                mFunctorsRunnable.attachInfo = attachInfo;
+                attachInfo.mHandler.removeCallbacks(mFunctorsRunnable);
+                attachInfo.mHandler.postDelayed(mFunctorsRunnable,  0);
                 return true;
             }
             return false;
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 0fe2a8e..2b6cbcf 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -74,7 +74,7 @@
     void setEventDispatching(boolean enabled);
     void addWindowToken(IBinder token, int type);
     void removeWindowToken(IBinder token);
-    void addAppToken(int addPos, IApplicationToken token,
+    void addAppToken(int addPos, int userId, IApplicationToken token,
             int groupId, int requestedOrientation, boolean fullscreen, boolean showWhenLocked);
     void setAppGroupId(IBinder token, int groupId);
     void setAppOrientation(IApplicationToken token, int requestedOrientation);
diff --git a/core/java/android/view/ScaleGestureDetector.java b/core/java/android/view/ScaleGestureDetector.java
index ee3f5d8..51c5c7b 100644
--- a/core/java/android/view/ScaleGestureDetector.java
+++ b/core/java/android/view/ScaleGestureDetector.java
@@ -259,6 +259,8 @@
             mInputEventConsistencyVerifier.onTouchEvent(event, 0);
         }
 
+        mCurrTime = event.getEventTime();
+
         final int action = event.getActionMasked();
 
         final boolean streamComplete = action == MotionEvent.ACTION_UP ||
@@ -341,6 +343,7 @@
             mPrevSpanX = mCurrSpanX = spanX;
             mPrevSpanY = mCurrSpanY = spanY;
             mPrevSpan = mCurrSpan = span;
+            mPrevTime = mCurrTime;
             mInProgress = mListener.onScaleBegin(this);
         }
 
@@ -359,6 +362,7 @@
                 mPrevSpanX = mCurrSpanX;
                 mPrevSpanY = mCurrSpanY;
                 mPrevSpan = mCurrSpan;
+                mPrevTime = mCurrTime;
             }
         }
 
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index 550a740..0a81a71 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -225,6 +225,9 @@
     // non compatibility mode.
     private Matrix mCompatibleMatrix;
 
+    private int mWidth;
+    private int mHeight;
+
     private native void nativeCreate(SurfaceSession session, String name,
             int w, int h, int format, int flags)
             throws OutOfResourcesException;
@@ -330,6 +333,8 @@
         checkHeadless();
 
         mName = name;
+        mWidth = w;
+        mHeight = h;
         nativeCreate(session, name, w, h, format, flags);
 
         mCloseGuard.open("release");
@@ -538,7 +543,7 @@
 
     /** @hide */
     public void setPosition(int x, int y) {
-        nativeSetPosition((float)x, (float)y);
+        nativeSetPosition(x, y);
     }
 
     /** @hide */
@@ -548,10 +553,22 @@
 
     /** @hide */
     public void setSize(int w, int h) {
+        mWidth = w;
+        mHeight = h;
         nativeSetSize(w, h);
     }
 
     /** @hide */
+    public int getWidth() {
+        return mWidth;
+    }
+
+    /** @hide */
+    public int getHeight() {
+        return mHeight;
+    }
+
+    /** @hide */
     public void hide() {
         nativeSetFlags(SURFACE_HIDDEN, SURFACE_HIDDEN);
     }
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index ef50353..cf61599 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -11856,8 +11856,6 @@
 
         mCurrentAnimation = null;
 
-        resetRtlProperties();
-        onRtlPropertiesChanged(LAYOUT_DIRECTION_DEFAULT);
         resetAccessibilityStateChanged();
     }
 
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 00723f3..dbbcde6 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -3620,8 +3620,6 @@
             childHasTransientStateChanged(view, false);
         }
 
-        view.resetRtlProperties();
-
         onViewRemoved(view);
 
         needGlobalAttributesUpdate(false);
@@ -5372,21 +5370,6 @@
      * @hide
      */
     @Override
-    public void resetRtlProperties() {
-        super.resetRtlProperties();
-        int count = getChildCount();
-        for (int i = 0; i < count; i++) {
-            final View child = getChildAt(i);
-            if (child.isLayoutDirectionInherited()) {
-                child.resetRtlProperties();
-            }
-        }
-    }
-
-    /**
-     * @hide
-     */
-    @Override
     public void resetResolvedLayoutDirection() {
         super.resetResolvedLayoutDirection();
 
diff --git a/core/java/android/view/VolumePanel.java b/core/java/android/view/VolumePanel.java
index d7c7f46..001d020 100644
--- a/core/java/android/view/VolumePanel.java
+++ b/core/java/android/view/VolumePanel.java
@@ -302,6 +302,7 @@
         lp.type = LayoutParams.TYPE_VOLUME_OVERLAY;
         lp.width = LayoutParams.WRAP_CONTENT;
         lp.height = LayoutParams.WRAP_CONTENT;
+        lp.privateFlags |= LayoutParams.PRIVATE_FLAG_FORCE_SHOW_NAV_BAR;
         window.setAttributes(lp);
         window.addFlags(LayoutParams.FLAG_NOT_FOCUSABLE | LayoutParams.FLAG_NOT_TOUCH_MODAL
                 | LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH);
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 3b31ff6..6a67d8b 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -946,6 +946,13 @@
         public static final int PRIVATE_FLAG_SHOW_FOR_ALL_USERS = 0x00000010;
 
         /**
+         * Special flag for the volume overlay: force the window manager out of "hide nav bar"
+         * mode while the window is on screen.
+         *
+         * {@hide} */
+        public static final int PRIVATE_FLAG_FORCE_SHOW_NAV_BAR = 0x00000020;
+
+        /**
          * Control flags that are private to the platform.
          * @hide
          */
diff --git a/core/java/android/widget/CompoundButton.java b/core/java/android/widget/CompoundButton.java
index 421a324..452ad1b 100644
--- a/core/java/android/widget/CompoundButton.java
+++ b/core/java/android/widget/CompoundButton.java
@@ -248,6 +248,15 @@
         return padding;
     }
 
+    /**
+     * @hide
+     */
+    @Override
+    public int getHorizontalOffsetForDrawables() {
+        final Drawable buttonDrawable = mButtonDrawable;
+        return (buttonDrawable != null) ? buttonDrawable.getIntrinsicWidth() : 0;
+    }
+
     @Override
     protected void onDraw(Canvas canvas) {
         super.onDraw(canvas);
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index b1a44c5..30d022c 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -36,6 +36,8 @@
 import android.inputmethodservice.ExtractEditText;
 import android.os.Bundle;
 import android.os.Handler;
+import android.os.Message;
+import android.os.Messenger;
 import android.os.SystemClock;
 import android.provider.Settings;
 import android.text.DynamicLayout;
@@ -187,6 +189,8 @@
 
     private TextView mTextView;
 
+    private final UserDictionaryListener mUserDictionaryListener = new UserDictionaryListener();
+
     Editor(TextView textView) {
         mTextView = textView;
     }
@@ -291,6 +295,7 @@
         mErrorWasChanged = true;
 
         if (mError == null) {
+            setErrorIcon(null);
             if (mErrorPopup != null) {
                 if (mErrorPopup.isShowing()) {
                     mErrorPopup.dismiss();
@@ -299,21 +304,24 @@
                 mErrorPopup = null;
             }
 
-            setErrorIcon(null);
-        } else if (mTextView.isFocused()) {
-            showError();
+        } else {
             setErrorIcon(icon);
+            if (mTextView.isFocused()) {
+                showError();
+            }
         }
     }
 
     private void setErrorIcon(Drawable icon) {
-        final Drawables dr = mTextView.mDrawables;
-        if (dr != null) {
-            mTextView.setCompoundDrawables(dr.mDrawableLeft, dr.mDrawableTop, icon,
-                    dr.mDrawableBottom);
-        } else {
-            mTextView.setCompoundDrawables(null, null, icon, null);
+        Drawables dr = mTextView.mDrawables;
+        if (dr == null) {
+            mTextView.mDrawables = dr = new Drawables();
         }
+        dr.setErrorDrawable(icon, mTextView);
+
+        mTextView.resetResolvedDrawables();
+        mTextView.invalidate();
+        mTextView.requestLayout();
     }
 
     private void hideError() {
@@ -321,15 +329,13 @@
             if (mErrorPopup.isShowing()) {
                 mErrorPopup.dismiss();
             }
-
-            setErrorIcon(null);
         }
 
         mShowErrorAfterAttach = false;
     }
 
     /**
-     * Returns the Y offset to make the pointy top of the error point
+     * Returns the X offset to make the pointy top of the error point
      * at the middle of the error icon.
      */
     private int getErrorX() {
@@ -340,8 +346,23 @@
         final float scale = mTextView.getResources().getDisplayMetrics().density;
 
         final Drawables dr = mTextView.mDrawables;
-        return mTextView.getWidth() - mErrorPopup.getWidth() - mTextView.getPaddingRight() -
-                (dr != null ? dr.mDrawableSizeRight : 0) / 2 + (int) (25 * scale + 0.5f);
+
+        final int layoutDirection = mTextView.getLayoutDirection();
+        int errorX;
+        int offset;
+        switch (layoutDirection) {
+            default:
+            case View.LAYOUT_DIRECTION_LTR:
+                offset = - (dr != null ? dr.mDrawableSizeRight : 0) / 2 + (int) (25 * scale + 0.5f);
+                errorX = mTextView.getWidth() - mErrorPopup.getWidth() -
+                        mTextView.getPaddingRight() + offset;
+                break;
+            case View.LAYOUT_DIRECTION_RTL:
+                offset = (dr != null ? dr.mDrawableSizeLeft : 0) / 2 - (int) (25 * scale + 0.5f);
+                errorX = mTextView.getPaddingLeft() + offset;
+                break;
+        }
+        return errorX;
     }
 
     /**
@@ -358,16 +379,27 @@
                 mTextView.getCompoundPaddingBottom() - compoundPaddingTop;
 
         final Drawables dr = mTextView.mDrawables;
-        int icontop = compoundPaddingTop +
-                (vspace - (dr != null ? dr.mDrawableHeightRight : 0)) / 2;
+
+        final int layoutDirection = mTextView.getLayoutDirection();
+        int height;
+        switch (layoutDirection) {
+            default:
+            case View.LAYOUT_DIRECTION_LTR:
+                height = (dr != null ? dr.mDrawableHeightRight : 0);
+                break;
+            case View.LAYOUT_DIRECTION_RTL:
+                height = (dr != null ? dr.mDrawableHeightLeft : 0);
+                break;
+        }
+
+        int icontop = compoundPaddingTop + (vspace - height) / 2;
 
         /*
          * The "2" is the distance between the point and the top edge
          * of the background.
          */
         final float scale = mTextView.getResources().getDisplayMetrics().density;
-        return icontop + (dr != null ? dr.mDrawableHeightRight : 0) - mTextView.getHeight() -
-                (int) (2 * scale + 0.5f);
+        return icontop + height - mTextView.getHeight() - (int) (2 * scale + 0.5f);
     }
 
     void createInputContentTypeIfNeeded() {
@@ -2574,6 +2606,11 @@
                 Intent intent = new Intent(Settings.ACTION_USER_DICTIONARY_INSERT);
                 intent.putExtra("word", originalText);
                 intent.putExtra("locale", mTextView.getTextServicesLocale().toString());
+                // Put a listener to replace the original text with a word which the user
+                // modified in a user dictionary dialog.
+                mUserDictionaryListener.waitForUserDictionaryAdded(
+                        mTextView, originalText, spanStart, spanEnd);
+                intent.putExtra("listener", new Messenger(mUserDictionaryListener));
                 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
                 mTextView.getContext().startActivity(intent);
                 // There is no way to know if the word was indeed added. Re-check.
@@ -3726,7 +3763,7 @@
             super(v, width, height);
             mView = v;
             // Make sure the TextView has a background set as it will be used the first time it is
-            // shown and positionned. Initialized with below background, which should have
+            // shown and positioned. Initialized with below background, which should have
             // dimensions identical to the above version for this to work (and is more likely).
             mPopupInlineErrorBackgroundId = getResourceId(mPopupInlineErrorBackgroundId,
                     com.android.internal.R.styleable.Theme_errorMessageBackground);
@@ -3792,4 +3829,65 @@
         boolean mContentChanged;
         int mChangedStart, mChangedEnd, mChangedDelta;
     }
+
+    /**
+     * @hide
+     */
+    public static class UserDictionaryListener extends Handler {
+        public TextView mTextView;
+        public String mOriginalWord;
+        public int mWordStart;
+        public int mWordEnd;
+
+        public void waitForUserDictionaryAdded(
+                TextView tv, String originalWord, int spanStart, int spanEnd) {
+            mTextView = tv;
+            mOriginalWord = originalWord;
+            mWordStart = spanStart;
+            mWordEnd = spanEnd;
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch(msg.what) {
+                case 0: /* CODE_WORD_ADDED */
+                case 2: /* CODE_ALREADY_PRESENT */
+                    if (!(msg.obj instanceof Bundle)) {
+                        Log.w(TAG, "Illegal message. Abort handling onUserDictionaryAdded.");
+                        return;
+                    }
+                    final Bundle bundle = (Bundle)msg.obj;
+                    final String originalWord = bundle.getString("originalWord");
+                    final String addedWord = bundle.getString("word");
+                    onUserDictionaryAdded(originalWord, addedWord);
+                    return;
+                default:
+                    return;
+            }
+        }
+
+        private void onUserDictionaryAdded(String originalWord, String addedWord) {
+            if (TextUtils.isEmpty(mOriginalWord) || TextUtils.isEmpty(addedWord)) {
+                return;
+            }
+            if (mWordStart < 0 || mWordEnd >= mTextView.length()) {
+                return;
+            }
+            if (!mOriginalWord.equals(originalWord)) {
+                return;
+            }
+            if (originalWord.equals(addedWord)) {
+                return;
+            }
+            final Editable editable = (Editable) mTextView.getText();
+            final String currentWord = editable.toString().substring(mWordStart, mWordEnd);
+            if (!currentWord.equals(originalWord)) {
+                return;
+            }
+            mTextView.replaceText_internal(mWordStart, mWordEnd, addedWord);
+            // Move cursor at the end of the replaced word
+            final int newCursorPosition = mWordStart + addedWord.length();
+            mTextView.setCursorPosition_internal(newCursorPosition, newCursorPosition);
+        }
+    }
 }
diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java
index e52e84d..27fda24 100644
--- a/core/java/android/widget/RelativeLayout.java
+++ b/core/java/android/widget/RelativeLayout.java
@@ -369,10 +369,10 @@
         int width = 0;
         int height = 0;
 
-        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
-        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
-        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
-        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
+        final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
+        final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
+        final int widthSize = MeasureSpec.getSize(widthMeasureSpec);
+        final int heightSize = MeasureSpec.getSize(heightMeasureSpec);
 
         // Record our dimensions if they are known;
         if (widthMode != MeasureSpec.UNSPECIFIED) {
@@ -416,6 +416,42 @@
 
         View[] views = mSortedHorizontalChildren;
         int count = views.length;
+
+        // We need to know our size for doing the correct computation of positioning in RTL mode
+        if (isLayoutRtl() && (myWidth == -1 || isWrapContentWidth)) {
+            int w = getPaddingStart() + getPaddingEnd();
+            final int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
+            for (int i = 0; i < count; i++) {
+                View child = views[i];
+                if (child.getVisibility() != GONE) {
+                    LayoutParams params = (LayoutParams) child.getLayoutParams();
+                    // Would be similar to a call to measureChildHorizontal(child, params, -1, myHeight)
+                    // but we cannot change for now the behavior of measureChildHorizontal() for
+                    // taking care or a "-1" for "mywidth" so use here our own version of that code.
+                    int childHeightMeasureSpec;
+                    if (params.width == LayoutParams.MATCH_PARENT) {
+                        childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(myHeight, MeasureSpec.EXACTLY);
+                    } else {
+                        childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(myHeight, MeasureSpec.AT_MOST);
+                    }
+                    child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
+
+                    w += child.getMeasuredWidth();
+                    w += params.leftMargin + params.rightMargin;
+                }
+            }
+            if (myWidth == -1) {
+                // Easy case: "myWidth" was undefined before so use the width we have just computed
+                myWidth = w;
+            } else {
+                // "myWidth" was defined before, so take the min of it and the computed width if it
+                // is a non null one
+                if (w > 0) {
+                    myWidth = Math.min(myWidth, w);
+                }
+            }
+        }
+
         for (int i = 0; i < count; i++) {
             View child = views[i];
             if (child.getVisibility() != GONE) {
@@ -924,7 +960,7 @@
 
             // Find the first non-GONE view up the chain
             while (v.getVisibility() == View.GONE) {
-                rules = ((LayoutParams) v.getLayoutParams()).getRules();
+                rules = ((LayoutParams) v.getLayoutParams()).getRules(v.getLayoutDirection());
                 node = mGraph.mKeyNodes.get((rules[relation]));
                 if (node == null) return null;
                 v = node.view;
@@ -975,7 +1011,7 @@
     protected void onLayout(boolean changed, int l, int t, int r, int b) {
         //  The layout has actually already been performed and the positions
         //  cached.  Apply the cached values to the children.
-        int count = getChildCount();
+        final int count = getChildCount();
 
         for (int i = 0; i < count; i++) {
             View child = getChildAt(i);
diff --git a/core/java/android/widget/RemoteViewsAdapter.java b/core/java/android/widget/RemoteViewsAdapter.java
index e481702..aeee111 100644
--- a/core/java/android/widget/RemoteViewsAdapter.java
+++ b/core/java/android/widget/RemoteViewsAdapter.java
@@ -21,6 +21,7 @@
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedList;
+
 import android.appwidget.AppWidgetManager;
 import android.content.Context;
 import android.content.Intent;
@@ -29,9 +30,10 @@
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.Message;
+import android.os.Process;
 import android.os.RemoteException;
+import android.os.UserHandle;
 import android.util.Log;
-import android.util.Pair;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.View.MeasureSpec;
@@ -40,6 +42,7 @@
 
 import com.android.internal.widget.IRemoteViewsAdapterConnection;
 import com.android.internal.widget.IRemoteViewsFactory;
+import com.android.internal.widget.LockPatternUtils;
 
 /**
  * An adapter to a RemoteViewsService which fetches and caches RemoteViews
@@ -87,13 +90,15 @@
     private Handler mMainQueue;
 
     // We cache the FixedSizeRemoteViewsCaches across orientation. These are the related data
-    // structures;
-    private static final HashMap<Pair<Intent.FilterComparison, Integer>, FixedSizeRemoteViewsCache>
-            sCachedRemoteViewsCaches = new HashMap<Pair<Intent.FilterComparison, Integer>,
+    // structures; 
+    private static final HashMap<RemoteViewsCacheKey,
+            FixedSizeRemoteViewsCache> sCachedRemoteViewsCaches
+            = new HashMap<RemoteViewsCacheKey,
                     FixedSizeRemoteViewsCache>();
-    private static final HashMap<Pair<Intent.FilterComparison, Integer>, Runnable>
-            sRemoteViewsCacheRemoveRunnables = new HashMap<Pair<Intent.FilterComparison, Integer>,
-            Runnable>();
+    private static final HashMap<RemoteViewsCacheKey, Runnable>
+            sRemoteViewsCacheRemoveRunnables
+            = new HashMap<RemoteViewsCacheKey, Runnable>();
+
     private static HandlerThread sCacheRemovalThread;
     private static Handler sCacheRemovalQueue;
 
@@ -106,6 +111,8 @@
     // construction (happens when we have a cached FixedSizeRemoteViewsCache).
     private boolean mDataReady = false;
 
+    int mUserId;
+
     /**
      * An interface for the RemoteAdapter to notify other classes when adapters
      * are actually connected to/disconnected from their actual services.
@@ -146,8 +153,16 @@
         public synchronized void bind(Context context, int appWidgetId, Intent intent) {
             if (!mIsConnecting) {
                 try {
+                    RemoteViewsAdapter adapter;
                     final AppWidgetManager mgr = AppWidgetManager.getInstance(context);
-                    mgr.bindRemoteViewsService(appWidgetId, intent, asBinder());
+                    if (Process.myUid() == Process.SYSTEM_UID
+                            && (adapter = mAdapter.get()) != null) {
+                        mgr.bindRemoteViewsService(appWidgetId, intent, asBinder(),
+                                new UserHandle(adapter.mUserId));
+                    } else {
+                        mgr.bindRemoteViewsService(appWidgetId, intent, asBinder(),
+                                Process.myUserHandle());
+                    }
                     mIsConnecting = true;
                 } catch (Exception e) {
                     Log.e("RemoteViewsAdapterServiceConnection", "bind(): " + e.getMessage());
@@ -159,8 +174,15 @@
 
         public synchronized void unbind(Context context, int appWidgetId, Intent intent) {
             try {
+                RemoteViewsAdapter adapter;
                 final AppWidgetManager mgr = AppWidgetManager.getInstance(context);
-                mgr.unbindRemoteViewsService(appWidgetId, intent);
+                if (Process.myUid() == Process.SYSTEM_UID
+                        && (adapter = mAdapter.get()) != null) {
+                    mgr.unbindRemoteViewsService(appWidgetId, intent,
+                            new UserHandle(adapter.mUserId));
+                } else {
+                    mgr.unbindRemoteViewsService(appWidgetId, intent, Process.myUserHandle());
+                }
                 mIsConnecting = false;
             } catch (Exception e) {
                 Log.e("RemoteViewsAdapterServiceConnection", "unbind(): " + e.getMessage());
@@ -296,9 +318,13 @@
      */
     private class RemoteViewsFrameLayoutRefSet {
         private HashMap<Integer, LinkedList<RemoteViewsFrameLayout>> mReferences;
+        private HashMap<RemoteViewsFrameLayout, LinkedList<RemoteViewsFrameLayout>>
+                mViewToLinkedList;
 
         public RemoteViewsFrameLayoutRefSet() {
             mReferences = new HashMap<Integer, LinkedList<RemoteViewsFrameLayout>>();
+            mViewToLinkedList =
+                    new HashMap<RemoteViewsFrameLayout, LinkedList<RemoteViewsFrameLayout>>();
         }
 
         /**
@@ -315,6 +341,7 @@
                 refs = new LinkedList<RemoteViewsFrameLayout>();
                 mReferences.put(pos, refs);
             }
+            mViewToLinkedList.put(layout, refs);
 
             // Add the references to the list
             refs.add(layout);
@@ -333,21 +360,34 @@
                 final LinkedList<RemoteViewsFrameLayout> refs = mReferences.get(pos);
                 for (final RemoteViewsFrameLayout ref : refs) {
                     ref.onRemoteViewsLoaded(view, mRemoteViewsOnClickHandler);
+                    if (mViewToLinkedList.containsKey(ref)) {
+                        mViewToLinkedList.remove(ref);
+                    }
                 }
                 refs.clear();
-
                 // Remove this set from the original mapping
                 mReferences.remove(pos);
             }
         }
 
         /**
+         * We need to remove views from this set if they have been recycled by the AdapterView.
+         */
+        public void removeView(RemoteViewsFrameLayout rvfl) {
+            if (mViewToLinkedList.containsKey(rvfl)) {
+                mViewToLinkedList.get(rvfl).remove(rvfl);
+                mViewToLinkedList.remove(rvfl);
+            }
+        }
+
+        /**
          * Removes all references to all RemoteViewsFrameLayouts returned by the adapter.
          */
         public void clear() {
             // We currently just clear the references, and leave all the previous layouts returned
             // in their default state of the loading view.
             mReferences.clear();
+            mViewToLinkedList.clear();
         }
     }
 
@@ -751,6 +791,33 @@
         }
     }
 
+    static class RemoteViewsCacheKey {
+        final Intent.FilterComparison filter;
+        final int widgetId;
+        final int userId;
+
+        RemoteViewsCacheKey(Intent.FilterComparison filter, int widgetId, int userId) {
+            this.filter = filter;
+            this.widgetId = widgetId;
+            this.userId = userId;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (!(o instanceof RemoteViewsCacheKey)) {
+                return false;
+            }
+            RemoteViewsCacheKey other = (RemoteViewsCacheKey) o;
+            return other.filter.equals(filter) && other.widgetId == widgetId
+                    && other.userId == userId;
+        }
+
+        @Override
+        public int hashCode() {
+            return (filter == null ? 0 : filter.hashCode()) ^ (widgetId << 2) ^ (userId << 10);
+        }
+    }
+
     public RemoteViewsAdapter(Context context, Intent intent, RemoteAdapterConnectionCallback callback) {
         mContext = context;
         mIntent = intent;
@@ -761,6 +828,11 @@
         }
         mRequestedViews = new RemoteViewsFrameLayoutRefSet();
 
+        if (Process.myUid() == Process.SYSTEM_UID) {
+            mUserId = new LockPatternUtils(context).getCurrentUser();
+        } else {
+            mUserId = UserHandle.myUserId();
+        }
         // Strip the previously injected app widget id from service intent
         if (intent.hasExtra(RemoteViews.EXTRA_REMOTEADAPTER_APPWIDGET_ID)) {
             intent.removeExtra(RemoteViews.EXTRA_REMOTEADAPTER_APPWIDGET_ID);
@@ -782,8 +854,8 @@
         mCallback = new WeakReference<RemoteAdapterConnectionCallback>(callback);
         mServiceConnection = new RemoteViewsAdapterServiceConnection(this);
 
-        Pair<Intent.FilterComparison, Integer> key = new Pair<Intent.FilterComparison, Integer>
-                (new Intent.FilterComparison(mIntent), mAppWidgetId);
+        RemoteViewsCacheKey key = new RemoteViewsCacheKey(new Intent.FilterComparison(mIntent),
+                mAppWidgetId, mUserId);
 
         synchronized(sCachedRemoteViewsCaches) {
             if (sCachedRemoteViewsCaches.containsKey(key)) {
@@ -824,8 +896,8 @@
     }
 
     public void saveRemoteViewsCache() {
-        final Pair<Intent.FilterComparison, Integer> key = new Pair<Intent.FilterComparison,
-                Integer> (new Intent.FilterComparison(mIntent), mAppWidgetId);
+        final RemoteViewsCacheKey key = new RemoteViewsCacheKey(
+                new Intent.FilterComparison(mIntent), mAppWidgetId, mUserId);
 
         synchronized(sCachedRemoteViewsCaches) {
             // If we already have a remove runnable posted for this key, remove it.
@@ -947,6 +1019,7 @@
         long itemId = 0;
         try {
             remoteViews = factory.getViewAt(position);
+            remoteViews.setUser(new UserHandle(mUserId));
             itemId = factory.getItemId(position);
         } catch (RemoteException e) {
             Log.e(TAG, "Error in updateRemoteViews(" + position + "): " + e.getMessage());
@@ -1079,6 +1152,10 @@
             boolean isConnected = mServiceConnection.isConnected();
             boolean hasNewItems = false;
 
+            if (convertView != null && convertView instanceof RemoteViewsFrameLayout) {
+                mRequestedViews.removeView((RemoteViewsFrameLayout) convertView);
+            }
+
             if (!isInCache && !isConnected) {
                 // Requesting bind service will trigger a super.notifyDataSetChanged(), which will
                 // in turn trigger another request to getView()
diff --git a/core/java/android/widget/ShareActionProvider.java b/core/java/android/widget/ShareActionProvider.java
index 4045497..62afd2e 100644
--- a/core/java/android/widget/ShareActionProvider.java
+++ b/core/java/android/widget/ShareActionProvider.java
@@ -39,31 +39,26 @@
  * <p>
  * Here is how to use the action provider with custom backing file in a {@link MenuItem}:
  * </p>
- * <p>
  * <pre>
- * <code>
- *  // In Activity#onCreateOptionsMenu
- *  public boolean onCreateOptionsMenu(Menu menu) {
- *      // Get the menu item.
- *      MenuItem menuItem = menu.findItem(R.id.my_menu_item);
- *      // Get the provider and hold onto it to set/change the share intent.
- *      mShareActionProvider = (ShareActionProvider) menuItem.getActionProvider();
- *      // Set history different from the default before getting the action
- *      // view since a call to {@link MenuItem#getActionView() MenuItem.getActionView()} calls
- *      // {@link ActionProvider#onCreateActionView()} which uses the backing file name. Omit this
- *      // line if using the default share history file is desired.
- *      mShareActionProvider.setShareHistoryFileName("custom_share_history.xml");
- *      . . .
- *  }
+ * // In Activity#onCreateOptionsMenu
+ * public boolean onCreateOptionsMenu(Menu menu) {
+ *     // Get the menu item.
+ *     MenuItem menuItem = menu.findItem(R.id.my_menu_item);
+ *     // Get the provider and hold onto it to set/change the share intent.
+ *     mShareActionProvider = (ShareActionProvider) menuItem.getActionProvider();
+ *     // Set history different from the default before getting the action
+ *     // view since a call to {@link MenuItem#getActionView() MenuItem.getActionView()} calls
+ *     // {@link ActionProvider#onCreateActionView()} which uses the backing file name. Omit this
+ *     // line if using the default share history file is desired.
+ *     mShareActionProvider.setShareHistoryFileName("custom_share_history.xml");
+ *     . . .
+ * }
  *
- *  // Somewhere in the application.
- *  public void doShare(Intent shareIntent) {
- *      // When you want to share set the share intent.
- *      mShareActionProvider.setShareIntent(shareIntent);
- *  }
- * </pre>
- * </code>
- * </p>
+ * // Somewhere in the application.
+ * public void doShare(Intent shareIntent) {
+ *     // When you want to share set the share intent.
+ *     mShareActionProvider.setShareIntent(shareIntent);
+ * }</pre>
  * <p>
  * <strong>Note:</strong> While the sample snippet demonstrates how to use this provider
  * in the context of a menu item, the use of the provider is not limited to menu items.
@@ -245,9 +240,9 @@
      * call {@link android.app.Activity#invalidateOptionsMenu()} to recreate the
      * action view. You should <strong>not</strong> call
      * {@link android.app.Activity#invalidateOptionsMenu()} from
-     * {@link android.app.Activity#onCreateOptionsMenu(Menu)}."
-     * <p>
-     * <code>
+     * {@link android.app.Activity#onCreateOptionsMenu(Menu)}.
+     * </p>
+     * <pre>
      * private void doShare(Intent intent) {
      *     if (IMAGE.equals(intent.getMimeType())) {
      *         mShareActionProvider.setHistoryFileName(SHARE_IMAGE_HISTORY_FILE_NAME);
@@ -256,9 +251,7 @@
      *     }
      *     mShareActionProvider.setIntent(intent);
      *     invalidateOptionsMenu();
-     * }
-     * <code>
-     *
+     * }</pre>
      * @param shareHistoryFile The share history file name.
      */
     public void setShareHistoryFileName(String shareHistoryFile) {
@@ -269,16 +262,11 @@
     /**
      * Sets an intent with information about the share action. Here is a
      * sample for constructing a share intent:
-     * <p>
      * <pre>
-     * <code>
-     *  Intent shareIntent = new Intent(Intent.ACTION_SEND);
-     *  shareIntent.setType("image/*");
-     *  Uri uri = Uri.fromFile(new File(getFilesDir(), "foo.jpg"));
-     *  shareIntent.putExtra(Intent.EXTRA_STREAM, uri.toString());
-     * </pre>
-     * </code>
-     * </p>
+     * Intent shareIntent = new Intent(Intent.ACTION_SEND);
+     * shareIntent.setType("image/*");
+     * Uri uri = Uri.fromFile(new File(getFilesDir(), "foo.jpg"));
+     * shareIntent.putExtra(Intent.EXTRA_STREAM, uri.toString());</pre>
      *
      * @param shareIntent The share intent.
      *
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 5d90400..22bfadb 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -284,15 +284,144 @@
     private TextUtils.TruncateAt mEllipsize;
 
     static class Drawables {
+        final static int DRAWABLE_NONE = -1;
+        final static int DRAWABLE_RIGHT = 0;
+        final static int DRAWABLE_LEFT = 1;
+
         final Rect mCompoundRect = new Rect();
+
         Drawable mDrawableTop, mDrawableBottom, mDrawableLeft, mDrawableRight,
-                mDrawableStart, mDrawableEnd;
+                mDrawableStart, mDrawableEnd, mDrawableError, mDrawableTemp;
+
         int mDrawableSizeTop, mDrawableSizeBottom, mDrawableSizeLeft, mDrawableSizeRight,
-                mDrawableSizeStart, mDrawableSizeEnd;
+                mDrawableSizeStart, mDrawableSizeEnd, mDrawableSizeError, mDrawableSizeTemp;
+
         int mDrawableWidthTop, mDrawableWidthBottom, mDrawableHeightLeft, mDrawableHeightRight,
-                mDrawableHeightStart, mDrawableHeightEnd;
+                mDrawableHeightStart, mDrawableHeightEnd, mDrawableHeightError, mDrawableHeightTemp;
+
         int mDrawablePadding;
+
+        int mDrawableSaved = DRAWABLE_NONE;
+
+        public void resolveWithLayoutDirection(int layoutDirection) {
+            switch(layoutDirection) {
+                case LAYOUT_DIRECTION_RTL:
+                    if (mDrawableStart != null) {
+                        mDrawableRight = mDrawableStart;
+
+                        mDrawableSizeRight = mDrawableSizeStart;
+                        mDrawableHeightRight = mDrawableHeightStart;
+                    }
+                    if (mDrawableEnd != null) {
+                        mDrawableLeft = mDrawableEnd;
+
+                        mDrawableSizeLeft = mDrawableSizeEnd;
+                        mDrawableHeightLeft = mDrawableHeightEnd;
+                    }
+                    break;
+
+                case LAYOUT_DIRECTION_LTR:
+                default:
+                    if (mDrawableStart != null) {
+                        mDrawableLeft = mDrawableStart;
+
+                        mDrawableSizeLeft = mDrawableSizeStart;
+                        mDrawableHeightLeft = mDrawableHeightStart;
+                    }
+                    if (mDrawableEnd != null) {
+                        mDrawableRight = mDrawableEnd;
+
+                        mDrawableSizeRight = mDrawableSizeEnd;
+                        mDrawableHeightRight = mDrawableHeightEnd;
+                    }
+                    break;
+            }
+            applyErrorDrawableIfNeeded(layoutDirection);
+            updateDrawablesLayoutDirection(layoutDirection);
+        }
+
+        private void updateDrawablesLayoutDirection(int layoutDirection) {
+            if (mDrawableLeft != null) {
+                mDrawableLeft.setLayoutDirection(layoutDirection);
+            }
+            if (mDrawableRight != null) {
+                mDrawableRight.setLayoutDirection(layoutDirection);
+            }
+            if (mDrawableTop != null) {
+                mDrawableTop.setLayoutDirection(layoutDirection);
+            }
+            if (mDrawableBottom != null) {
+                mDrawableBottom.setLayoutDirection(layoutDirection);
+            }
+        }
+
+        public void setErrorDrawable(Drawable dr, TextView tv) {
+            if (mDrawableError != dr && mDrawableError != null) {
+                mDrawableError.setCallback(null);
+            }
+            mDrawableError = dr;
+
+            final Rect compoundRect = mCompoundRect;
+            int[] state = tv.getDrawableState();
+
+            if (mDrawableError != null) {
+                mDrawableError.setState(state);
+                mDrawableError.copyBounds(compoundRect);
+                mDrawableError.setCallback(tv);
+                mDrawableSizeError = compoundRect.width();
+                mDrawableHeightError = compoundRect.height();
+            } else {
+                mDrawableSizeError = mDrawableHeightError = 0;
+            }
+        }
+
+        private void applyErrorDrawableIfNeeded(int layoutDirection) {
+            // first restore the initial state if needed
+            switch (mDrawableSaved) {
+                case DRAWABLE_LEFT:
+                    mDrawableLeft = mDrawableTemp;
+                    mDrawableSizeLeft = mDrawableSizeTemp;
+                    mDrawableHeightLeft = mDrawableHeightTemp;
+                    break;
+                case DRAWABLE_RIGHT:
+                    mDrawableRight = mDrawableTemp;
+                    mDrawableSizeRight = mDrawableSizeTemp;
+                    mDrawableHeightRight = mDrawableHeightTemp;
+                    break;
+                case DRAWABLE_NONE:
+                default:
+            }
+            // then, if needed, assign the Error drawable to the correct location
+            if (mDrawableError != null) {
+                switch(layoutDirection) {
+                    case LAYOUT_DIRECTION_RTL:
+                        mDrawableSaved = DRAWABLE_LEFT;
+
+                        mDrawableTemp = mDrawableLeft;
+                        mDrawableSizeTemp = mDrawableSizeLeft;
+                        mDrawableHeightTemp = mDrawableHeightLeft;
+
+                        mDrawableLeft = mDrawableError;
+                        mDrawableSizeLeft = mDrawableSizeError;
+                        mDrawableHeightLeft = mDrawableHeightError;
+                        break;
+                    case LAYOUT_DIRECTION_LTR:
+                    default:
+                        mDrawableSaved = DRAWABLE_RIGHT;
+
+                        mDrawableTemp = mDrawableRight;
+                        mDrawableSizeTemp = mDrawableSizeRight;
+                        mDrawableHeightTemp = mDrawableHeightRight;
+
+                        mDrawableRight = mDrawableError;
+                        mDrawableSizeRight = mDrawableSizeError;
+                        mDrawableHeightRight = mDrawableHeightError;
+                        break;
+                }
+            }
+        }
     }
+
     Drawables mDrawables;
 
     private CharWrapper mCharWrapper;
@@ -4734,6 +4863,13 @@
         return highlight;
     }
 
+    /**
+     * @hide
+     */
+    public int getHorizontalOffsetForDrawables() {
+        return 0;
+    }
+
     @Override
     protected void onDraw(Canvas canvas) {
         restartMarqueeIfNeeded();
@@ -4751,6 +4887,10 @@
         final int left = mLeft;
         final int bottom = mBottom;
         final int top = mTop;
+        final boolean isLayoutRtl = isLayoutRtl();
+        final int offset = getHorizontalOffsetForDrawables();
+        final int leftOffset = isLayoutRtl ? 0 : offset;
+        final int rightOffset = isLayoutRtl ? offset : 0 ;
 
         final Drawables dr = mDrawables;
         if (dr != null) {
@@ -4766,7 +4906,7 @@
             // Make sure to update invalidateDrawable() when changing this code.
             if (dr.mDrawableLeft != null) {
                 canvas.save();
-                canvas.translate(scrollX + mPaddingLeft,
+                canvas.translate(scrollX + mPaddingLeft + leftOffset,
                                  scrollY + compoundPaddingTop +
                                  (vspace - dr.mDrawableHeightLeft) / 2);
                 dr.mDrawableLeft.draw(canvas);
@@ -4777,7 +4917,8 @@
             // Make sure to update invalidateDrawable() when changing this code.
             if (dr.mDrawableRight != null) {
                 canvas.save();
-                canvas.translate(scrollX + right - left - mPaddingRight - dr.mDrawableSizeRight,
+                canvas.translate(scrollX + right - left - mPaddingRight
+                        - dr.mDrawableSizeRight - rightOffset,
                          scrollY + compoundPaddingTop + (vspace - dr.mDrawableHeightRight) / 2);
                 dr.mDrawableRight.draw(canvas);
                 canvas.restore();
@@ -4862,8 +5003,6 @@
         }
         canvas.translate(compoundPaddingLeft, extendedPaddingTop + voffsetText);
 
-        final boolean isLayoutRtl = isLayoutRtl();
-
         final int layoutDirection = getLayoutDirection();
         final int absoluteGravity = Gravity.getAbsoluteGravity(mGravity, layoutDirection);
         if (mEllipsize == TextUtils.TruncateAt.MARQUEE &&
@@ -8229,9 +8368,8 @@
 
     TextDirectionHeuristic getTextDirectionHeuristic() {
         if (hasPasswordTransformationMethod()) {
-            // TODO: take care of the content direction to show the password text and dots justified
-            // to the left or to the right
-            return TextDirectionHeuristics.LOCALE;
+            // passwords fields should be LTR
+            return TextDirectionHeuristics.LTR;
         }
 
         // Always need to resolve layout direction first
@@ -8264,63 +8402,10 @@
             return;
         }
         mLastLayoutDirection = layoutDirection;
-        // No drawable to resolve
-        if (mDrawables == null) {
-            return;
-        }
-        // No relative drawable to resolve
-        if (mDrawables.mDrawableStart == null && mDrawables.mDrawableEnd == null) {
-            return;
-        }
 
-        Drawables dr = mDrawables;
-        switch(layoutDirection) {
-            case LAYOUT_DIRECTION_RTL:
-                if (dr.mDrawableStart != null) {
-                    dr.mDrawableRight = dr.mDrawableStart;
-
-                    dr.mDrawableSizeRight = dr.mDrawableSizeStart;
-                    dr.mDrawableHeightRight = dr.mDrawableHeightStart;
-                }
-                if (dr.mDrawableEnd != null) {
-                    dr.mDrawableLeft = dr.mDrawableEnd;
-
-                    dr.mDrawableSizeLeft = dr.mDrawableSizeEnd;
-                    dr.mDrawableHeightLeft = dr.mDrawableHeightEnd;
-                }
-                break;
-
-            case LAYOUT_DIRECTION_LTR:
-            default:
-                if (dr.mDrawableStart != null) {
-                    dr.mDrawableLeft = dr.mDrawableStart;
-
-                    dr.mDrawableSizeLeft = dr.mDrawableSizeStart;
-                    dr.mDrawableHeightLeft = dr.mDrawableHeightStart;
-                }
-                if (dr.mDrawableEnd != null) {
-                    dr.mDrawableRight = dr.mDrawableEnd;
-
-                    dr.mDrawableSizeRight = dr.mDrawableSizeEnd;
-                    dr.mDrawableHeightRight = dr.mDrawableHeightEnd;
-                }
-                break;
-        }
-        updateDrawablesLayoutDirection(dr, layoutDirection);
-    }
-
-    private void updateDrawablesLayoutDirection(Drawables dr, int layoutDirection) {
-        if (dr.mDrawableLeft != null) {
-            dr.mDrawableLeft.setLayoutDirection(layoutDirection);
-        }
-        if (dr.mDrawableRight != null) {
-            dr.mDrawableRight.setLayoutDirection(layoutDirection);
-        }
-        if (dr.mDrawableTop != null) {
-            dr.mDrawableTop.setLayoutDirection(layoutDirection);
-        }
-        if (dr.mDrawableBottom != null) {
-            dr.mDrawableBottom.setLayoutDirection(layoutDirection);
+        // Resolve drawables
+        if (mDrawables != null) {
+            mDrawables.resolveWithLayoutDirection(layoutDirection);
         }
     }
 
@@ -8328,6 +8413,7 @@
      * @hide
      */
     protected void resetResolvedDrawables() {
+        super.resetResolvedDrawables();
         mLastLayoutDirection = -1;
     }
 
diff --git a/core/java/android/widget/Toast.java b/core/java/android/widget/Toast.java
index 485bd37..1d85126 100644
--- a/core/java/android/widget/Toast.java
+++ b/core/java/android/widget/Toast.java
@@ -374,8 +374,11 @@
                 // remove the old view if necessary
                 handleHide();
                 mView = mNextView;
-                mWM = (WindowManager)mView.getContext().getApplicationContext()
-                        .getSystemService(Context.WINDOW_SERVICE);
+                Context context = mView.getContext().getApplicationContext();
+                if (context == null) {
+                    context = mView.getContext();
+                }
+                mWM = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
                 // We can resolve the Gravity here by using the Locale for getting
                 // the layout direction
                 final Configuration config = mView.getContext().getResources().getConfiguration();
diff --git a/core/java/android/widget/VideoView.java b/core/java/android/widget/VideoView.java
index 7c8196d..329b0df 100644
--- a/core/java/android/widget/VideoView.java
+++ b/core/java/android/widget/VideoView.java
@@ -54,7 +54,6 @@
     // settable by the client
     private Uri         mUri;
     private Map<String, String> mHeaders;
-    private int         mDuration;
 
     // all possible internal states
     private static final int STATE_ERROR              = -1;
@@ -229,7 +228,6 @@
             mMediaPlayer = new MediaPlayer();
             mMediaPlayer.setOnPreparedListener(mPreparedListener);
             mMediaPlayer.setOnVideoSizeChangedListener(mSizeChangedListener);
-            mDuration = -1;
             mMediaPlayer.setOnCompletionListener(mCompletionListener);
             mMediaPlayer.setOnErrorListener(mErrorListener);
             mMediaPlayer.setOnInfoListener(mOnInfoListener);
@@ -608,17 +606,12 @@
         openVideo();
     }
 
-    // cache duration as mDuration for faster access
     public int getDuration() {
         if (isInPlaybackState()) {
-            if (mDuration > 0) {
-                return mDuration;
-            }
-            mDuration = mMediaPlayer.getDuration();
-            return mDuration;
+            return mMediaPlayer.getDuration();
         }
-        mDuration = -1;
-        return mDuration;
+
+        return -1;
     }
 
     public int getCurrentPosition() {
diff --git a/core/java/com/android/internal/annotations/GuardedBy.java b/core/java/com/android/internal/annotations/GuardedBy.java
new file mode 100644
index 0000000..fc61945
--- /dev/null
+++ b/core/java/com/android/internal/annotations/GuardedBy.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation type used to mark a method or field that can only be accessed when
+ * holding the referenced lock.
+ */
+@Target({ ElementType.FIELD, ElementType.METHOD })
+@Retention(RetentionPolicy.CLASS)
+public @interface GuardedBy {
+    String value();
+}
diff --git a/core/java/com/android/internal/annotations/Immutable.java b/core/java/com/android/internal/annotations/Immutable.java
new file mode 100644
index 0000000..b424275
--- /dev/null
+++ b/core/java/com/android/internal/annotations/Immutable.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation type used to mark a class which is immutable.
+ */
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.CLASS)
+public @interface Immutable {
+}
diff --git a/core/java/com/android/internal/annotations/VisibleForTesting.java b/core/java/com/android/internal/annotations/VisibleForTesting.java
new file mode 100644
index 0000000..bc3121c
--- /dev/null
+++ b/core/java/com/android/internal/annotations/VisibleForTesting.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.annotations;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Denotes that the class, method or field has its visibility relaxed so
+ * that unit tests can access it.
+ * <p/>
+ * The <code>visibility</code> argument can be used to specific what the original
+ * visibility should have been if it had not been made public or package-private for testing.
+ * The default is to consider the element private.
+ */
+@Retention(RetentionPolicy.SOURCE)
+public @interface VisibleForTesting {
+    /**
+     * Intended visibility if the element had not been made public or package-private for
+     * testing.
+     */
+    enum Visibility {
+        /** The element should be considered protected. */
+        PROTECTED,
+        /** The element should be considered package-private. */
+        PACKAGE,
+        /** The element should be considered private. */
+        PRIVATE
+    }
+
+    /**
+     * Intended visibility if the element had not been made public or package-private for testing.
+     * If not specified, one should assume the element originally intended to be private.
+     */
+    Visibility visibility() default Visibility.PRIVATE;
+}
diff --git a/core/java/com/android/internal/app/ActionBarImpl.java b/core/java/com/android/internal/app/ActionBarImpl.java
index 46478ca..f041f07 100644
--- a/core/java/com/android/internal/app/ActionBarImpl.java
+++ b/core/java/com/android/internal/app/ActionBarImpl.java
@@ -801,6 +801,11 @@
         return mThemedContext;
     }
     
+    @Override
+    public boolean isTitleTruncated() {
+        return mActionView != null && mActionView.isTitleTruncated();
+    }
+
     /**
      * @hide 
      */
diff --git a/core/java/com/android/internal/app/MediaRouteChooserDialogFragment.java b/core/java/com/android/internal/app/MediaRouteChooserDialogFragment.java
index 386f387..2bc80ff 100644
--- a/core/java/com/android/internal/app/MediaRouteChooserDialogFragment.java
+++ b/core/java/com/android/internal/app/MediaRouteChooserDialogFragment.java
@@ -136,13 +136,14 @@
         if (mRouter == null) return;
 
         final RouteInfo selectedRoute = mRouter.getSelectedRoute(mRouteTypes);
-        mVolumeIcon.setImageResource(
+        mVolumeIcon.setImageResource(selectedRoute == null ||
                 selectedRoute.getPlaybackType() == RouteInfo.PLAYBACK_TYPE_LOCAL ?
                 R.drawable.ic_audio_vol : R.drawable.ic_media_route_on_holo_dark);
 
         mIgnoreSliderVolumeChanges = true;
 
-        if (selectedRoute.getVolumeHandling() == RouteInfo.PLAYBACK_VOLUME_FIXED) {
+        if (selectedRoute == null ||
+                selectedRoute.getVolumeHandling() == RouteInfo.PLAYBACK_VOLUME_FIXED) {
             // Disable the slider and show it at max volume.
             mVolumeSlider.setMax(1);
             mVolumeSlider.setProgress(1);
@@ -160,7 +161,8 @@
         if (mIgnoreSliderVolumeChanges) return;
 
         final RouteInfo selectedRoute = mRouter.getSelectedRoute(mRouteTypes);
-        if (selectedRoute.getVolumeHandling() == RouteInfo.PLAYBACK_VOLUME_VARIABLE) {
+        if (selectedRoute != null &&
+                selectedRoute.getVolumeHandling() == RouteInfo.PLAYBACK_VOLUME_VARIABLE) {
             final int maxVolume = selectedRoute.getVolumeMax();
             newValue = Math.max(0, Math.min(newValue, maxVolume));
             selectedRoute.requestSetVolume(newValue);
@@ -652,14 +654,19 @@
         
         public boolean onKeyDown(int keyCode, KeyEvent event) {
             if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN && mVolumeSlider.isEnabled()) {
-                mRouter.getSelectedRoute(mRouteTypes).requestUpdateVolume(-1);
-                return true;
+                final RouteInfo selectedRoute = mRouter.getSelectedRoute(mRouteTypes);
+                if (selectedRoute != null) {
+                    selectedRoute.requestUpdateVolume(-1);
+                    return true;
+                }
             } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP && mVolumeSlider.isEnabled()) {
-                mRouter.getSelectedRoute(mRouteTypes).requestUpdateVolume(1);
-                return true;
-            } else {
-                return super.onKeyDown(keyCode, event);
+                final RouteInfo selectedRoute = mRouter.getSelectedRoute(mRouteTypes);
+                if (selectedRoute != null) {
+                    mRouter.getSelectedRoute(mRouteTypes).requestUpdateVolume(1);
+                    return true;
+                }
             }
+            return super.onKeyDown(keyCode, event);
         }
 
         public boolean onKeyUp(int keyCode, KeyEvent event) {
diff --git a/core/java/com/android/internal/appwidget/IAppWidgetService.aidl b/core/java/com/android/internal/appwidget/IAppWidgetService.aidl
index cfb16fa..e685e63 100644
--- a/core/java/com/android/internal/appwidget/IAppWidgetService.aidl
+++ b/core/java/com/android/internal/appwidget/IAppWidgetService.aidl
@@ -32,12 +32,16 @@
     //
     int[] startListening(IAppWidgetHost host, String packageName, int hostId,
             out List<RemoteViews> updatedViews);
+    int[] startListeningAsUser(IAppWidgetHost host, String packageName, int hostId,
+            out List<RemoteViews> updatedViews, int userId);
     void stopListening(int hostId);
+    void stopListeningAsUser(int hostId, int userId);
     int allocateAppWidgetId(String packageName, int hostId);
     void deleteAppWidgetId(int appWidgetId);
     void deleteHost(int hostId);
     void deleteAllHosts();
     RemoteViews getAppWidgetViews(int appWidgetId);
+    int[] getAppWidgetIdsForHost(int hostId);
 
     //
     // for AppWidgetManager
@@ -48,15 +52,15 @@
     void partiallyUpdateAppWidgetIds(in int[] appWidgetIds, in RemoteViews views);
     void updateAppWidgetProvider(in ComponentName provider, in RemoteViews views);
     void notifyAppWidgetViewDataChanged(in int[] appWidgetIds, int viewId);
-    List<AppWidgetProviderInfo> getInstalledProviders();
+    List<AppWidgetProviderInfo> getInstalledProviders(int categoryFilter);
     AppWidgetProviderInfo getAppWidgetInfo(int appWidgetId);
     boolean hasBindAppWidgetPermission(in String packageName);
     void setBindAppWidgetPermission(in String packageName, in boolean permission);
     void bindAppWidgetId(int appWidgetId, in ComponentName provider, in Bundle options);
     boolean bindAppWidgetIdIfAllowed(
             in String packageName, int appWidgetId, in ComponentName provider, in Bundle options);
-    void bindRemoteViewsService(int appWidgetId, in Intent intent, in IBinder connection);
-    void unbindRemoteViewsService(int appWidgetId, in Intent intent);
+    void bindRemoteViewsService(int appWidgetId, in Intent intent, in IBinder connection, int userId);
+    void unbindRemoteViewsService(int appWidgetId, in Intent intent, int userId);
     int[] getAppWidgetIds(in ComponentName provider);
 
 }
diff --git a/core/java/com/android/internal/content/PackageHelper.java b/core/java/com/android/internal/content/PackageHelper.java
index c5e7d9d..1a4835b 100644
--- a/core/java/com/android/internal/content/PackageHelper.java
+++ b/core/java/com/android/internal/content/PackageHelper.java
@@ -51,7 +51,7 @@
     public static final int RECOMMEND_FAILED_INVALID_URI = -6;
     public static final int RECOMMEND_FAILED_VERSION_DOWNGRADE = -7;
 
-    private static final boolean localLOGV = true;
+    private static final boolean localLOGV = false;
     private static final String TAG = "PackageHelper";
     // App installation location settings values
     public static final int APP_INSTALL_AUTO = 0;
diff --git a/core/java/com/android/internal/net/NetworkStatsFactory.java b/core/java/com/android/internal/net/NetworkStatsFactory.java
index 8b222f0..c517a68 100644
--- a/core/java/com/android/internal/net/NetworkStatsFactory.java
+++ b/core/java/com/android/internal/net/NetworkStatsFactory.java
@@ -25,6 +25,7 @@
 import android.os.StrictMode;
 import android.os.SystemClock;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.ProcFileReader;
 
 import java.io.File;
@@ -53,7 +54,7 @@
         this(new File("/proc/"));
     }
 
-    // @VisibleForTesting
+    @VisibleForTesting
     public NetworkStatsFactory(File procRoot) {
         mStatsXtIfaceAll = new File(procRoot, "net/xt_qtaguid/iface_stat_all");
         mStatsXtIfaceFmt = new File(procRoot, "net/xt_qtaguid/iface_stat_fmt");
diff --git a/core/java/com/android/internal/util/LocalLog.java b/core/java/com/android/internal/util/LocalLog.java
new file mode 100644
index 0000000..f0e6171
--- /dev/null
+++ b/core/java/com/android/internal/util/LocalLog.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.util;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+
+import android.util.Slog;
+
+/**
+ * Helper class for logging serious issues, which also keeps a small
+ * snapshot of the logged events that can be printed later, such as part
+ * of a system service's dumpsys output.
+ * @hide
+ */
+public class LocalLog {
+    private final String mTag;
+    private final int mMaxLines = 20;
+    private final ArrayList<String> mLines = new ArrayList<String>(mMaxLines);
+
+    public LocalLog(String tag) {
+        mTag = tag;
+    }
+
+    public void w(String msg) {
+        synchronized (mLines) {
+            Slog.w(mTag, msg);
+            if (mLines.size() >= mMaxLines) {
+                mLines.remove(0);
+            }
+            mLines.add(msg);
+        }
+    }
+
+    public boolean dump(PrintWriter pw, String header, String prefix) {
+        synchronized (mLines) {
+            if (mLines.size() <= 0) {
+                return false;
+            }
+            if (header != null) {
+                pw.println(header);
+            }
+            for (int i=0; i<mLines.size(); i++) {
+                if (prefix != null) {
+                    pw.print(prefix);
+                }
+                pw.println(mLines.get(i));
+            }
+            return true;
+        }
+    }
+}
diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java
index 6fb459c..0f964b9 100644
--- a/core/java/com/android/internal/widget/ActionBarView.java
+++ b/core/java/com/android/internal/widget/ActionBarView.java
@@ -40,6 +40,7 @@
 import android.graphics.drawable.Drawable;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.text.Layout;
 import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.util.Log;
@@ -49,7 +50,6 @@
 import android.view.Menu;
 import android.view.MenuItem;
 import android.view.MotionEvent;
-import android.view.TouchDelegate;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.ViewParent;
@@ -83,7 +83,8 @@
             ActionBar.DISPLAY_USE_LOGO |
             ActionBar.DISPLAY_HOME_AS_UP |
             ActionBar.DISPLAY_SHOW_CUSTOM |
-            ActionBar.DISPLAY_SHOW_TITLE;
+            ActionBar.DISPLAY_SHOW_TITLE |
+            ActionBar.DISPLAY_TITLE_MULTIPLE_LINES;
 
     private static final int DEFAULT_CUSTOM_GRAVITY = Gravity.START | Gravity.CENTER_VERTICAL;
     
@@ -100,6 +101,7 @@
     private TextView mTitleView;
     private TextView mSubtitleView;
     private View mTitleUpView;
+    private ViewGroup mUpGoerFive;
 
     private Spinner mSpinner;
     private LinearLayout mListNavLayout;
@@ -120,6 +122,7 @@
     private boolean mIncludeTabs;
     private boolean mIsCollapsable;
     private boolean mIsCollapsed;
+    private boolean mWasHomeEnabled; // Was it enabled before action view expansion?
 
     private MenuBuilder mOptionsMenu;
     
@@ -137,10 +140,6 @@
 
     Window.Callback mWindowCallback;
 
-    private final Rect mTempRect = new Rect();
-    private int mMaxHomeSlop;
-    private static final int MAX_HOME_SLOP = 32; // dp
-
     private final AdapterView.OnItemSelectedListener mNavItemSelectedListener =
             new AdapterView.OnItemSelectedListener() {
         public void onItemSelected(AdapterView parent, View view, int position, long id) {
@@ -219,14 +218,25 @@
                 com.android.internal.R.styleable.ActionBar_homeLayout,
                 com.android.internal.R.layout.action_bar_home);
 
-        mHomeLayout = (HomeView) inflater.inflate(homeResId, this, false);
+        mUpGoerFive = (ViewGroup) inflater.inflate(
+                com.android.internal.R.layout.action_bar_up_container, this, false);
+        mHomeLayout = (HomeView) inflater.inflate(homeResId, mUpGoerFive, false);
 
-        mExpandedHomeLayout = (HomeView) inflater.inflate(homeResId, this, false);
+        mExpandedHomeLayout = (HomeView) inflater.inflate(homeResId, mUpGoerFive, false);
         mExpandedHomeLayout.setUp(true);
         mExpandedHomeLayout.setOnClickListener(mExpandedActionViewUpListener);
         mExpandedHomeLayout.setContentDescription(getResources().getText(
                 R.string.action_bar_up_description));
         
+        // This needs to highlight/be focusable on its own.
+        // TODO: Clean up the handoff between expanded/normal.
+        final Drawable upBackground = mUpGoerFive.getBackground();
+        if (upBackground != null) {
+            mExpandedHomeLayout.setBackground(upBackground.getConstantState().newDrawable());
+        }
+        mExpandedHomeLayout.setEnabled(true);
+        mExpandedHomeLayout.setFocusable(true);
+
         mTitleStyleRes = a.getResourceId(R.styleable.ActionBar_titleTextStyle, 0);
         mSubtitleStyleRes = a.getResourceId(R.styleable.ActionBar_subtitleTextStyle, 0);
         mProgressStyle = a.getResourceId(R.styleable.ActionBar_progressBarStyle, 0);
@@ -250,16 +260,14 @@
         a.recycle();
         
         mLogoNavItem = new ActionMenuItem(context, 0, android.R.id.home, 0, 0, mTitle);
-        mHomeLayout.setOnClickListener(mUpClickListener);
-        mHomeLayout.setClickable(true);
-        mHomeLayout.setFocusable(true);
+
+        mUpGoerFive.setOnClickListener(mUpClickListener);
+        mUpGoerFive.setClickable(true);
+        mUpGoerFive.setFocusable(true);
 
         if (getImportantForAccessibility() == View.IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
             setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
         }
-
-        mMaxHomeSlop =
-                (int) (MAX_HOME_SLOP * context.getResources().getDisplayMetrics().density + 0.5f);
     }
 
     @Override
@@ -269,8 +277,8 @@
         mTitleView = null;
         mSubtitleView = null;
         mTitleUpView = null;
-        if (mTitleLayout != null && mTitleLayout.getParent() == this) {
-            removeView(mTitleLayout);
+        if (mTitleLayout != null && mTitleLayout.getParent() == mUpGoerFive) {
+            mUpGoerFive.removeView(mTitleLayout);
         }
         mTitleLayout = null;
         if ((mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0) {
@@ -551,19 +559,34 @@
     }
 
     public void setHomeButtonEnabled(boolean enable) {
-        mHomeLayout.setEnabled(enable);
-        mHomeLayout.setFocusable(enable);
+        setHomeButtonEnabled(enable, true);
+    }
+
+    private void setHomeButtonEnabled(boolean enable, boolean recordState) {
+        if (recordState) {
+            mWasHomeEnabled = enable;
+        }
+
+        if (mExpandedActionView != null) {
+            // There's an action view currently showing and we want to keep the state
+            // configured for the action view at the moment. If we needed to record the
+            // new state for later we will have done so above.
+            return;
+        }
+
+        mUpGoerFive.setEnabled(enable);
+        mUpGoerFive.setFocusable(enable);
         // Make sure the home button has an accurate content description for accessibility.
         if (!enable) {
-            mHomeLayout.setContentDescription(null);
-            mHomeLayout.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
+            mUpGoerFive.setContentDescription(null);
+            mUpGoerFive.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
         } else {
-            mHomeLayout.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_AUTO);
+            mUpGoerFive.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_AUTO);
             if ((mDisplayOptions & ActionBar.DISPLAY_HOME_AS_UP) != 0) {
-                mHomeLayout.setContentDescription(mContext.getResources().getText(
+                mUpGoerFive.setContentDescription(mContext.getResources().getText(
                         R.string.action_bar_up_description));
             } else {
-                mHomeLayout.setContentDescription(mContext.getResources().getText(
+                mUpGoerFive.setContentDescription(mContext.getResources().getText(
                         R.string.action_bar_home_description));
             }
         }
@@ -600,7 +623,7 @@
                 if ((options & ActionBar.DISPLAY_SHOW_TITLE) != 0) {
                     initTitle();
                 } else {
-                    removeView(mTitleLayout);
+                    mUpGoerFive.removeView(mTitleLayout);
                 }
             }
 
@@ -608,8 +631,6 @@
                     (ActionBar.DISPLAY_HOME_AS_UP | ActionBar.DISPLAY_SHOW_HOME)) != 0) {
                 final boolean homeAsUp = (mDisplayOptions & ActionBar.DISPLAY_HOME_AS_UP) != 0;
                 mTitleUpView.setVisibility(!showHome ? (homeAsUp ? VISIBLE : INVISIBLE) : GONE);
-                mTitleLayout.setEnabled(!showHome && homeAsUp);
-                mTitleLayout.setClickable(!showHome && homeAsUp);
             }
 
             if ((flagsChanged & ActionBar.DISPLAY_SHOW_CUSTOM) != 0 && mCustomNavView != null) {
@@ -620,6 +641,17 @@
                 }
             }
             
+            if (mTitleLayout != null &&
+                    (flagsChanged & ActionBar.DISPLAY_TITLE_MULTIPLE_LINES) != 0) {
+                if ((options & ActionBar.DISPLAY_TITLE_MULTIPLE_LINES) != 0) {
+                    mTitleView.setSingleLine(false);
+                    mTitleView.setMaxLines(2);
+                } else {
+                    mTitleView.setMaxLines(1);
+                    mTitleView.setSingleLine(true);
+                }
+            }
+
             requestLayout();
         } else {
             invalidate();
@@ -753,7 +785,8 @@
     protected void onFinishInflate() {
         super.onFinishInflate();
 
-        addView(mHomeLayout);
+        mUpGoerFive.addView(mHomeLayout, 0);
+        addView(mUpGoerFive);
 
         if (mCustomNavView != null && (mDisplayOptions & ActionBar.DISPLAY_SHOW_CUSTOM) != 0) {
             final ViewParent parent = mCustomNavView.getParent();
@@ -775,8 +808,6 @@
             mSubtitleView = (TextView) mTitleLayout.findViewById(R.id.action_bar_subtitle);
             mTitleUpView = (View) mTitleLayout.findViewById(R.id.up);
 
-            mTitleLayout.setOnClickListener(mUpClickListener);
-
             if (mTitleStyleRes != 0) {
                 mTitleView.setTextAppearance(mContext, mTitleStyleRes);
             }
@@ -796,11 +827,9 @@
             final boolean showHome = (mDisplayOptions & ActionBar.DISPLAY_SHOW_HOME) != 0;
             final boolean showTitleUp = !showHome;
             mTitleUpView.setVisibility(showTitleUp ? (homeAsUp ? VISIBLE : INVISIBLE) : GONE);
-            mTitleLayout.setEnabled(homeAsUp && showTitleUp);
-            mTitleLayout.setClickable(homeAsUp && showTitleUp);
         }
 
-        addView(mTitleLayout);
+        mUpGoerFive.addView(mTitleLayout);
         if (mExpandedActionView != null ||
                 (TextUtils.isEmpty(mTitle) && TextUtils.isEmpty(mSubtitle))) {
             // Don't show while in expanded mode or with empty text
@@ -820,6 +849,28 @@
         return mIsCollapsed;
     }
 
+    /**
+     * @return True if any characters in the title were truncated
+     */
+    public boolean isTitleTruncated() {
+        if (mTitleView == null) {
+            return false;
+        }
+
+        final Layout titleLayout = mTitleView.getLayout();
+        if (titleLayout == null) {
+            return false;
+        }
+
+        final int lineCount = titleLayout.getLineCount();
+        for (int i = 0; i < lineCount; i++) {
+            if (titleLayout.getEllipsisCount(i) > 0) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         final int childCount = getChildCount();
@@ -828,7 +879,16 @@
             for (int i = 0; i < childCount; i++) {
                 final View child = getChildAt(i);
                 if (child.getVisibility() != GONE &&
-                        !(child == mMenuView && mMenuView.getChildCount() == 0)) {
+                        !(child == mMenuView && mMenuView.getChildCount() == 0) &&
+                        child != mUpGoerFive) {
+                    visibleChildren++;
+                }
+            }
+
+            final int upChildCount = mUpGoerFive.getChildCount();
+            for (int i = 0; i < upChildCount; i++) {
+                final View child = mUpGoerFive.getChildAt(i);
+                if (child.getVisibility() != GONE) {
                     visibleChildren++;
                 }
             }
@@ -872,7 +932,8 @@
 
         HomeView homeLayout = mExpandedActionView != null ? mExpandedHomeLayout : mHomeLayout;
 
-        if (homeLayout.getVisibility() != GONE) {
+        int homeWidth = 0;
+        if (homeLayout.getVisibility() != GONE && homeLayout.getParent() == mUpGoerFive) {
             final ViewGroup.LayoutParams lp = homeLayout.getLayoutParams();
             int homeWidthSpec;
             if (lp.width < 0) {
@@ -880,10 +941,18 @@
             } else {
                 homeWidthSpec = MeasureSpec.makeMeasureSpec(lp.width, MeasureSpec.EXACTLY);
             }
+
+            /*
+             * This is a little weird.
+             * We're only measuring the *home* affordance within the Up container here
+             * on purpose, because we want to give the available space to all other views before
+             * the title text. We'll remeasure the whole up container again later.
+             */
             homeLayout.measure(homeWidthSpec, exactHeightSpec);
-            final int homeWidth = homeLayout.getMeasuredWidth() + homeLayout.getStartOffset();
-            availableWidth = Math.max(0, availableWidth - homeWidth);
-            leftOfCenter = Math.max(0, availableWidth - homeWidth);
+            homeWidth = homeLayout.getMeasuredWidth();
+            final int homeOffsetWidth = homeWidth + homeLayout.getStartOffset();
+            availableWidth = Math.max(0, availableWidth - homeOffsetWidth);
+            leftOfCenter = Math.max(0, availableWidth - homeOffsetWidth);
         }
         
         if (mMenuView != null && mMenuView.getParent() == this) {
@@ -985,9 +1054,13 @@
             availableWidth -= horizontalMargin + customView.getMeasuredWidth();
         }
 
-        if (mExpandedActionView == null && showTitle) {
-            availableWidth = measureChildView(mTitleLayout, availableWidth,
-                    MeasureSpec.makeMeasureSpec(mContentHeight, MeasureSpec.EXACTLY), 0);
+        /*
+         * Measure the whole up container now, allowing for the full home+title sections.
+         * (This will re-measure the home view.)
+         */
+        availableWidth = measureChildView(mUpGoerFive, availableWidth + homeWidth,
+                MeasureSpec.makeMeasureSpec(mContentHeight, MeasureSpec.EXACTLY), 0);
+        if (mTitleLayout != null) {
             leftOfCenter = Math.max(0, leftOfCenter - mTitleLayout.getMeasuredWidth());
         }
 
@@ -1034,24 +1107,17 @@
         final int y = getPaddingTop();
 
         HomeView homeLayout = mExpandedActionView != null ? mExpandedHomeLayout : mHomeLayout;
-        boolean needsTouchDelegate = false;
-        int homeSlop = mMaxHomeSlop;
-        int homeRight = 0;
-        if (homeLayout.getVisibility() != GONE) {
-            final int startOffset = homeLayout.getStartOffset();
-            x += positionChild(homeLayout,
-                            next(x, startOffset, isLayoutRtl), y, contentHeight, isLayoutRtl);
-            x = next(x, startOffset, isLayoutRtl);
-            needsTouchDelegate = homeLayout == mHomeLayout;
-            homeRight = x;
-        }
+        final int startOffset = homeLayout.getVisibility() != GONE &&
+                homeLayout.getParent() == mUpGoerFive ? homeLayout.getStartOffset() : 0;
+
+        // Position the up container based on where the edge of the home layout should go.
+        x += positionChild(mUpGoerFive,
+                next(x, startOffset, isLayoutRtl), y, contentHeight, isLayoutRtl);
+        x = next(x, startOffset, isLayoutRtl);
 
         if (mExpandedActionView == null) {
             final boolean showTitle = mTitleLayout != null && mTitleLayout.getVisibility() != GONE &&
                     (mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0;
-            if (showTitle) {
-                x += positionChild(mTitleLayout, x, y, contentHeight, isLayoutRtl);
-            }
 
             switch (mNavigationMode) {
                 case ActionBar.NAVIGATION_MODE_STANDARD:
@@ -1061,7 +1127,6 @@
                         if (showTitle) {
                             x = next(x, mItemPadding, isLayoutRtl);
                         }
-                        homeSlop = Math.min(homeSlop, Math.max(x - homeRight, 0));
                         x += positionChild(mListNavLayout, x, y, contentHeight, isLayoutRtl);
                         x = next(x, mItemPadding, isLayoutRtl);
                     }
@@ -1069,7 +1134,6 @@
                 case ActionBar.NAVIGATION_MODE_TABS:
                     if (mTabScrollView != null) {
                         if (showTitle) x = next(x, mItemPadding, isLayoutRtl);
-                        homeSlop = Math.min(homeSlop, Math.max(x - homeRight, 0));
                         x += positionChild(mTabScrollView, x, y, contentHeight, isLayoutRtl);
                         x = next(x, mItemPadding, isLayoutRtl);
                     }
@@ -1174,7 +1238,6 @@
             final int customWidth = customView.getMeasuredWidth();
             customView.layout(xpos, ypos, xpos + customWidth,
                     ypos + customView.getMeasuredHeight());
-            homeSlop = Math.min(homeSlop, Math.max(xpos - homeRight, 0));
             x = next(x, customWidth, isLayoutRtl);
         }
 
@@ -1184,14 +1247,6 @@
             mProgressView.layout(mProgressBarPadding, -halfProgressHeight,
                     mProgressBarPadding + mProgressView.getMeasuredWidth(), halfProgressHeight);
         }
-
-        if (needsTouchDelegate) {
-            mTempRect.set(homeLayout.getLeft(), homeLayout.getTop(),
-                    homeLayout.getRight() + homeSlop, homeLayout.getBottom());
-            setTouchDelegate(new TouchDelegate(mTempRect, homeLayout));
-        } else {
-            setTouchDelegate(null);
-        }
     }
 
     @Override
@@ -1491,14 +1546,15 @@
             if (mExpandedActionView.getParent() != ActionBarView.this) {
                 addView(mExpandedActionView);
             }
-            if (mExpandedHomeLayout.getParent() != ActionBarView.this) {
-                addView(mExpandedHomeLayout);
+            if (mExpandedHomeLayout.getParent() != mUpGoerFive) {
+                mUpGoerFive.addView(mExpandedHomeLayout);
             }
             mHomeLayout.setVisibility(GONE);
             if (mTitleLayout != null) mTitleLayout.setVisibility(GONE);
             if (mTabScrollView != null) mTabScrollView.setVisibility(GONE);
             if (mSpinner != null) mSpinner.setVisibility(GONE);
             if (mCustomNavView != null) mCustomNavView.setVisibility(GONE);
+            setHomeButtonEnabled(false, false);
             requestLayout();
             item.setActionViewExpanded(true);
 
@@ -1518,7 +1574,7 @@
             }
 
             removeView(mExpandedActionView);
-            removeView(mExpandedHomeLayout);
+            mUpGoerFive.removeView(mExpandedHomeLayout);
             mExpandedActionView = null;
             if ((mDisplayOptions & ActionBar.DISPLAY_SHOW_HOME) != 0) {
                 mHomeLayout.setVisibility(VISIBLE);
@@ -1541,6 +1597,7 @@
             }
             mExpandedHomeLayout.setIcon(null);
             mCurrentExpandedItem = null;
+            setHomeButtonEnabled(mWasHomeEnabled); // Set by expandItemActionView above
             requestLayout();
             item.setActionViewExpanded(false);
 
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index 75fef24..907b52a 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -24,7 +24,6 @@
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.os.Binder;
-import android.os.Bundle;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -54,8 +53,6 @@
  */
 public class LockPatternUtils {
 
-    private static final String OPTION_ENABLE_FACELOCK = "enable_facelock";
-
     private static final String TAG = "LockPatternUtils";
 
     /**
@@ -116,16 +113,6 @@
     public static final String KEYGUARD_SHOW_APPWIDGET = "showappwidget";
 
     /**
-     * Options used to lock the device upon user switch.
-     */
-    public static final Bundle USER_SWITCH_LOCK_OPTIONS = new Bundle();
-
-    static {
-        USER_SWITCH_LOCK_OPTIONS.putBoolean(KEYGUARD_SHOW_USER_SWITCHER, true);
-        USER_SWITCH_LOCK_OPTIONS.putBoolean(KEYGUARD_SHOW_SECURITY_CHALLENGE, true);
-    }
-
-    /**
      * The bit in LOCK_BIOMETRIC_WEAK_FLAGS to be used to indicate whether liveliness should
      * be used
      */
diff --git a/core/jni/android_net_wifi_Wifi.cpp b/core/jni/android_net_wifi_Wifi.cpp
index e7c4c23..9537ac4 100644
--- a/core/jni/android_net_wifi_Wifi.cpp
+++ b/core/jni/android_net_wifi_Wifi.cpp
@@ -122,9 +122,9 @@
     return (jboolean)(::wifi_start_supplicant(p2pSupported) == 0);
 }
 
-static jboolean android_net_wifi_killSupplicant(JNIEnv* env, jobject)
+static jboolean android_net_wifi_killSupplicant(JNIEnv* env, jobject, jboolean p2pSupported)
 {
-    return (jboolean)(::wifi_stop_supplicant() == 0);
+    return (jboolean)(::wifi_stop_supplicant(p2pSupported) == 0);
 }
 
 static jboolean android_net_wifi_connectToSupplicant(JNIEnv* env, jobject, jstring jIface)
@@ -204,7 +204,7 @@
     { "isDriverLoaded", "()Z",  (void *)android_net_wifi_isDriverLoaded },
     { "unloadDriver", "()Z",  (void *)android_net_wifi_unloadDriver },
     { "startSupplicant", "(Z)Z",  (void *)android_net_wifi_startSupplicant },
-    { "killSupplicant", "()Z",  (void *)android_net_wifi_killSupplicant },
+    { "killSupplicant", "(Z)Z",  (void *)android_net_wifi_killSupplicant },
     { "connectToSupplicant", "(Ljava/lang/String;)Z",
             (void *)android_net_wifi_connectToSupplicant },
     { "closeSupplicantConnection", "(Ljava/lang/String;)V",
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 89c8c36..2a357af 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -143,6 +143,30 @@
 
     <protected-broadcast android:name="android.intent.action.DREAMING_STARTED" />
     <protected-broadcast android:name="android.intent.action.DREAMING_STOPPED" />
+    <protected-broadcast android:name="android.intent.action.ANY_DATA_STATE" />
+
+    <protected-broadcast android:name="com.android.server.WifiManager.action.START_SCAN" />
+    <protected-broadcast android:name="com.android.server.WifiManager.action.DELAYED_DRIVER_STOP" />
+    <protected-broadcast android:name="android.net.wifi.WIFI_STATE_CHANGED" />
+    <protected-broadcast android:name="android.net.wifi.WIFI_AP_STATE_CHANGED" />
+    <protected-broadcast android:name="android.net.wifi.SCAN_RESULTS" />
+    <protected-broadcast android:name="android.net.wifi.RSSI_CHANGED" />
+    <protected-broadcast android:name="android.net.wifi.STATE_CHANGE" />
+    <protected-broadcast android:name="android.net.wifi.LINK_CONFIGURATION_CHANGED" />
+    <protected-broadcast android:name="android.net.wifi.CONFIGURED_NETWORKS_CHANGE" />
+    <protected-broadcast android:name="android.net.wifi.supplicant.CONNECTION_CHANGE" />
+    <protected-broadcast android:name="android.net.wifi.supplicant.STATE_CHANGE" />
+    <protected-broadcast android:name="android.net.wifi.p2p.STATE_CHANGED" />
+    <protected-broadcast android:name="android.net.wifi.p2p.DISCOVERY_STATE_CHANGE" />
+    <protected-broadcast android:name="android.net.wifi.p2p.THIS_DEVICE_CHANGED" />
+    <protected-broadcast android:name="android.net.wifi.p2p.PEERS_CHANGED" />
+    <protected-broadcast android:name="android.net.wifi.p2p.CONNECTION_STATE_CHANGE" />
+    <protected-broadcast android:name="android.net.wifi.p2p.PERSISTENT_GROUPS_CHANGED" />
+    <protected-broadcast android:name="android.net.conn.TETHER_STATE_CHANGED" />
+    <protected-broadcast android:name="android.net.conn.INET_CONDITION_ACTION" />
+
+
+
 
     <protected-broadcast android:name="android.intent.action.ANY_DATA_STATE" />
 
diff --git a/core/res/res/drawable-hdpi/dialog_bottom_holo_dark.9.png b/core/res/res/drawable-hdpi/dialog_bottom_holo_dark.9.png
index 9eaf9d5..b23740c 100644
--- a/core/res/res/drawable-hdpi/dialog_bottom_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/dialog_bottom_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dialog_bottom_holo_light.9.png b/core/res/res/drawable-hdpi/dialog_bottom_holo_light.9.png
index 55a125e..44803d7 100644
--- a/core/res/res/drawable-hdpi/dialog_bottom_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/dialog_bottom_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dialog_full_holo_dark.9.png b/core/res/res/drawable-hdpi/dialog_full_holo_dark.9.png
index 13205f0..911f3fe 100644
--- a/core/res/res/drawable-hdpi/dialog_full_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/dialog_full_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dialog_full_holo_light.9.png b/core/res/res/drawable-hdpi/dialog_full_holo_light.9.png
index 6f5dcc1..2129567 100644
--- a/core/res/res/drawable-hdpi/dialog_full_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/dialog_full_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dialog_middle_holo_dark.9.png b/core/res/res/drawable-hdpi/dialog_middle_holo_dark.9.png
index be3f7a1..9ce7cfc 100644
--- a/core/res/res/drawable-hdpi/dialog_middle_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/dialog_middle_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dialog_middle_holo_light.9.png b/core/res/res/drawable-hdpi/dialog_middle_holo_light.9.png
index 2e92a6d..396a0f2 100644
--- a/core/res/res/drawable-hdpi/dialog_middle_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/dialog_middle_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dialog_top_holo_dark.9.png b/core/res/res/drawable-hdpi/dialog_top_holo_dark.9.png
index 0e5444b..22ca61f 100644
--- a/core/res/res/drawable-hdpi/dialog_top_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/dialog_top_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dialog_top_holo_light.9.png b/core/res/res/drawable-hdpi/dialog_top_holo_light.9.png
index 32ca205..9b54cd5 100644
--- a/core/res/res/drawable-hdpi/dialog_top_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/dialog_top_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_coins_l.png b/core/res/res/drawable-hdpi/ic_coins_l.png
new file mode 100644
index 0000000..e1e3e2a
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_coins_l.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/kg_add_widget.png b/core/res/res/drawable-hdpi/kg_add_widget.png
index 723d97a..68971a5 100644
--- a/core/res/res/drawable-hdpi/kg_add_widget.png
+++ b/core/res/res/drawable-hdpi/kg_add_widget.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/kg_add_widget_disabled.png b/core/res/res/drawable-hdpi/kg_add_widget_disabled.png
new file mode 100644
index 0000000..f24cf642
--- /dev/null
+++ b/core/res/res/drawable-hdpi/kg_add_widget_disabled.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/kg_add_widget_pressed.png b/core/res/res/drawable-hdpi/kg_add_widget_pressed.png
new file mode 100644
index 0000000..55112ca
--- /dev/null
+++ b/core/res/res/drawable-hdpi/kg_add_widget_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/menu_dropdown_panel_holo_dark.9.png b/core/res/res/drawable-hdpi/menu_dropdown_panel_holo_dark.9.png
index e83b346..72ee35f 100644
--- a/core/res/res/drawable-hdpi/menu_dropdown_panel_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/menu_dropdown_panel_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/menu_dropdown_panel_holo_light.9.png b/core/res/res/drawable-hdpi/menu_dropdown_panel_holo_light.9.png
index fd4fbf8..0d1f9bf 100644
--- a/core/res/res/drawable-hdpi/menu_dropdown_panel_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/menu_dropdown_panel_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/menu_hardkey_panel_holo_dark.9.png b/core/res/res/drawable-hdpi/menu_hardkey_panel_holo_dark.9.png
index 8aee55a..465ee6d 100644
--- a/core/res/res/drawable-hdpi/menu_hardkey_panel_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/menu_hardkey_panel_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/menu_hardkey_panel_holo_light.9.png b/core/res/res/drawable-hdpi/menu_hardkey_panel_holo_light.9.png
index 2ebb7a2..76a5c53 100644
--- a/core/res/res/drawable-hdpi/menu_hardkey_panel_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/menu_hardkey_panel_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-hdpi/popup_inline_error.9.png b/core/res/res/drawable-ldrtl-hdpi/popup_inline_error.9.png
new file mode 100644
index 0000000..8b43f4e
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-hdpi/popup_inline_error.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-hdpi/popup_inline_error_above.9.png b/core/res/res/drawable-ldrtl-hdpi/popup_inline_error_above.9.png
new file mode 100644
index 0000000..20e9002
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-hdpi/popup_inline_error_above.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-hdpi/popup_inline_error_above_holo_dark.9.png b/core/res/res/drawable-ldrtl-hdpi/popup_inline_error_above_holo_dark.9.png
new file mode 100644
index 0000000..b5f397c
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-hdpi/popup_inline_error_above_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-hdpi/popup_inline_error_above_holo_light.9.png b/core/res/res/drawable-ldrtl-hdpi/popup_inline_error_above_holo_light.9.png
new file mode 100644
index 0000000..a04d695
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-hdpi/popup_inline_error_above_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-hdpi/popup_inline_error_holo_dark.9.png b/core/res/res/drawable-ldrtl-hdpi/popup_inline_error_holo_dark.9.png
new file mode 100644
index 0000000..8567b1f
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-hdpi/popup_inline_error_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-hdpi/popup_inline_error_holo_light.9.png b/core/res/res/drawable-ldrtl-hdpi/popup_inline_error_holo_light.9.png
new file mode 100644
index 0000000..7d1754c
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-hdpi/popup_inline_error_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-ldpi/popup_inline_error.9.png b/core/res/res/drawable-ldrtl-ldpi/popup_inline_error.9.png
new file mode 100644
index 0000000..d2efb62
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-ldpi/popup_inline_error.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-ldpi/popup_inline_error_above.9.png b/core/res/res/drawable-ldrtl-ldpi/popup_inline_error_above.9.png
new file mode 100644
index 0000000..04d200d
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-ldpi/popup_inline_error_above.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-mdpi/popup_inline_error.9.png b/core/res/res/drawable-ldrtl-mdpi/popup_inline_error.9.png
new file mode 100644
index 0000000..27e8d4f
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-mdpi/popup_inline_error.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-mdpi/popup_inline_error_above.9.png b/core/res/res/drawable-ldrtl-mdpi/popup_inline_error_above.9.png
new file mode 100644
index 0000000..4ae2b91
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-mdpi/popup_inline_error_above.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-mdpi/popup_inline_error_above_holo_dark.9.png b/core/res/res/drawable-ldrtl-mdpi/popup_inline_error_above_holo_dark.9.png
new file mode 100644
index 0000000..8cc3b69
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-mdpi/popup_inline_error_above_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-mdpi/popup_inline_error_above_holo_light.9.png b/core/res/res/drawable-ldrtl-mdpi/popup_inline_error_above_holo_light.9.png
new file mode 100644
index 0000000..7a84200
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-mdpi/popup_inline_error_above_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-mdpi/popup_inline_error_holo_dark.9.png b/core/res/res/drawable-ldrtl-mdpi/popup_inline_error_holo_dark.9.png
new file mode 100644
index 0000000..8fc2e2e
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-mdpi/popup_inline_error_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-mdpi/popup_inline_error_holo_light.9.png b/core/res/res/drawable-ldrtl-mdpi/popup_inline_error_holo_light.9.png
new file mode 100644
index 0000000..687a691
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-mdpi/popup_inline_error_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-xhdpi/popup_inline_error.9.png b/core/res/res/drawable-ldrtl-xhdpi/popup_inline_error.9.png
new file mode 100644
index 0000000..db91a56
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-xhdpi/popup_inline_error.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-xhdpi/popup_inline_error_above.9.png b/core/res/res/drawable-ldrtl-xhdpi/popup_inline_error_above.9.png
new file mode 100644
index 0000000..90820b5
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-xhdpi/popup_inline_error_above.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-xhdpi/popup_inline_error_above_holo_dark.9.png b/core/res/res/drawable-ldrtl-xhdpi/popup_inline_error_above_holo_dark.9.png
new file mode 100644
index 0000000..5989975
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-xhdpi/popup_inline_error_above_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-xhdpi/popup_inline_error_above_holo_light.9.png b/core/res/res/drawable-ldrtl-xhdpi/popup_inline_error_above_holo_light.9.png
new file mode 100644
index 0000000..3b3f87d3
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-xhdpi/popup_inline_error_above_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-xhdpi/popup_inline_error_holo_dark.9.png b/core/res/res/drawable-ldrtl-xhdpi/popup_inline_error_holo_dark.9.png
new file mode 100644
index 0000000..75baba2
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-xhdpi/popup_inline_error_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-xhdpi/popup_inline_error_holo_light.9.png b/core/res/res/drawable-ldrtl-xhdpi/popup_inline_error_holo_light.9.png
new file mode 100644
index 0000000..6c0203d
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-xhdpi/popup_inline_error_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dialog_bottom_holo_dark.9.png b/core/res/res/drawable-mdpi/dialog_bottom_holo_dark.9.png
index f874d66..31dc4fd 100644
--- a/core/res/res/drawable-mdpi/dialog_bottom_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/dialog_bottom_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dialog_bottom_holo_light.9.png b/core/res/res/drawable-mdpi/dialog_bottom_holo_light.9.png
index 0d6c715..7541e8a 100644
--- a/core/res/res/drawable-mdpi/dialog_bottom_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/dialog_bottom_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dialog_full_holo_dark.9.png b/core/res/res/drawable-mdpi/dialog_full_holo_dark.9.png
index 63144ae..dc37316 100644
--- a/core/res/res/drawable-mdpi/dialog_full_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/dialog_full_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dialog_full_holo_light.9.png b/core/res/res/drawable-mdpi/dialog_full_holo_light.9.png
index 953ba78..0c5770a 100644
--- a/core/res/res/drawable-mdpi/dialog_full_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/dialog_full_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dialog_middle_holo_dark.9.png b/core/res/res/drawable-mdpi/dialog_middle_holo_dark.9.png
index 0c57ffc..ca389e3 100644
--- a/core/res/res/drawable-mdpi/dialog_middle_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/dialog_middle_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dialog_middle_holo_light.9.png b/core/res/res/drawable-mdpi/dialog_middle_holo_light.9.png
index c6be52e..7a836ce 100644
--- a/core/res/res/drawable-mdpi/dialog_middle_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/dialog_middle_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dialog_top_holo_dark.9.png b/core/res/res/drawable-mdpi/dialog_top_holo_dark.9.png
index 7e9f258..fb848a3 100644
--- a/core/res/res/drawable-mdpi/dialog_top_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/dialog_top_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dialog_top_holo_light.9.png b/core/res/res/drawable-mdpi/dialog_top_holo_light.9.png
index 11cc5a4..2ddcab1 100644
--- a/core/res/res/drawable-mdpi/dialog_top_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/dialog_top_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_coins_l.png b/core/res/res/drawable-mdpi/ic_coins_l.png
new file mode 100644
index 0000000..a6d7abb
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_coins_l.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/kg_add_widget.png b/core/res/res/drawable-mdpi/kg_add_widget.png
index 5b0a5a4..136ae17 100644
--- a/core/res/res/drawable-mdpi/kg_add_widget.png
+++ b/core/res/res/drawable-mdpi/kg_add_widget.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/kg_add_widget_disabled.png b/core/res/res/drawable-mdpi/kg_add_widget_disabled.png
new file mode 100644
index 0000000..02e0f0e
--- /dev/null
+++ b/core/res/res/drawable-mdpi/kg_add_widget_disabled.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/kg_add_widget_pressed.png b/core/res/res/drawable-mdpi/kg_add_widget_pressed.png
new file mode 100644
index 0000000..34a7aaa
--- /dev/null
+++ b/core/res/res/drawable-mdpi/kg_add_widget_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/menu_dropdown_panel_holo_dark.9.png b/core/res/res/drawable-mdpi/menu_dropdown_panel_holo_dark.9.png
index 9583c9b..31dc342 100644
--- a/core/res/res/drawable-mdpi/menu_dropdown_panel_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/menu_dropdown_panel_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/menu_dropdown_panel_holo_light.9.png b/core/res/res/drawable-mdpi/menu_dropdown_panel_holo_light.9.png
index 54d2cd0..755c145 100644
--- a/core/res/res/drawable-mdpi/menu_dropdown_panel_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/menu_dropdown_panel_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/menu_hardkey_panel_holo_dark.9.png b/core/res/res/drawable-mdpi/menu_hardkey_panel_holo_dark.9.png
index ce48b33..3677994 100644
--- a/core/res/res/drawable-mdpi/menu_hardkey_panel_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/menu_hardkey_panel_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/menu_hardkey_panel_holo_light.9.png b/core/res/res/drawable-mdpi/menu_hardkey_panel_holo_light.9.png
index 1f313af..02b25f0 100644
--- a/core/res/res/drawable-mdpi/menu_hardkey_panel_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/menu_hardkey_panel_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/dialog_bottom_holo_dark.9.png b/core/res/res/drawable-xhdpi/dialog_bottom_holo_dark.9.png
index 467ea1f..3c26c6b 100644
--- a/core/res/res/drawable-xhdpi/dialog_bottom_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/dialog_bottom_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/dialog_bottom_holo_light.9.png b/core/res/res/drawable-xhdpi/dialog_bottom_holo_light.9.png
index 74929a3..f7423f3 100644
--- a/core/res/res/drawable-xhdpi/dialog_bottom_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/dialog_bottom_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/dialog_full_holo_dark.9.png b/core/res/res/drawable-xhdpi/dialog_full_holo_dark.9.png
index a8ab305..75d36be 100644
--- a/core/res/res/drawable-xhdpi/dialog_full_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/dialog_full_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/dialog_full_holo_light.9.png b/core/res/res/drawable-xhdpi/dialog_full_holo_light.9.png
index a8f02d66..d9bd337 100644
--- a/core/res/res/drawable-xhdpi/dialog_full_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/dialog_full_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/dialog_middle_holo_dark.9.png b/core/res/res/drawable-xhdpi/dialog_middle_holo_dark.9.png
index 97eb217..e9467b4 100644
--- a/core/res/res/drawable-xhdpi/dialog_middle_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/dialog_middle_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/dialog_middle_holo_light.9.png b/core/res/res/drawable-xhdpi/dialog_middle_holo_light.9.png
index 1300c19..ce3a880 100644
--- a/core/res/res/drawable-xhdpi/dialog_middle_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/dialog_middle_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/dialog_top_holo_dark.9.png b/core/res/res/drawable-xhdpi/dialog_top_holo_dark.9.png
index f82e26b..fa95667 100644
--- a/core/res/res/drawable-xhdpi/dialog_top_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/dialog_top_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/dialog_top_holo_light.9.png b/core/res/res/drawable-xhdpi/dialog_top_holo_light.9.png
index 8bd32a3..555fb81 100644
--- a/core/res/res/drawable-xhdpi/dialog_top_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/dialog_top_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_coins_l.png b/core/res/res/drawable-xhdpi/ic_coins_l.png
new file mode 100644
index 0000000..84e7e72
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_coins_l.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/kg_add_widget.png b/core/res/res/drawable-xhdpi/kg_add_widget.png
index 9c84de2..ca48be2 100644
--- a/core/res/res/drawable-xhdpi/kg_add_widget.png
+++ b/core/res/res/drawable-xhdpi/kg_add_widget.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/kg_add_widget_disabled.png b/core/res/res/drawable-xhdpi/kg_add_widget_disabled.png
new file mode 100644
index 0000000..55fa1ac
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/kg_add_widget_disabled.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/kg_add_widget_pressed.png b/core/res/res/drawable-xhdpi/kg_add_widget_pressed.png
new file mode 100644
index 0000000..4b86727
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/kg_add_widget_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/menu_dropdown_panel_holo_dark.9.png b/core/res/res/drawable-xhdpi/menu_dropdown_panel_holo_dark.9.png
index f67e609..abc48f8 100644
--- a/core/res/res/drawable-xhdpi/menu_dropdown_panel_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/menu_dropdown_panel_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/menu_dropdown_panel_holo_light.9.png b/core/res/res/drawable-xhdpi/menu_dropdown_panel_holo_light.9.png
index ed71eda..48905ed 100644
--- a/core/res/res/drawable-xhdpi/menu_dropdown_panel_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/menu_dropdown_panel_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/menu_hardkey_panel_holo_dark.9.png b/core/res/res/drawable-xhdpi/menu_hardkey_panel_holo_dark.9.png
index 585bccc..c1ad023 100644
--- a/core/res/res/drawable-xhdpi/menu_hardkey_panel_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/menu_hardkey_panel_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/menu_hardkey_panel_holo_light.9.png b/core/res/res/drawable-xhdpi/menu_hardkey_panel_holo_light.9.png
index a0669b9..a1e33d6 100644
--- a/core/res/res/drawable-xhdpi/menu_hardkey_panel_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/menu_hardkey_panel_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable/keyguard_add_widget_button.xml b/core/res/res/drawable/keyguard_add_widget_button.xml
new file mode 100644
index 0000000..c26f81d
--- /dev/null
+++ b/core/res/res/drawable/keyguard_add_widget_button.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_pressed="true" android:drawable="@drawable/kg_add_widget_pressed" />
+    <item android:state_enabled="false" android:drawable="@drawable/kg_add_widget_disabled" />
+    <item android:drawable="@drawable/kg_add_widget" />
+</selector>
diff --git a/core/res/res/layout-xlarge/screen_action_bar.xml b/core/res/res/layout-xlarge/screen_action_bar.xml
index 751d322..0b6122d 100644
--- a/core/res/res/layout-xlarge/screen_action_bar.xml
+++ b/core/res/res/layout-xlarge/screen_action_bar.xml
@@ -20,7 +20,8 @@
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:orientation="vertical"
-    android:fitsSystemWindows="true">
+    android:fitsSystemWindows="true"
+    android:splitMotionEvents="false">
     <com.android.internal.widget.ActionBarContainer android:id="@+id/action_bar_container"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
diff --git a/core/res/res/layout-xlarge/screen_action_bar_overlay.xml b/core/res/res/layout-xlarge/screen_action_bar_overlay.xml
index f2a1ea1..a95635e 100644
--- a/core/res/res/layout-xlarge/screen_action_bar_overlay.xml
+++ b/core/res/res/layout-xlarge/screen_action_bar_overlay.xml
@@ -23,7 +23,8 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/action_bar_overlay_layout"
     android:layout_width="match_parent"
-    android:layout_height="match_parent">
+    android:layout_height="match_parent"
+    android:splitMotionEvents="false">
     <FrameLayout android:id="@android:id/content"
         android:layout_width="match_parent"
         android:layout_height="match_parent" />
diff --git a/core/res/res/layout/action_bar_home.xml b/core/res/res/layout/action_bar_home.xml
index fe58215..5341f3d 100644
--- a/core/res/res/layout/action_bar_home.xml
+++ b/core/res/res/layout/action_bar_home.xml
@@ -17,9 +17,7 @@
 <view xmlns:android="http://schemas.android.com/apk/res/android"
       class="com.android.internal.widget.ActionBarView$HomeView"
       android:layout_width="wrap_content"
-      android:layout_height="match_parent"
-      android:background="?android:attr/actionBarItemBackground"
-      android:animateLayoutChanges="true">
+      android:layout_height="match_parent">
     <ImageView android:id="@android:id/up"
                android:src="?android:attr/homeAsUpIndicator"
                android:layout_gravity="center_vertical|start"
diff --git a/core/res/res/layout/action_bar_title_item.xml b/core/res/res/layout/action_bar_title_item.xml
index df773eb..ccc5b07 100644
--- a/core/res/res/layout/action_bar_title_item.xml
+++ b/core/res/res/layout/action_bar_title_item.xml
@@ -16,10 +16,9 @@
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
               android:layout_width="wrap_content"
-              android:layout_height="wrap_content"
+              android:layout_height="match_parent"
               android:orientation="horizontal"
               android:paddingEnd="8dip"
-              android:background="?android:attr/actionBarItemBackground"
               android:enabled="false">
 
     <ImageView android:id="@android:id/up"
diff --git a/core/res/res/layout/action_bar_up_container.xml b/core/res/res/layout/action_bar_up_container.xml
new file mode 100644
index 0000000..c6fad64
--- /dev/null
+++ b/core/res/res/layout/action_bar_up_container.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+      android:layout_width="wrap_content"
+      android:layout_height="match_parent"
+      android:background="?android:attr/actionBarItemBackground"
+      android:gravity="center_vertical"
+      android:enabled="false">
+</LinearLayout>
diff --git a/core/res/res/layout/keyguard_add_widget.xml b/core/res/res/layout/keyguard_add_widget.xml
index db166ac..d043fdb 100644
--- a/core/res/res/layout/keyguard_add_widget.xml
+++ b/core/res/res/layout/keyguard_add_widget.xml
@@ -36,7 +36,7 @@
             android:layout_height="wrap_content"
             android:layout_gravity="center"
             android:padding="24dp"
-            android:src="@drawable/kg_add_widget"
+            android:src="@drawable/keyguard_add_widget_button"
             android:contentDescription="@string/keyguard_accessibility_add_widget"/>
     </FrameLayout>
 </com.android.internal.policy.impl.keyguard.KeyguardWidgetFrame>
diff --git a/core/res/res/layout/keyguard_pin_view.xml b/core/res/res/layout/keyguard_pin_view.xml
index e494b69..6a3b9e6 100644
--- a/core/res/res/layout/keyguard_pin_view.xml
+++ b/core/res/res/layout/keyguard_pin_view.xml
@@ -39,6 +39,7 @@
        android:layout_height="0dp"
        android:orientation="vertical"
        android:layout_weight="1"
+       android:layoutDirection="ltr"
        >
        <LinearLayout
           android:layout_width="match_parent"
diff --git a/core/res/res/layout/keyguard_sim_pin_view.xml b/core/res/res/layout/keyguard_sim_pin_view.xml
index 026b025..6e6fe08 100644
--- a/core/res/res/layout/keyguard_sim_pin_view.xml
+++ b/core/res/res/layout/keyguard_sim_pin_view.xml
@@ -44,6 +44,7 @@
        android:layout_height="0dp"
        android:orientation="vertical"
        android:layout_weight="1"
+       android:layoutDirection="ltr"
        >
        <LinearLayout
            android:layout_width="match_parent"
diff --git a/core/res/res/layout/keyguard_sim_puk_view.xml b/core/res/res/layout/keyguard_sim_puk_view.xml
index 28a9f9a..0412fdc 100644
--- a/core/res/res/layout/keyguard_sim_puk_view.xml
+++ b/core/res/res/layout/keyguard_sim_puk_view.xml
@@ -45,6 +45,7 @@
        android:layout_height="0dp"
        android:orientation="vertical"
        android:layout_weight="1"
+       android:layoutDirection="ltr"
        >
        <LinearLayout
            android:layout_width="match_parent"
diff --git a/core/res/res/layout/list_menu_item_layout.xml b/core/res/res/layout/list_menu_item_layout.xml
index 0f37c71..e8d4983 100644
--- a/core/res/res/layout/list_menu_item_layout.xml
+++ b/core/res/res/layout/list_menu_item_layout.xml
@@ -40,7 +40,8 @@
             android:singleLine="true"
             android:duplicateParentState="true"
             android:ellipsize="marquee"
-            android:fadingEdge="horizontal" />
+            android:fadingEdge="horizontal"
+            android:textAlignment="viewStart" />
 
         <TextView
             android:id="@+id/shortcut"
@@ -50,7 +51,8 @@
             android:layout_alignParentStart="true"
             android:textAppearance="?android:attr/textAppearanceSmall"
             android:singleLine="true"
-            android:duplicateParentState="true" />
+            android:duplicateParentState="true"
+            android:textAlignment="viewStart" />
 
     </RelativeLayout>
 
diff --git a/core/res/res/layout/media_controller.xml b/core/res/res/layout/media_controller.xml
index ad74a3a..7575836 100644
--- a/core/res/res/layout/media_controller.xml
+++ b/core/res/res/layout/media_controller.xml
@@ -48,7 +48,8 @@
             android:layout_gravity="center_horizontal"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:paddingEnd="4dip" />
+            android:paddingEnd="4dip"
+            android:textColor="@color/dim_foreground_dark" />
 
         <SeekBar
             android:id="@+id/mediacontroller_progress"
@@ -67,7 +68,8 @@
             android:layout_gravity="center_horizontal"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:paddingStart="4dip" />
+            android:paddingStart="4dip"
+            android:textColor="@color/dim_foreground_dark" />
     </LinearLayout>
 
 </LinearLayout>
diff --git a/core/res/res/layout/notification_template_base.xml b/core/res/res/layout/notification_template_base.xml
index 134f45e..d2e25c1 100644
--- a/core/res/res/layout/notification_template_base.xml
+++ b/core/res/res/layout/notification_template_base.xml
@@ -61,7 +61,6 @@
             <ViewStub android:id="@+id/time"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:layout_gravity="center"
                 android:layout_weight="0"
                 android:visibility="gone"
                 android:layout="@layout/notification_template_part_time"
@@ -69,7 +68,6 @@
             <ViewStub android:id="@+id/chronometer"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:layout_gravity="center"
                 android:layout_weight="0"
                 android:visibility="gone"
                 android:layout="@layout/notification_template_part_chronometer"
diff --git a/core/res/res/layout/notification_template_big_base.xml b/core/res/res/layout/notification_template_big_base.xml
index b5da486..7cc6650 100644
--- a/core/res/res/layout/notification_template_big_base.xml
+++ b/core/res/res/layout/notification_template_big_base.xml
@@ -66,7 +66,6 @@
                 <ViewStub android:id="@+id/time"
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
-                    android:layout_gravity="center"
                     android:layout_weight="0"
                     android:visibility="gone"
                     android:layout="@layout/notification_template_part_time"
@@ -74,7 +73,6 @@
                 <ViewStub android:id="@+id/chronometer"
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
-                    android:layout_gravity="center"
                     android:layout_weight="0"
                     android:visibility="gone"
                     android:layout="@layout/notification_template_part_chronometer"
diff --git a/core/res/res/layout/notification_template_big_text.xml b/core/res/res/layout/notification_template_big_text.xml
index 01f1acf..7e6da22 100644
--- a/core/res/res/layout/notification_template_big_text.xml
+++ b/core/res/res/layout/notification_template_big_text.xml
@@ -68,7 +68,6 @@
                 <ViewStub android:id="@+id/time"
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
-                    android:layout_gravity="center"
                     android:layout_weight="0"
                     android:visibility="gone"
                     android:layout="@layout/notification_template_part_time"
@@ -76,7 +75,6 @@
                 <ViewStub android:id="@+id/chronometer"
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
-                    android:layout_gravity="center"
                     android:layout_weight="0"
                     android:visibility="gone"
                     android:layout="@layout/notification_template_part_chronometer"
diff --git a/core/res/res/layout/notification_template_inbox.xml b/core/res/res/layout/notification_template_inbox.xml
index 1b7e659..1eec871 100644
--- a/core/res/res/layout/notification_template_inbox.xml
+++ b/core/res/res/layout/notification_template_inbox.xml
@@ -69,7 +69,6 @@
                 <ViewStub android:id="@+id/time"
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
-                    android:layout_gravity="center"
                     android:layout_weight="0"
                     android:visibility="gone"
                     android:layout="@layout/notification_template_part_time"
@@ -77,7 +76,6 @@
                 <ViewStub android:id="@+id/chronometer"
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
-                    android:layout_gravity="center"
                     android:layout_weight="0"
                     android:visibility="gone"
                     android:layout="@layout/notification_template_part_chronometer"
diff --git a/core/res/res/layout/popup_menu_item_layout.xml b/core/res/res/layout/popup_menu_item_layout.xml
index f67ed4e..452f85d 100644
--- a/core/res/res/layout/popup_menu_item_layout.xml
+++ b/core/res/res/layout/popup_menu_item_layout.xml
@@ -41,7 +41,8 @@
             android:singleLine="true"
             android:duplicateParentState="true"
             android:ellipsize="marquee"
-            android:fadingEdge="horizontal" />
+            android:fadingEdge="horizontal"
+            android:textAlignment="viewStart" />
 
         <TextView
             android:id="@+id/shortcut"
@@ -51,7 +52,8 @@
             android:layout_alignParentStart="true"
             android:textAppearance="?android:attr/textAppearanceSmallPopupMenu"
             android:singleLine="true"
-            android:duplicateParentState="true" />
+            android:duplicateParentState="true"
+            android:textAlignment="viewStart" />
 
     </RelativeLayout>
 
diff --git a/core/res/res/layout/screen_action_bar.xml b/core/res/res/layout/screen_action_bar.xml
index b0f1bc5..f0b2313 100644
--- a/core/res/res/layout/screen_action_bar.xml
+++ b/core/res/res/layout/screen_action_bar.xml
@@ -22,7 +22,8 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:orientation="vertical"
-    android:fitsSystemWindows="true">
+    android:fitsSystemWindows="true"
+    android:splitMotionEvents="false">
     <com.android.internal.widget.ActionBarContainer android:id="@+id/action_bar_container"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
diff --git a/core/res/res/layout/screen_action_bar_overlay.xml b/core/res/res/layout/screen_action_bar_overlay.xml
index 20a7db1..c8181d1 100644
--- a/core/res/res/layout/screen_action_bar_overlay.xml
+++ b/core/res/res/layout/screen_action_bar_overlay.xml
@@ -23,7 +23,8 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/action_bar_overlay_layout"
     android:layout_width="match_parent"
-    android:layout_height="match_parent">
+    android:layout_height="match_parent"
+    android:splitMotionEvents="false">
     <FrameLayout android:id="@android:id/content"
         android:layout_width="match_parent"
         android:layout_height="match_parent" />
diff --git a/core/res/res/layout/sms_short_code_confirmation_dialog.xml b/core/res/res/layout/sms_short_code_confirmation_dialog.xml
index ec39d97..d82f560 100644
--- a/core/res/res/layout/sms_short_code_confirmation_dialog.xml
+++ b/core/res/res/layout/sms_short_code_confirmation_dialog.xml
@@ -30,9 +30,9 @@
         style="?android:attr/textAppearanceMedium"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:paddingLeft="16dip"
-        android:paddingRight="16dip"
-        android:paddingTop="8dip"
+        android:paddingLeft="20dip"
+        android:paddingRight="20dip"
+        android:paddingTop="16dip"
         android:paddingBottom="16dip" />
 
     <TableLayout android:id="@+id/sms_short_code_detail_layout"
@@ -51,7 +51,7 @@
                 android:layout_height="wrap_content"
                 android:paddingLeft="8dip"
                 android:paddingRight="8dip"
-                android:src="@null" />
+                android:src="@drawable/ic_coins_l" />
             <TextView android:id="@+id/sms_short_code_detail_message"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content" />
@@ -60,14 +60,19 @@
         <TableRow
             android:layout_width="wrap_content"
             android:layout_height="wrap_content" >
-
-            <CheckBox android:id="@+id/sms_short_code_remember_choice_checkbox"
-                android:layout_width="wrap_content"
+            <RelativeLayout android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:paddingRight="8dip" />
+                android:paddingTop="12dip"
+                android:paddingLeft="8dip" >
+            <CheckBox android:id="@+id/sms_short_code_remember_choice_checkbox"
+                android:paddingTop="11dip"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content" />
+            </RelativeLayout>
             <TextView android:id="@+id/sms_short_code_remember_choice_text"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
+                android:paddingTop="18dip"
                 android:text="@string/sms_short_code_remember_choice" />
         </TableRow>
 
@@ -77,6 +82,7 @@
 
             <Space android:layout_gravity="fill" />
             <TextView android:id="@+id/sms_short_code_remember_undo_instruction"
+                android:paddingTop="10dip"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content" />
         </TableRow>
diff --git a/core/res/res/mipmap-xxhdpi/sym_def_app_icon.png b/core/res/res/mipmap-xxhdpi/sym_def_app_icon.png
new file mode 100644
index 0000000..e3f3144
--- /dev/null
+++ b/core/res/res/mipmap-xxhdpi/sym_def_app_icon.png
Binary files differ
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 51d23e8..09f752f 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -993,6 +993,18 @@
     <string name="weeks" msgid="6509623834583944518">"weke"</string>
     <string name="year" msgid="4001118221013892076">"jaar"</string>
     <string name="years" msgid="6881577717993213522">"jaar"</string>
+  <plurals name="duration_seconds">
+    <item quantity="one" msgid="6962015528372969481">"1 sekonde"</item>
+    <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> sekondes"</item>
+  </plurals>
+  <plurals name="duration_minutes">
+    <item quantity="one" msgid="4915414002546085617">"1 minuut"</item>
+    <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> minute"</item>
+  </plurals>
+  <plurals name="duration_hours">
+    <item quantity="one" msgid="8917467491248809972">"1 uur"</item>
+    <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> ure"</item>
+  </plurals>
     <string name="VideoView_error_title" msgid="3534509135438353077">"Videoprobleem"</string>
     <string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Hierdie video is nie geldig vir stroming na hierdie toestel nie."</string>
     <string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Kan nie hierdie video speel nie."</string>
@@ -1082,7 +1094,7 @@
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Kennisgewing-volume"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Verstek luitoon"</string>
     <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Verstek luitoon (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
-    <string name="ringtone_silent" msgid="4440324407807468713">"Stil"</string>
+    <string name="ringtone_silent" msgid="7937634392408977062">"Geen"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Luitone"</string>
     <string name="ringtone_unknown" msgid="5477919988701784788">"Onbekende luitoon"</string>
   <plurals name="wifi_available">
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index f846ffd..643f959 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -993,6 +993,18 @@
     <string name="weeks" msgid="6509623834583944518">"ሳምንቶች"</string>
     <string name="year" msgid="4001118221013892076">"ዓመት"</string>
     <string name="years" msgid="6881577717993213522">"ዓመታት"</string>
+  <plurals name="duration_seconds">
+    <item quantity="one" msgid="6962015528372969481">"1 ሰከንድ"</item>
+    <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> ሰከንዶች"</item>
+  </plurals>
+  <plurals name="duration_minutes">
+    <item quantity="one" msgid="4915414002546085617">"1 ደቂቃ"</item>
+    <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> ደቂቃዎች"</item>
+  </plurals>
+  <plurals name="duration_hours">
+    <item quantity="one" msgid="8917467491248809972">"1 ሰዓት"</item>
+    <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> ሰዓታት"</item>
+  </plurals>
     <string name="VideoView_error_title" msgid="3534509135438353077">"የቪዲዮ ችግር"</string>
     <string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"ይቅርታ፣ ይህ ቪዲዮ በዚህ መሣሪያ ለመልቀቅ ትክክል አይደለም።"</string>
     <string name="VideoView_error_text_unknown" msgid="3450439155187810085">"ይሄን ቪዲዮ ማጫወት አልተቻለም።"</string>
@@ -1082,7 +1094,7 @@
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"የማሳወቂያ ክፍልፍል"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"ነባሪ የስልክ ላይ ጥሪ"</string>
     <string name="ringtone_default_with_actual" msgid="8129563480895990372">"(<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>) ነባሪ የስልክ ላይ ጥሪ"</string>
-    <string name="ringtone_silent" msgid="4440324407807468713">"ፀጥታ"</string>
+    <string name="ringtone_silent" msgid="7937634392408977062">"ምንም"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"ጥሪ ድምፆች"</string>
     <string name="ringtone_unknown" msgid="5477919988701784788">"ያልታወቀ የስልክ ጥሪ ድምፅ"</string>
   <plurals name="wifi_available">
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index a7c0c50..c41e706 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -993,6 +993,18 @@
     <string name="weeks" msgid="6509623834583944518">"أسابيع"</string>
     <string name="year" msgid="4001118221013892076">"سنة"</string>
     <string name="years" msgid="6881577717993213522">"أعوام"</string>
+  <plurals name="duration_seconds">
+    <item quantity="one" msgid="6962015528372969481">"ثانية واحدة"</item>
+    <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> من الثواني"</item>
+  </plurals>
+  <plurals name="duration_minutes">
+    <item quantity="one" msgid="4915414002546085617">"دقيقة واحدة"</item>
+    <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> من الدقائق"</item>
+  </plurals>
+  <plurals name="duration_hours">
+    <item quantity="one" msgid="8917467491248809972">"ساعة واحدة"</item>
+    <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> من الساعات"</item>
+  </plurals>
     <string name="VideoView_error_title" msgid="3534509135438353077">"مشكلة في الفيديو"</string>
     <string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"عذرًا، هذا الفيديو غير صالح للبث على هذا الجهاز."</string>
     <string name="VideoView_error_text_unknown" msgid="3450439155187810085">"لا يمكنك تشغيل هذا الفيديو."</string>
@@ -1082,7 +1094,7 @@
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"مستوى صوت الإشعار"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"نغمة الرنين الافتراضية"</string>
     <string name="ringtone_default_with_actual" msgid="8129563480895990372">"نغمة الرنين الافتراضية (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
-    <string name="ringtone_silent" msgid="4440324407807468713">"صامت"</string>
+    <string name="ringtone_silent" msgid="7937634392408977062">"لا شيء"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"نغمات الرنين"</string>
     <string name="ringtone_unknown" msgid="5477919988701784788">"نغمة رنين غير معروفة"</string>
   <plurals name="wifi_available">
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 6ae68f9..6d03273 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -993,6 +993,18 @@
     <string name="weeks" msgid="6509623834583944518">"тыд."</string>
     <string name="year" msgid="4001118221013892076">"год"</string>
     <string name="years" msgid="6881577717993213522">"г."</string>
+  <plurals name="duration_seconds">
+    <item quantity="one" msgid="6962015528372969481">"1 секунда"</item>
+    <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> с"</item>
+  </plurals>
+  <plurals name="duration_minutes">
+    <item quantity="one" msgid="4915414002546085617">"1 хвіліна"</item>
+    <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> хв."</item>
+  </plurals>
+  <plurals name="duration_hours">
+    <item quantity="one" msgid="8917467491248809972">"1 гадзіна"</item>
+    <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> гадз."</item>
+  </plurals>
     <string name="VideoView_error_title" msgid="3534509135438353077">"Праблема з відэа"</string>
     <string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Відэа не падыходзіць для патокавай перадачы на ​​гэту прыладу."</string>
     <string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Немагчыма прайграць гэта відэа."</string>
@@ -1082,7 +1094,7 @@
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Гучнасць апавяшчэнняў"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Рынгтон па змаўчаннi"</string>
     <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Рынгтон па змаўчаннi (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
-    <string name="ringtone_silent" msgid="4440324407807468713">"Ціхі рэжым"</string>
+    <string name="ringtone_silent" msgid="7937634392408977062">"Няма"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Рынгтоны"</string>
     <string name="ringtone_unknown" msgid="5477919988701784788">"Невядомы рынгтон"</string>
   <plurals name="wifi_available">
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 838f0cf..ca9311b 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -993,6 +993,18 @@
     <string name="weeks" msgid="6509623834583944518">"седмици"</string>
     <string name="year" msgid="4001118221013892076">"година"</string>
     <string name="years" msgid="6881577717993213522">"години"</string>
+  <plurals name="duration_seconds">
+    <item quantity="one" msgid="6962015528372969481">"1 секунда"</item>
+    <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> секунди"</item>
+  </plurals>
+  <plurals name="duration_minutes">
+    <item quantity="one" msgid="4915414002546085617">"1 минута"</item>
+    <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> минути"</item>
+  </plurals>
+  <plurals name="duration_hours">
+    <item quantity="one" msgid="8917467491248809972">"1 час"</item>
+    <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> часа"</item>
+  </plurals>
     <string name="VideoView_error_title" msgid="3534509135438353077">"Проблем с видеоклипа"</string>
     <string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Този видеоклип не е валиден за поточно предаване към това устройство."</string>
     <string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Този видеоклип не може да се пусне."</string>
@@ -1082,7 +1094,7 @@
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Сила на звука при известие"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Стандартна мелодия"</string>
     <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Стандартна мелодия (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
-    <string name="ringtone_silent" msgid="4440324407807468713">"Тишина"</string>
+    <string name="ringtone_silent" msgid="7937634392408977062">"Без"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Мелодии"</string>
     <string name="ringtone_unknown" msgid="5477919988701784788">"Неизвестна мелодия"</string>
   <plurals name="wifi_available">
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index fdc9506..2a6a333 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -993,6 +993,18 @@
     <string name="weeks" msgid="6509623834583944518">"setmanes"</string>
     <string name="year" msgid="4001118221013892076">"any"</string>
     <string name="years" msgid="6881577717993213522">"anys"</string>
+  <plurals name="duration_seconds">
+    <item quantity="one" msgid="6962015528372969481">"1 segon"</item>
+    <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> segons"</item>
+  </plurals>
+  <plurals name="duration_minutes">
+    <item quantity="one" msgid="4915414002546085617">"1 minut"</item>
+    <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> minuts"</item>
+  </plurals>
+  <plurals name="duration_hours">
+    <item quantity="one" msgid="8917467491248809972">"1 hora"</item>
+    <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> hores"</item>
+  </plurals>
     <string name="VideoView_error_title" msgid="3534509135438353077">"Problema amb el vídeo"</string>
     <string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Aquest vídeo no és vàlid per a la reproducció en aquest dispositiu."</string>
     <string name="VideoView_error_text_unknown" msgid="3450439155187810085">"No es pot reproduir aquest vídeo."</string>
@@ -1082,7 +1094,7 @@
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Volum de notificació"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"To predeterminat"</string>
     <string name="ringtone_default_with_actual" msgid="8129563480895990372">"To predeterminat (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
-    <string name="ringtone_silent" msgid="4440324407807468713">"Silenci"</string>
+    <string name="ringtone_silent" msgid="7937634392408977062">"Cap"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Sons de trucada"</string>
     <string name="ringtone_unknown" msgid="5477919988701784788">"To desconegut"</string>
   <plurals name="wifi_available">
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index b714088..f361a42 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -993,6 +993,18 @@
     <string name="weeks" msgid="6509623834583944518">"týd."</string>
     <string name="year" msgid="4001118221013892076">"rokem"</string>
     <string name="years" msgid="6881577717993213522">"lety"</string>
+  <plurals name="duration_seconds">
+    <item quantity="one" msgid="6962015528372969481">"1 sekunda"</item>
+    <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> s"</item>
+  </plurals>
+  <plurals name="duration_minutes">
+    <item quantity="one" msgid="4915414002546085617">"1 minuta"</item>
+    <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> min"</item>
+  </plurals>
+  <plurals name="duration_hours">
+    <item quantity="one" msgid="8917467491248809972">"1 hodina"</item>
+    <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> h"</item>
+  </plurals>
     <string name="VideoView_error_title" msgid="3534509135438353077">"Potíže s videem"</string>
     <string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Toto video nelze přenášet datovým proudem do tohoto zařízení."</string>
     <string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Toto video nelze přehrát."</string>
@@ -1082,7 +1094,7 @@
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Hlasitost oznámení"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Výchozí vyzváněcí tón"</string>
     <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Výchozí vyzváněcí tón (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
-    <string name="ringtone_silent" msgid="4440324407807468713">"Ticho"</string>
+    <string name="ringtone_silent" msgid="7937634392408977062">"Žádné"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Vyzváněcí tóny"</string>
     <string name="ringtone_unknown" msgid="5477919988701784788">"Neznámý vyzváněcí tón"</string>
   <plurals name="wifi_available">
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index b0fcf8b..e974576 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -993,6 +993,18 @@
     <string name="weeks" msgid="6509623834583944518">"uger"</string>
     <string name="year" msgid="4001118221013892076">"år"</string>
     <string name="years" msgid="6881577717993213522">"år"</string>
+  <plurals name="duration_seconds">
+    <item quantity="one" msgid="6962015528372969481">"Ét sekund"</item>
+    <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> sekunder"</item>
+  </plurals>
+  <plurals name="duration_minutes">
+    <item quantity="one" msgid="4915414002546085617">"Ét minut"</item>
+    <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> minutter"</item>
+  </plurals>
+  <plurals name="duration_hours">
+    <item quantity="one" msgid="8917467491248809972">"Én time"</item>
+    <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> timer"</item>
+  </plurals>
     <string name="VideoView_error_title" msgid="3534509135438353077">"Videoproblem"</string>
     <string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Denne video kan ikke streames på denne enhed."</string>
     <string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Videoen kan ikke afspilles."</string>
@@ -1082,7 +1094,7 @@
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Lydstyrke for meddelelser"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Standardringetone"</string>
     <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Standardringetone (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
-    <string name="ringtone_silent" msgid="4440324407807468713">"Lydløs"</string>
+    <string name="ringtone_silent" msgid="7937634392408977062">"Ingen"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Ringetoner"</string>
     <string name="ringtone_unknown" msgid="5477919988701784788">"Ukendt ringetone"</string>
   <plurals name="wifi_available">
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index a32bbe6..3547321 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -170,7 +170,7 @@
     <string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Kostenpflichtige Aktionen"</string>
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Ihre Nachrichten"</string>
     <string name="permgroupdesc_messages" msgid="7821999071003699236">"SMS, E-Mails und andere Nachrichten lesen und schreiben"</string>
-    <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"Ihre persönlichen Informationen"</string>
+    <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"Ihre personenbezogenen Daten"</string>
     <string name="permgroupdesc_personalInfo" msgid="8426453129788861338">"Direkter Zugriff auf Informationen über Sie, die in Ihrer Kontaktkarte gespeichert sind"</string>
     <string name="permgrouplab_socialInfo" msgid="5799096623412043791">"Ihre sozialen Informationen"</string>
     <string name="permgroupdesc_socialInfo" msgid="7129842457611643493">"Direkter Zugriff auf Informationen über Ihre Kontakte und sozialen Verbindungen"</string>
@@ -241,7 +241,7 @@
     <string name="permdesc_receiveEmergencyBroadcast" msgid="848524070262431974">"Ermöglicht der App, Notfall-Broadcasts zu empfangen und zu verarbeiten. Diese Berechtigung steht nur System-Apps zur Verfügung."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"Cell Broadcast-Nachrichten lesen"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Ermöglicht der App, von Ihrem Gerät empfangene Cell Broadcast-Nachrichten zu lesen. Cell Broadcast-Benachrichtigungen werden an einigen Standorten gesendet, um Sie über Notfallsituationen zu informieren. Schädliche Apps können die Leistung oder den Betrieb Ihres Geräts beeinträchtigen, wenn eine Cell Broadcast-Notfallbenachrichtigung eingeht."</string>
-    <string name="permlab_sendSms" msgid="5600830612147671529">"Kurznachrichten senden"</string>
+    <string name="permlab_sendSms" msgid="5600830612147671529">"SMS senden"</string>
     <string name="permdesc_sendSms" msgid="7094729298204937667">"Ermöglicht der App, SMS zu senden. Dies kann zu unerwarteten Kosten führen. Schädliche Apps können Kosten verursachen, indem sie Nachrichten ohne Ihre Bestätigung senden."</string>
     <string name="permlab_sendSmsNoConfirmation" msgid="4781483105951730228">"SMS ohne Bestätigung senden"</string>
     <string name="permdesc_sendSmsNoConfirmation" msgid="402569800862935907">"Ermöglicht der App, SMS zu senden. Dies kann zu unerwarteten Kosten führen. Schädliche Apps können Kosten verursachen, indem sie Nachrichten ohne Ihre Bestätigung senden."</string>
@@ -253,7 +253,7 @@
     <string name="permdesc_writeSms" product="default" msgid="7268668709052328567">"Ermöglicht der App, auf Ihrem Telefon oder Ihrer SIM-Karte gespeicherte SMS zu bearbeiten. Schädliche Apps können so Ihre Nachrichten löschen."</string>
     <string name="permlab_receiveWapPush" msgid="5991398711936590410">"Textnachrichten (WAP) empfangen"</string>
     <string name="permdesc_receiveWapPush" msgid="748232190220583385">"Ermöglicht der App, WAP-Nachrichten zu empfangen und zu verarbeiten. Mit der Berechtigung können Nachrichten, die an Sie gesendet wurden, überwacht und gelöscht werden, bevor sie Ihnen angezeigt werden."</string>
-    <string name="permlab_getTasks" msgid="6466095396623933906">"aktive Apps abrufen"</string>
+    <string name="permlab_getTasks" msgid="6466095396623933906">"Aktive Apps abrufen"</string>
     <string name="permdesc_getTasks" msgid="7454215995847658102">"Ermöglicht der App, Informationen zu aktuellen und kürzlich ausgeführten Aufgaben abzurufen. Damit kann die App möglicherweise ermitteln, welche Apps auf Ihrem Gerät zum Einsatz kommen."</string>
     <string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"Nutzerübergreifend interagieren"</string>
     <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Ermöglicht der App, auf dem Gerät nutzerübergreifend Aktionen durchzuführen. Schädliche Apps können so den zwischen den Nutzern bestehenden Schutz aufheben."</string>
@@ -295,7 +295,7 @@
     <string name="permdesc_filter_events" msgid="8006236315888347680">"Ermöglicht einer App, einen Eingabefilter zu registrieren, der den Stream aller Nutzerereignisse vor ihrem Versand filtert. Eine schädliche App kann die System-UI ohne Eingriff des Nutzers kontrollieren."</string>
     <string name="permlab_magnify_display" msgid="5973626738170618775">"Anzeige vergrößern"</string>
     <string name="permdesc_magnify_display" msgid="7121235684515003792">"Erlaubt der App, den Inhalt einer Anzeige zu vergrößern. Schädliche Apps verändern eventuell die Ansicht, sodass Inhalte nicht richtig angezeigt werden."</string>
-    <string name="permlab_shutdown" msgid="7185747824038909016">"partielles Herunterfahren"</string>
+    <string name="permlab_shutdown" msgid="7185747824038909016">"Partielles Herunterfahren"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Versetzt den Aktivitätsmanager in einen heruntergefahrenen Zustand. Führt kein vollständiges Herunterfahren aus."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"App-Wechsel verhindern"</string>
     <string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Hindert den Nutzer daran, zu einer anderen App zu wechseln"</string>
@@ -303,9 +303,9 @@
     <string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Ermöglicht der App, den Start von Systemaktivitäten zu überwachen und zu steuern. Schädliche Apps können so das gesamte System beeinträchtigen. Diese Berechtigung wird nur zu Entwicklungszwecken und nie für die normale Nutzung benötigt."</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"Broadcast ohne Paket senden"</string>
     <string name="permdesc_broadcastPackageRemoved" msgid="6621901216207931089">"Ermöglicht der App, eine Benachrichtigung zu senden, dass ein App-Paket entfernt wurde. Schädliche Apps können so eine andere aktive App beenden."</string>
-    <string name="permlab_broadcastSmsReceived" msgid="5689095009030336593">"per SMS empfangenen Broadcast senden"</string>
+    <string name="permlab_broadcastSmsReceived" msgid="5689095009030336593">"Per SMS empfangenen Broadcast senden"</string>
     <string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Ermöglicht der App, eine Benachrichtigung zu senden, dass eine SMS empfangen wurde. Schädliche Apps können so eingehende SMS fälschen."</string>
-    <string name="permlab_broadcastWapPush" msgid="3145347413028582371">"von WAP-PUSH empfangenen Broadcast senden"</string>
+    <string name="permlab_broadcastWapPush" msgid="3145347413028582371">"Von WAP-PUSH empfangenen Broadcast senden"</string>
     <string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Ermöglicht der App, eine Benachrichtigung zu senden, dass eine WAP PUSH-Nachricht empfangen wurde. Schädliche Apps können so den Empfang von MMS vortäuschen oder unbemerkt den Inhalt einer beliebigen Webseite durch schädliche Inhalte ersetzen."</string>
     <string name="permlab_setProcessLimit" msgid="2451873664363662666">"Anzahl der laufenden Prozesse beschränken"</string>
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Ermöglicht der App, die maximale Anzahl an aktiven Prozessen zu steuern. Wird nie für normale Apps benötigt."</string>
@@ -319,7 +319,7 @@
     <string name="permdesc_backup" msgid="6912230525140589891">"Ermöglicht der App, den Sicherungs- und Wiederherstellungsmechanismus des Systems zu steuern. Nicht für normale Apps vorgesehen."</string>
     <string name="permlab_confirm_full_backup" msgid="5557071325804469102">"Vollständige Sicherung oder Wiederherstellung bestätigen"</string>
     <string name="permdesc_confirm_full_backup" msgid="1748762171637699562">"Ermöglicht der App, die Benutzeroberfläche zur Bestätigung der vollständigen Sicherung zu starten. Kann nicht von jeder App verwendet werden."</string>
-    <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"nicht autorisierte Fenster anzeigen"</string>
+    <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"Nicht autorisierte Fenster anzeigen"</string>
     <string name="permdesc_internalSystemWindow" msgid="7458387759461466397">"Ermöglicht der App die Erstellung von Fenstern, die von der Benutzeroberfläche des internen Systems verwendet werden. Nicht für normale Apps vorgesehen."</string>
     <string name="permlab_systemAlertWindow" msgid="3543347980839518613">"Über andere Apps ziehen"</string>
     <string name="permdesc_systemAlertWindow" msgid="8584678381972820118">"Ermöglicht der App, über andere Apps oder Teile der Benutzeroberfläche zu zeichnen. Dies kann sich auf die Oberfläche in jeder App auswirken oder die erwartete Darstellung in anderen Apps verändern."</string>
@@ -375,8 +375,8 @@
     <string name="permlab_movePackage" msgid="3289890271645921411">"App-Ressourcen verschieben"</string>
     <string name="permdesc_movePackage" msgid="319562217778244524">"Ermöglicht der App, App-Ressourcen von internen auf externe Medien zu verschieben und umgekehrt"</string>
     <string name="permlab_readLogs" msgid="6615778543198967614">"Vertrauliche Protokolldaten lesen"</string>
-    <string name="permdesc_readLogs" product="tablet" msgid="82061313293455151">"Ermöglicht der App, die verschiedenen Protokolldateien des Systems zu lesen. So können allgemeine Informationen zu den auf Ihrem Tablet durchgeführten Aktionen eingesehen werden, darunter auch persönliche oder geheime Daten."</string>
-    <string name="permdesc_readLogs" product="default" msgid="2063438140241560443">"Ermöglicht der App, die verschiedenen Protokolldateien des Systems zu lesen. So können allgemeine Informationen zu den auf Ihrem Telefon durchgeführten Aktionen eingesehen werden, darunter auch persönliche oder geheime Daten."</string>
+    <string name="permdesc_readLogs" product="tablet" msgid="82061313293455151">"Ermöglicht der App, die verschiedenen Protokolldateien des Systems zu lesen. So können allgemeine Informationen zu den auf Ihrem Tablet durchgeführten Aktionen eingesehen werden, darunter auch personenbezogene oder vertrauliche Daten."</string>
+    <string name="permdesc_readLogs" product="default" msgid="2063438140241560443">"Ermöglicht der App, die verschiedenen Protokolldateien des Systems zu lesen. So können allgemeine Informationen zu den auf Ihrem Telefon durchgeführten Aktionen eingesehen werden, darunter auch personenbezogene oder vertrauliche Daten."</string>
     <string name="permlab_anyCodecForPlayback" msgid="715805555823881818">"Für Wiedergabe beliebigen Mediendecodierer verwenden"</string>
     <string name="permdesc_anyCodecForPlayback" msgid="8283912488433189010">"Ermöglicht der App, alle installierten Mediendecodierer zur Wiedergabe zu verwenden."</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"Lese-/Schreibberechtigung für zu Diagnosegruppe gehörige Elemente"</string>
@@ -397,7 +397,7 @@
     <string name="permlab_receiveBootCompleted" msgid="5312965565987800025">"Beim Start ausführen"</string>
     <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7390304664116880704">"Ermöglicht der App, sich selbst zu starten, sobald das System gebootet wurde. Dadurch kann es länger dauern, bis das Tablet gestartet wird, und durch die ständige Aktivität der App wird die gesamte Leistung des Tablets beeinträchtigt."</string>
     <string name="permdesc_receiveBootCompleted" product="default" msgid="513950589102617504">"Ermöglicht der App, sich selbst zu starten, sobald das System gebootet wurde. Dadurch kann es länger dauern, bis das Telefon gestartet wird, und durch die ständige Aktivität der App wird die gesamte Leistung des Telefons beeinträchtigt."</string>
-    <string name="permlab_broadcastSticky" msgid="7919126372606881614">"dauerhaften Broadcast senden"</string>
+    <string name="permlab_broadcastSticky" msgid="7919126372606881614">"Dauerhaften Broadcast senden"</string>
     <string name="permdesc_broadcastSticky" product="tablet" msgid="7749760494399915651">"Ermöglicht der App, weiluerhafte Broadcasts zu senden, die auch nach Ende des Broadcasts bestehen bleiben. Ein zu intensiver Einsatz kann das Tablet langsam oder instabil machen, weil zu viel Arbeitsspeicher belegt wird."</string>
     <string name="permdesc_broadcastSticky" product="default" msgid="2825803764232445091">"Ermöglicht der App, weiluerhafte Broadcasts zu senden, die auch nach Ende des Broadcasts bestehen bleiben. Ein zu intensiver Einsatz kann das Telefon langsam oder instabil machen, weil zu viel Arbeitsspeicher belegt wird."</string>
     <string name="permlab_readContacts" msgid="8348481131899886131">"Kontakte lesen"</string>
@@ -406,16 +406,16 @@
     <string name="permlab_writeContacts" msgid="5107492086416793544">"Meine Kontakte ändern"</string>
     <string name="permdesc_writeContacts" product="tablet" msgid="897243932521953602">"Ermöglicht der App, Daten zu Kontakten, die auf Ihrem Tablet gespeichert sind, zu ändern, einschließlich der Häufigkeit, mit der Sie bestimmte Kontakte angerufen, diesen E-Mails gesendet oder anderweitig mit ihnen kommuniziert haben. Die Berechtigung erlaubt Apps, Kontaktdaten zu löschen."</string>
     <string name="permdesc_writeContacts" product="default" msgid="589869224625163558">"Ermöglicht der App, Daten zu Kontakten, die auf Ihrem Telefon gespeichert sind, zu ändern, einschließlich der Häufigkeit, mit der Sie bestimmte Kontakte angerufen, diesen E-Mails gesendet oder anderweitig mit ihnen kommuniziert haben. Die Berechtigung erlaubt Apps, Kontaktdaten zu löschen."</string>
-    <string name="permlab_readCallLog" msgid="3478133184624102739">"Anrufprotokoll lesen"</string>
+    <string name="permlab_readCallLog" msgid="3478133184624102739">"Anrufliste lesen"</string>
     <string name="permdesc_readCallLog" product="tablet" msgid="3700645184870760285">"Ermöglicht der App, die Anrufliste Ihres Tablets zu lesen, einschließlich der Daten über ein- und ausgehende Anrufe. Die Berechtigung erlaubt Apps, Ihre Anruflistendaten zu speichern, und schädliche Apps können diese Daten ohne Ihr Wissen weiterleiten."</string>
     <string name="permdesc_readCallLog" product="default" msgid="5777725796813217244">"Ermöglicht der App, die Anrufliste Ihres Telefons zu lesen, einschließlich der Daten über ein- und ausgehende Anrufe. Die Berechtigung erlaubt Apps, Ihre Anruflistendaten zu speichern, und schädliche Apps können diese Daten ohne Ihr Wissen weiterleiten."</string>
     <string name="permlab_writeCallLog" msgid="8552045664743499354">"Anrufprotokoll bearbeiten"</string>
     <string name="permdesc_writeCallLog" product="tablet" msgid="6661806062274119245">"Ermöglicht der App, das Anrufprotokoll Ihres Tablets zu ändern, einschließlich der Daten über ein- und ausgehende Anrufe. Schädliche Apps können so Ihr Anrufprotokoll löschen oder ändern."</string>
     <string name="permdesc_writeCallLog" product="default" msgid="683941736352787842">"Ermöglicht der App, das Anrufprotokoll Ihres Telefons zu ändern, einschließlich der Daten über ein- und ausgehende Anrufe. Schädliche Apps können so Ihr Anrufprotokoll löschen oder ändern."</string>
     <string name="permlab_readProfile" msgid="4701889852612716678">"Meine Kontaktkarten lesen"</string>
-    <string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"Ermöglicht der App, auf Ihrem Gerät gespeicherte persönliche Profildaten zu lesen, einschließlich Ihres Namens und Ihrer Kontaktdaten. Die App kann Sie somit identifizieren und Ihre Profildaten an andere senden."</string>
+    <string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"Ermöglicht der App, auf Ihrem Gerät gespeicherte personenbezogene Profildaten zu lesen, einschließlich Ihres Namens und Ihrer Kontaktdaten. Die App kann Sie somit identifizieren und Ihre Profildaten an andere senden."</string>
     <string name="permlab_writeProfile" msgid="907793628777397643">"Meine Kontaktkarten ändern"</string>
-    <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Ermöglicht der App, auf Ihrem Gerät gespeicherte persönliche Profildaten zu ändern, einschließlich Ihres Namens und Ihrer Kontaktdaten, sowie Daten hinzuzufügen. Die App kann Sie so identifizieren und Ihre Profildaten an andere senden."</string>
+    <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Ermöglicht der App, auf Ihrem Gerät gespeicherte personenbezogene Profildaten zu ändern, einschließlich Ihres Namens und Ihrer Kontaktdaten, sowie Daten hinzuzufügen. Die App kann Sie so identifizieren und Ihre Profildaten an andere senden."</string>
     <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"In sozialem Stream lesen"</string>
     <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Ermöglicht der App, auf Updates aus sozialen Netzwerken von Ihnen und Ihren Freunden zuzugreifen und diese zu synchronisieren. Seien Sie vorsichtig, wenn Sie Informationen teilen: Der App wird erlaubt, die Kommunikation zwischen Ihnen und Ihren Freunden in sozialen Netzwerken zu lesen, unabhängig von der Vertraulichkeit der kommunizierten Informationen. Hinweis: Diese Berechtigung kann möglicherweise nicht in allen sozialen Netzwerken erzwungen werden."</string>
     <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"In sozialem Stream schreiben"</string>
@@ -432,9 +432,9 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Ermöglicht der App, auf zusätzliche Standortanbieterbefehle zuzugreifen. Damit könnte die App die Funktionsweise von GPS oder anderen Standortquellen beeinträchtigen."</string>
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"Berechtigung zur Installation eines Standortanbieters"</string>
     <string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Erstellen von simulierten Standortquellen für Testzwecke oder Installation eines neuen Standortanbieters. Damit kann die App den von anderen Standortquellen wie GPS oder Standortanbietern zurückgegebenen Standort und/oder Status überschreiben."</string>
-    <string name="permlab_accessFineLocation" msgid="1191898061965273372">"genauer Standort (GPS- und netzwerkbasiert)"</string>
+    <string name="permlab_accessFineLocation" msgid="1191898061965273372">"Genauer Standort (GPS- und netzwerkbasiert)"</string>
     <string name="permdesc_accessFineLocation" msgid="5295047563564981250">"Ermöglicht der App, Ihre genaue Position anhand von GPS-Daten (Global Positioning System) oder über Netzwerkstandortquellen wie Sendemasten oder WLAN zu ermitteln. Diese Standortdienste müssen auf Ihrem Gerät verfügbar und aktiviert sein, damit die App sie verwenden kann. Apps können Ihren Standort anhand dieser Daten ermitteln und verbrauchen eventuell zusätzliche Akkuleistung."</string>
-    <string name="permlab_accessCoarseLocation" msgid="4887895362354239628">"ungefährer Standort (netzwerkbasiert)"</string>
+    <string name="permlab_accessCoarseLocation" msgid="4887895362354239628">"Ungefährer Standort (netzwerkbasiert)"</string>
     <string name="permdesc_accessCoarseLocation" msgid="2538200184373302295">"Ermöglicht der App, Ihren ungefähren Standort zu ermitteln. Diese Standortangabe stammt von Standortdiensten, die Netzwerkstandortquellen wie etwa Sendemasten oder WLAN verwenden. Diese Standortdienste müssen auf Ihrem Gerät verfügbar und aktiviert sein, damit die App sie verwenden kann. Apps können Ihren ungefähren Standort anhand dieser Daten ermitteln."</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"Auf SurfaceFlinger zugreifen"</string>
     <string name="permdesc_accessSurfaceFlinger" msgid="1041619516733293551">"Ermöglicht der App, die systemnahen SurfaceFlinger-Funktionen zu verwenden"</string>
@@ -496,7 +496,7 @@
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"Auf Check-in-Eigenschaften zugreifen"</string>
     <string name="permdesc_checkinProperties" msgid="4024526968630194128">"Ermöglicht der App Schreib-/Lesezugriff auf vom Check-in-Service hochgeladene Elemente. Nicht für normale Apps vorgesehen."</string>
     <string name="permlab_bindGadget" msgid="776905339015863471">"Widgets auswählen"</string>
-    <string name="permdesc_bindGadget" msgid="8261326938599049290">"Ermöglicht der App, dem System zu melden, welche Widgets von welcher App verwendet werden können. Mit dieser Berechtigung können Apps anderen Apps Zugriff auf persönliche Daten gewähren. Nicht für normale Apps vorgesehen."</string>
+    <string name="permdesc_bindGadget" msgid="8261326938599049290">"Ermöglicht der App, dem System zu melden, welche Widgets von welcher App verwendet werden können. Mit dieser Berechtigung können Apps anderen Apps Zugriff auf personenbezogene Daten gewähren. Nicht für normale Apps vorgesehen."</string>
     <string name="permlab_modifyPhoneState" msgid="8423923777659292228">"Telefonstatus ändern"</string>
     <string name="permdesc_modifyPhoneState" msgid="1029877529007686732">"Ermöglicht der App, die Telefonfunktionen des Geräts zu steuern. Eine App mit dieser Berechtigung kann das Netzwerk wechseln oder das Radio des Telefons ein- und ausschalten, ohne Sie darüber zu informieren."</string>
     <string name="permlab_readPhoneState" msgid="9178228524507610486">"Telefonstatus und Identität abrufen"</string>
@@ -993,6 +993,18 @@
     <string name="weeks" msgid="6509623834583944518">"Wochen"</string>
     <string name="year" msgid="4001118221013892076">"Jahr"</string>
     <string name="years" msgid="6881577717993213522">"Jahre"</string>
+  <plurals name="duration_seconds">
+    <item quantity="one" msgid="6962015528372969481">"1 Sekunde"</item>
+    <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> Sekunden"</item>
+  </plurals>
+  <plurals name="duration_minutes">
+    <item quantity="one" msgid="4915414002546085617">"1 Minute"</item>
+    <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> Minuten"</item>
+  </plurals>
+  <plurals name="duration_hours">
+    <item quantity="one" msgid="8917467491248809972">"1 Stunde"</item>
+    <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> Stunden"</item>
+  </plurals>
     <string name="VideoView_error_title" msgid="3534509135438353077">"Videoprobleme"</string>
     <string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Dieses Video ist nicht für Streaming auf diesem Gerät gültig."</string>
     <string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Video kann nicht wiedergegeben werden."</string>
@@ -1082,7 +1094,7 @@
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Benachrichtigungslautstärke"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Standard-Klingelton"</string>
     <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Standard-Klingelton (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
-    <string name="ringtone_silent" msgid="4440324407807468713">"Lautlos"</string>
+    <string name="ringtone_silent" msgid="7937634392408977062">"Keine"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Klingeltöne"</string>
     <string name="ringtone_unknown" msgid="5477919988701784788">"Unbekannter Klingelton"</string>
   <plurals name="wifi_available">
@@ -1114,7 +1126,7 @@
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
     <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"Das Telefon wird vorübergehend vom WLAN getrennt, während eine Verbindung mit <xliff:g id="DEVICE_NAME">%1$s</xliff:g> hergestellt wird."</string>
     <string name="select_character" msgid="3365550120617701745">"Zeichen einfügen"</string>
-    <string name="sms_control_title" msgid="7296612781128917719">"Kurznachrichten werden gesendet"</string>
+    <string name="sms_control_title" msgid="7296612781128917719">"SMS werden gesendet"</string>
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; sendet eine große Anzahl SMS. Möchten Sie zulassen, dass die App weiterhin Nachrichten sendet?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Zulassen"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Nicht zulassen"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 069c5d6..70c1550 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -993,6 +993,18 @@
     <string name="weeks" msgid="6509623834583944518">"εβδομάδες"</string>
     <string name="year" msgid="4001118221013892076">"έτος"</string>
     <string name="years" msgid="6881577717993213522">"έτη"</string>
+  <plurals name="duration_seconds">
+    <item quantity="one" msgid="6962015528372969481">"1 δευτερόλεπτο"</item>
+    <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> δευτερόλεπτα"</item>
+  </plurals>
+  <plurals name="duration_minutes">
+    <item quantity="one" msgid="4915414002546085617">"1 λεπτό"</item>
+    <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> λεπτά"</item>
+  </plurals>
+  <plurals name="duration_hours">
+    <item quantity="one" msgid="8917467491248809972">"1 ώρα"</item>
+    <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> ώρες"</item>
+  </plurals>
     <string name="VideoView_error_title" msgid="3534509135438353077">"Πρόβλημα με το βίντεο"</string>
     <string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Αυτό το βίντεο δεν είναι έγκυρο για ροή σε αυτή τη συσκευή."</string>
     <string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Δεν μπορείτε να αναπαράγετε αυτό το βίντεο."</string>
@@ -1082,7 +1094,7 @@
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Ένταση ήχου ειδοποιήσεων"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Προεπιλεγμένος ήχος κλήσης"</string>
     <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Προεπιλεγμένος ήχος κλήσης (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
-    <string name="ringtone_silent" msgid="4440324407807468713">"Σίγαση"</string>
+    <string name="ringtone_silent" msgid="7937634392408977062">"Κανένας"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Ήχοι κλήσης"</string>
     <string name="ringtone_unknown" msgid="5477919988701784788">"Άγνωστος ήχος κλήσης"</string>
   <plurals name="wifi_available">
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 888e42e..c1c78e2 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -993,6 +993,18 @@
     <string name="weeks" msgid="6509623834583944518">"weeks"</string>
     <string name="year" msgid="4001118221013892076">"year"</string>
     <string name="years" msgid="6881577717993213522">"years"</string>
+  <plurals name="duration_seconds">
+    <item quantity="one" msgid="6962015528372969481">"1 second"</item>
+    <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> seconds"</item>
+  </plurals>
+  <plurals name="duration_minutes">
+    <item quantity="one" msgid="4915414002546085617">"1 minute"</item>
+    <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> minutes"</item>
+  </plurals>
+  <plurals name="duration_hours">
+    <item quantity="one" msgid="8917467491248809972">"1 hour"</item>
+    <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> hours"</item>
+  </plurals>
     <string name="VideoView_error_title" msgid="3534509135438353077">"Video problem"</string>
     <string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"This video isn\'t valid for streaming to this device."</string>
     <string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Can\'t play this video."</string>
@@ -1082,7 +1094,8 @@
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Notification volume"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Default ringtone"</string>
     <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Default ringtone (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
-    <string name="ringtone_silent" msgid="4440324407807468713">"Silent"</string>
+    <!-- no translation found for ringtone_silent (7937634392408977062) -->
+    <skip />
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Ringtones"</string>
     <string name="ringtone_unknown" msgid="5477919988701784788">"Unknown ringtone"</string>
   <plurals name="wifi_available">
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 47d436d..cf1c9db 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -993,6 +993,18 @@
     <string name="weeks" msgid="6509623834583944518">"semanas"</string>
     <string name="year" msgid="4001118221013892076">"año"</string>
     <string name="years" msgid="6881577717993213522">"años"</string>
+  <plurals name="duration_seconds">
+    <item quantity="one" msgid="6962015528372969481">"1 segundo"</item>
+    <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> segundos"</item>
+  </plurals>
+  <plurals name="duration_minutes">
+    <item quantity="one" msgid="4915414002546085617">"1 minuto"</item>
+    <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> minutos"</item>
+  </plurals>
+  <plurals name="duration_hours">
+    <item quantity="one" msgid="8917467491248809972">"1 hora"</item>
+    <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> horas"</item>
+  </plurals>
     <string name="VideoView_error_title" msgid="3534509135438353077">"Problemas de video"</string>
     <string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"No es posible transmitir este video al dispositivo."</string>
     <string name="VideoView_error_text_unknown" msgid="3450439155187810085">"No se puede reproducir el video."</string>
@@ -1082,7 +1094,7 @@
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Volumen de notificación"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Tono de llamada predeterminado"</string>
     <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Tono de llamada predeterminado (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
-    <string name="ringtone_silent" msgid="4440324407807468713">"Silencioso"</string>
+    <string name="ringtone_silent" msgid="7937634392408977062">"Ninguno"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Tonos de llamada"</string>
     <string name="ringtone_unknown" msgid="5477919988701784788">"Tono de llamada desconocido"</string>
   <plurals name="wifi_available">
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index c129483..824b42a 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -993,6 +993,18 @@
     <string name="weeks" msgid="6509623834583944518">"semanas"</string>
     <string name="year" msgid="4001118221013892076">"año"</string>
     <string name="years" msgid="6881577717993213522">"años"</string>
+  <plurals name="duration_seconds">
+    <item quantity="one" msgid="6962015528372969481">"1 segundo"</item>
+    <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> segundos"</item>
+  </plurals>
+  <plurals name="duration_minutes">
+    <item quantity="one" msgid="4915414002546085617">"1 minuto"</item>
+    <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> minutos"</item>
+  </plurals>
+  <plurals name="duration_hours">
+    <item quantity="one" msgid="8917467491248809972">"1 hora"</item>
+    <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> horas"</item>
+  </plurals>
     <string name="VideoView_error_title" msgid="3534509135438353077">"Incidencias con el vídeo"</string>
     <string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Este vídeo no se puede transmitir al dispositivo."</string>
     <string name="VideoView_error_text_unknown" msgid="3450439155187810085">"No se puede reproducir el vídeo."</string>
@@ -1082,7 +1094,7 @@
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Volumen de notificaciones"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Tono predeterminado"</string>
     <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Tono predeterminado (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
-    <string name="ringtone_silent" msgid="4440324407807468713">"Silencio"</string>
+    <string name="ringtone_silent" msgid="7937634392408977062">"Ninguno"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Tonos"</string>
     <string name="ringtone_unknown" msgid="5477919988701784788">"Tono desconocido"</string>
   <plurals name="wifi_available">
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index 5fb21d4..6e7b87c 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -993,6 +993,18 @@
     <string name="weeks" msgid="6509623834583944518">"nädalat"</string>
     <string name="year" msgid="4001118221013892076">"aasta"</string>
     <string name="years" msgid="6881577717993213522">"aastat"</string>
+  <plurals name="duration_seconds">
+    <item quantity="one" msgid="6962015528372969481">"1 sekund"</item>
+    <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> sekundit"</item>
+  </plurals>
+  <plurals name="duration_minutes">
+    <item quantity="one" msgid="4915414002546085617">"1 minut"</item>
+    <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> minutit"</item>
+  </plurals>
+  <plurals name="duration_hours">
+    <item quantity="one" msgid="8917467491248809972">"1 tund"</item>
+    <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> tundi"</item>
+  </plurals>
     <string name="VideoView_error_title" msgid="3534509135438353077">"Probleem videoga"</string>
     <string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"See video ei sobi voogesituseks selles seadmes."</string>
     <string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Videot ei saa esitada."</string>
@@ -1082,7 +1094,7 @@
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Teatise helitugevus"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Vaikehelin"</string>
     <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Vaikehelin (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
-    <string name="ringtone_silent" msgid="4440324407807468713">"Hääletu"</string>
+    <string name="ringtone_silent" msgid="7937634392408977062">"Puudub"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Helinad"</string>
     <string name="ringtone_unknown" msgid="5477919988701784788">"Tundmatu helin"</string>
   <plurals name="wifi_available">
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index d5e624d0..51f1967 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -993,6 +993,18 @@
     <string name="weeks" msgid="6509623834583944518">"هفته"</string>
     <string name="year" msgid="4001118221013892076">"سال"</string>
     <string name="years" msgid="6881577717993213522">"سال"</string>
+  <plurals name="duration_seconds">
+    <item quantity="one" msgid="6962015528372969481">"۱ ثانیه"</item>
+    <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> ثانیه"</item>
+  </plurals>
+  <plurals name="duration_minutes">
+    <item quantity="one" msgid="4915414002546085617">"۱ دقیقه"</item>
+    <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> دقیقه"</item>
+  </plurals>
+  <plurals name="duration_hours">
+    <item quantity="one" msgid="8917467491248809972">"۱ ساعت"</item>
+    <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> ساعت"</item>
+  </plurals>
     <string name="VideoView_error_title" msgid="3534509135438353077">"مشکل در ویدئو"</string>
     <string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"متأسفیم، این ویدئو برای پخش جریانی با این دستگاه معتبر نیست."</string>
     <string name="VideoView_error_text_unknown" msgid="3450439155187810085">"پخش این ویدئو ممکن نیست."</string>
@@ -1082,7 +1094,7 @@
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"میزان صدای اعلان"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"آهنگ زنگ پیش‌فرض"</string>
     <string name="ringtone_default_with_actual" msgid="8129563480895990372">"آهنگ زنگ پیش‌فرض (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
-    <string name="ringtone_silent" msgid="4440324407807468713">"ساکت"</string>
+    <string name="ringtone_silent" msgid="7937634392408977062">"هیچکدام"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"آهنگ‌های زنگ"</string>
     <string name="ringtone_unknown" msgid="5477919988701784788">"آهنگ زنگ ناشناس"</string>
   <plurals name="wifi_available">
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 2b08bea..8bbd645 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -993,6 +993,18 @@
     <string name="weeks" msgid="6509623834583944518">"viikkoa"</string>
     <string name="year" msgid="4001118221013892076">"vuosi"</string>
     <string name="years" msgid="6881577717993213522">"vuotta"</string>
+  <plurals name="duration_seconds">
+    <item quantity="one" msgid="6962015528372969481">"1 sekunti"</item>
+    <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> sekuntia"</item>
+  </plurals>
+  <plurals name="duration_minutes">
+    <item quantity="one" msgid="4915414002546085617">"1 minuutti"</item>
+    <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> minuuttia"</item>
+  </plurals>
+  <plurals name="duration_hours">
+    <item quantity="one" msgid="8917467491248809972">"1 tunti"</item>
+    <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> tuntia"</item>
+  </plurals>
     <string name="VideoView_error_title" msgid="3534509135438353077">"Video-ongelma"</string>
     <string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Tätä videota ei voi suoratoistaa tällä laitteella."</string>
     <string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Videota ei voida toistaa."</string>
@@ -1082,7 +1094,7 @@
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Ilmoituksen äänenvoimakkuus"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Oletussoittoääni"</string>
     <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Oletussoittoääni (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
-    <string name="ringtone_silent" msgid="4440324407807468713">"Äänetön"</string>
+    <string name="ringtone_silent" msgid="7937634392408977062">"Ei mitään"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Soittoäänet"</string>
     <string name="ringtone_unknown" msgid="5477919988701784788">"Tuntematon soittoääni"</string>
   <plurals name="wifi_available">
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 479fe18..550e09c 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -993,6 +993,18 @@
     <string name="weeks" msgid="6509623834583944518">"semaines"</string>
     <string name="year" msgid="4001118221013892076">"année"</string>
     <string name="years" msgid="6881577717993213522">"années"</string>
+  <plurals name="duration_seconds">
+    <item quantity="one" msgid="6962015528372969481">"1 seconde"</item>
+    <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> secondes"</item>
+  </plurals>
+  <plurals name="duration_minutes">
+    <item quantity="one" msgid="4915414002546085617">"1 minute"</item>
+    <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> minutes"</item>
+  </plurals>
+  <plurals name="duration_hours">
+    <item quantity="one" msgid="8917467491248809972">"1 heure"</item>
+    <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> heures"</item>
+  </plurals>
     <string name="VideoView_error_title" msgid="3534509135438353077">"Problème vidéo"</string>
     <string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Impossible de lire cette vidéo en streaming sur cet appareil."</string>
     <string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Impossible de lire la vidéo."</string>
@@ -1082,7 +1094,7 @@
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Volume des notifications"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Sonnerie par défaut"</string>
     <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Sonnerie par défaut (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
-    <string name="ringtone_silent" msgid="4440324407807468713">"Silencieux"</string>
+    <string name="ringtone_silent" msgid="7937634392408977062">"Aucune"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Sonneries"</string>
     <string name="ringtone_unknown" msgid="5477919988701784788">"Sonnerie inconnue"</string>
   <plurals name="wifi_available">
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 65aa563..11972fa 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -993,6 +993,18 @@
     <string name="weeks" msgid="6509623834583944518">"सप्ताह"</string>
     <string name="year" msgid="4001118221013892076">"वर्ष"</string>
     <string name="years" msgid="6881577717993213522">"वर्ष"</string>
+  <plurals name="duration_seconds">
+    <item quantity="one" msgid="6962015528372969481">"1 सेकंड"</item>
+    <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> सेकंड"</item>
+  </plurals>
+  <plurals name="duration_minutes">
+    <item quantity="one" msgid="4915414002546085617">"1 मिनट"</item>
+    <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> मिनट"</item>
+  </plurals>
+  <plurals name="duration_hours">
+    <item quantity="one" msgid="8917467491248809972">"1 घंटा"</item>
+    <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> घंटे"</item>
+  </plurals>
     <string name="VideoView_error_title" msgid="3534509135438353077">"वीडियो समस्‍याएं"</string>
     <string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"यह वीडियो इस उपकरण पर स्ट्रीमिंग के लिए मान्‍य नहीं है."</string>
     <string name="VideoView_error_text_unknown" msgid="3450439155187810085">"यह वीडियो नहीं चलाया जा सकता."</string>
@@ -1082,7 +1094,7 @@
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"सूचना वॉल्‍यूम"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"डिफ़ॉल्‍ट रिंगटोन"</string>
     <string name="ringtone_default_with_actual" msgid="8129563480895990372">"डिफ़ॉल्‍ट रिंगटोन (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
-    <string name="ringtone_silent" msgid="4440324407807468713">"मौन"</string>
+    <string name="ringtone_silent" msgid="7937634392408977062">"कोई नहीं"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"रिंगटोन"</string>
     <string name="ringtone_unknown" msgid="5477919988701784788">"अज्ञात रिंगटोन"</string>
   <plurals name="wifi_available">
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index e279216..c13dd42 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -59,7 +59,7 @@
     <string name="BaMmi" msgid="455193067926770581">"Zabrana poziva"</string>
     <string name="PwdMmi" msgid="7043715687905254199">"Promjena zaporke"</string>
     <string name="PinMmi" msgid="3113117780361190304">"PIN je promijenjen"</string>
-    <string name="CnipMmi" msgid="3110534680557857162">"Pozivni je broj prisutan"</string>
+    <string name="CnipMmi" msgid="3110534680557857162">"Sadržan je pozivni broj"</string>
     <string name="CnirMmi" msgid="3062102121430548731">"Pozivni broj je ograničen"</string>
     <string name="ThreeWCMmi" msgid="9051047170321190368">"Trostrani poziv"</string>
     <string name="RuacMmi" msgid="7827887459138308886">"Odbijanje neželjenih i neugodnih poziva"</string>
@@ -993,6 +993,18 @@
     <string name="weeks" msgid="6509623834583944518">"tjedna"</string>
     <string name="year" msgid="4001118221013892076">"godina"</string>
     <string name="years" msgid="6881577717993213522">"godina"</string>
+  <plurals name="duration_seconds">
+    <item quantity="one" msgid="6962015528372969481">"1 s"</item>
+    <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> s"</item>
+  </plurals>
+  <plurals name="duration_minutes">
+    <item quantity="one" msgid="4915414002546085617">"1 min"</item>
+    <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> min"</item>
+  </plurals>
+  <plurals name="duration_hours">
+    <item quantity="one" msgid="8917467491248809972">"1 sat"</item>
+    <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> h"</item>
+  </plurals>
     <string name="VideoView_error_title" msgid="3534509135438353077">"Problem s videozapisom"</string>
     <string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Ovaj videozapis nije valjan za streaming na ovaj uređaj."</string>
     <string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Ovaj videozapis nije moguće reproducirati."</string>
@@ -1082,7 +1094,7 @@
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Glasnoća obavijesti"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Zadana melodija zvona"</string>
     <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Zadana melodija zvona (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
-    <string name="ringtone_silent" msgid="4440324407807468713">"Bešumno"</string>
+    <string name="ringtone_silent" msgid="7937634392408977062">"Nijedan"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Melodije zvona"</string>
     <string name="ringtone_unknown" msgid="5477919988701784788">"Nepoznata melodija zvona"</string>
   <plurals name="wifi_available">
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 88f4046..e1e7901 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -993,6 +993,18 @@
     <string name="weeks" msgid="6509623834583944518">"hét"</string>
     <string name="year" msgid="4001118221013892076">"év"</string>
     <string name="years" msgid="6881577717993213522">"év"</string>
+  <plurals name="duration_seconds">
+    <item quantity="one" msgid="6962015528372969481">"1 másodperc"</item>
+    <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> másodperc"</item>
+  </plurals>
+  <plurals name="duration_minutes">
+    <item quantity="one" msgid="4915414002546085617">"1 perc"</item>
+    <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> perc"</item>
+  </plurals>
+  <plurals name="duration_hours">
+    <item quantity="one" msgid="8917467491248809972">"1 óra"</item>
+    <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> óra"</item>
+  </plurals>
     <string name="VideoView_error_title" msgid="3534509135438353077">"Videoprobléma"</string>
     <string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Ezt a videót nem lehet megjeleníteni ezen az eszközön."</string>
     <string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Nem lehet lejátszani ezt a videót."</string>
@@ -1082,7 +1094,7 @@
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Értesítés hangereje"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Alapértelmezett csengőhang"</string>
     <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Alapértelmezett csengőhang (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
-    <string name="ringtone_silent" msgid="4440324407807468713">"Néma"</string>
+    <string name="ringtone_silent" msgid="7937634392408977062">"Egyik sem"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Csengőhangok"</string>
     <string name="ringtone_unknown" msgid="5477919988701784788">"Ismeretlen csengőhang"</string>
   <plurals name="wifi_available">
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index b5dfcd5..d6a16ca 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -417,9 +417,9 @@
     <string name="permlab_writeProfile" msgid="907793628777397643">"ubah kartu kontak Anda"</string>
     <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Memungkinkan aplikasi mengubah atau menambah informasi profil pribadi yang tersimpan di perangkat Anda, seperti nama dan informasi kontak. Ini berarti aplikasi tersebut dapat mengenali Anda dan mengirim informasi profil Anda ke orang lain."</string>
     <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"membaca aliran sosial Anda"</string>
-    <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Memungkinkan aplikasi mengakses dan menyinkronkan pembaruan sosial dari Anda dan teman. Hati-hati ketika berbagi informasi -- izin ini memungkinkan aplikasi membaca komunikasi antara Anda dan teman di jaringan sosial, terlepas dari kerahasiaan. Catatan: izin ini tidak dapat diberlakukan di semua jaringan sosial."</string>
+    <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Memungkinkan aplikasi mengakses dan menyinkronkan pembaruan sosial dari Anda dan teman. Hati-hati ketika berbagi informasi -- izin ini memungkinkan aplikasi membaca komunikasi antara Anda dan teman di jejaring sosial, terlepas dari kerahasiaan. Catatan: izin ini tidak dapat diberlakukan di semua jejaring sosial."</string>
     <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"menulis ke aliran sosial Anda"</string>
-    <string name="permdesc_writeSocialStream" product="default" msgid="3086557552204114849">"Memungkinkan aplikasi menampilkan pembaruan sosial dari teman Anda. Berhati-hatilah saat berbagi informasi -- izin ini memungkinkan aplikasi menghasilkan pesan yang mungkin kelihatannya berasal dari seorang teman. Catatan: izin ini tidak dapat diberlakukan di semua jaringan sosial."</string>
+    <string name="permdesc_writeSocialStream" product="default" msgid="3086557552204114849">"Memungkinkan aplikasi menampilkan pembaruan sosial dari teman Anda. Berhati-hatilah saat berbagi informasi -- izin ini memungkinkan aplikasi menghasilkan pesan yang mungkin kelihatannya berasal dari seorang teman. Catatan: izin ini tidak dapat diberlakukan di semua jejaring sosial."</string>
     <string name="permlab_readCalendar" msgid="5972727560257612398">"baca acara kalender serta informasi rahasia"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="4216462049057658723">"Memungkinkan aplikasi membaca semua acara kalender yang tersimpan di tablet Anda, termasuk milik teman atau rekan kerja. Izin ini memungkinkan aplikasi berbagi atau menyimpan data kalender Anda, terlepas dari kerahasiaan atau sensitivitas."</string>
     <string name="permdesc_readCalendar" product="default" msgid="7434548682470851583">"Memungkinkan aplikasi membaca semua acara kalender yang tersimpan di ponsel Anda, termasuk milik teman atau rekan kerja. Izin ini memungkinkan aplikasi berbagi atau menyimpan data kalender Anda, terlepas dari kerahasiaan atau sensitivitas."</string>
@@ -993,6 +993,18 @@
     <string name="weeks" msgid="6509623834583944518">"minggu"</string>
     <string name="year" msgid="4001118221013892076">"tahun"</string>
     <string name="years" msgid="6881577717993213522">"tahun"</string>
+  <plurals name="duration_seconds">
+    <item quantity="one" msgid="6962015528372969481">"1 detik"</item>
+    <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> detik"</item>
+  </plurals>
+  <plurals name="duration_minutes">
+    <item quantity="one" msgid="4915414002546085617">"1 menit"</item>
+    <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> menit"</item>
+  </plurals>
+  <plurals name="duration_hours">
+    <item quantity="one" msgid="8917467491248809972">"1 jam"</item>
+    <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> jam"</item>
+  </plurals>
     <string name="VideoView_error_title" msgid="3534509135438353077">"Masalah video"</string>
     <string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Video ini tidak valid untuk pengaliran ke perangkat ini."</string>
     <string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Tidak dapat memutar video ini."</string>
@@ -1082,7 +1094,7 @@
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Volume pemberitahuan"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Nada dering default"</string>
     <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Nada dering default (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
-    <string name="ringtone_silent" msgid="4440324407807468713">"Senyap"</string>
+    <string name="ringtone_silent" msgid="7937634392408977062">"Tidak Ada"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Nada dering"</string>
     <string name="ringtone_unknown" msgid="5477919988701784788">"Nada dering tidak dikenal"</string>
   <plurals name="wifi_available">
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 0edb0c1..2257daa 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -993,6 +993,18 @@
     <string name="weeks" msgid="6509623834583944518">"settimane"</string>
     <string name="year" msgid="4001118221013892076">"anno"</string>
     <string name="years" msgid="6881577717993213522">"anni"</string>
+  <plurals name="duration_seconds">
+    <item quantity="one" msgid="6962015528372969481">"1 secondo"</item>
+    <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> secondi"</item>
+  </plurals>
+  <plurals name="duration_minutes">
+    <item quantity="one" msgid="4915414002546085617">"1 minuto"</item>
+    <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> minuti"</item>
+  </plurals>
+  <plurals name="duration_hours">
+    <item quantity="one" msgid="8917467491248809972">"1 ora"</item>
+    <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> ore"</item>
+  </plurals>
     <string name="VideoView_error_title" msgid="3534509135438353077">"Problemi video"</string>
     <string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Questo video non è valido per lo streaming su questo dispositivo."</string>
     <string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Impossibile riprodurre il video."</string>
@@ -1082,7 +1094,7 @@
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Volume notifiche"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Suoneria predefinita"</string>
     <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Suoneria predefinita (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
-    <string name="ringtone_silent" msgid="4440324407807468713">"Silenzioso"</string>
+    <string name="ringtone_silent" msgid="7937634392408977062">"Nessuna"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Suonerie"</string>
     <string name="ringtone_unknown" msgid="5477919988701784788">"Suoneria sconosciuta"</string>
   <plurals name="wifi_available">
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index bb6a3ac..ce51ef4 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -993,6 +993,18 @@
     <string name="weeks" msgid="6509623834583944518">"שבועות"</string>
     <string name="year" msgid="4001118221013892076">"שנה"</string>
     <string name="years" msgid="6881577717993213522">"שנים"</string>
+  <plurals name="duration_seconds">
+    <item quantity="one" msgid="6962015528372969481">"שנייה אחת"</item>
+    <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> שניות"</item>
+  </plurals>
+  <plurals name="duration_minutes">
+    <item quantity="one" msgid="4915414002546085617">"דקה אחת"</item>
+    <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> דקות"</item>
+  </plurals>
+  <plurals name="duration_hours">
+    <item quantity="one" msgid="8917467491248809972">"שעה אחת"</item>
+    <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> שעות"</item>
+  </plurals>
     <string name="VideoView_error_title" msgid="3534509135438353077">"בעיה בווידאו"</string>
     <string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"סרטון זה אינו חוקי להעברה כמדיה זורמת למכשיר זה."</string>
     <string name="VideoView_error_text_unknown" msgid="3450439155187810085">"לא ניתן להפעיל סרטון זה."</string>
@@ -1034,7 +1046,7 @@
     <string name="chooseUsbActivity" msgid="6894748416073583509">"בחר יישום עבור התקן ה-USB"</string>
     <string name="noApplications" msgid="2991814273936504689">"אין יישומים שיכולים לבצע פעולה זו."</string>
     <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"לצערנו, פעולת ה<xliff:g id="APPLICATION">%1$s</xliff:g> הופסקה."</string>
+    <string name="aerr_application" msgid="932628488013092776">"לצערנו, פעולת <xliff:g id="APPLICATION">%1$s</xliff:g> הופסקה."</string>
     <string name="aerr_process" msgid="4507058997035697579">"לצערנו, התהליך <xliff:g id="PROCESS">%1$s</xliff:g> הופסק."</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
     <string name="anr_activity_application" msgid="1904477189057199066">"<xliff:g id="APPLICATION">%2$s</xliff:g> אינו מגיב."\n\n"תרצה לסגור אותו?"</string>
@@ -1082,7 +1094,7 @@
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"עוצמת קול של התראות"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"רינגטון ברירת מחדל"</string>
     <string name="ringtone_default_with_actual" msgid="8129563480895990372">"רינגטון ברירת מחדל (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
-    <string name="ringtone_silent" msgid="4440324407807468713">"שקט"</string>
+    <string name="ringtone_silent" msgid="7937634392408977062">"ללא"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"רינגטונים"</string>
     <string name="ringtone_unknown" msgid="5477919988701784788">"רינגטון לא ידוע"</string>
   <plurals name="wifi_available">
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 8af0fed..f2ca7c6 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -993,6 +993,18 @@
     <string name="weeks" msgid="6509623834583944518">"週間"</string>
     <string name="year" msgid="4001118221013892076">"年"</string>
     <string name="years" msgid="6881577717993213522">"年"</string>
+  <plurals name="duration_seconds">
+    <item quantity="one" msgid="6962015528372969481">"1秒"</item>
+    <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g>秒"</item>
+  </plurals>
+  <plurals name="duration_minutes">
+    <item quantity="one" msgid="4915414002546085617">"1分"</item>
+    <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g>分"</item>
+  </plurals>
+  <plurals name="duration_hours">
+    <item quantity="one" msgid="8917467491248809972">"1時間"</item>
+    <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g>時間"</item>
+  </plurals>
     <string name="VideoView_error_title" msgid="3534509135438353077">"動画の問題"</string>
     <string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"この動画はこの端末にストリーミングできません。"</string>
     <string name="VideoView_error_text_unknown" msgid="3450439155187810085">"この動画を再生できません。"</string>
@@ -1082,7 +1094,7 @@
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"通知音量"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"プリセット着信音"</string>
     <string name="ringtone_default_with_actual" msgid="8129563480895990372">"端末の基本着信音(<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
-    <string name="ringtone_silent" msgid="4440324407807468713">"サイレント"</string>
+    <string name="ringtone_silent" msgid="7937634392408977062">"なし"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"着信音"</string>
     <string name="ringtone_unknown" msgid="5477919988701784788">"不明な着信音"</string>
   <plurals name="wifi_available">
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 37c6b01..3e17643 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -570,9 +570,9 @@
     <string name="permlab_disableKeyguard" msgid="3598496301486439258">"화면 잠금 사용 중지"</string>
     <string name="permdesc_disableKeyguard" msgid="6034203065077122992">"앱이 키 잠금 및 관련 비밀번호 보안을 사용중지할 수 있도록 허용합니다. 예를 들어, 휴대전화가 수신전화를 받을 때 키 잠금을 사용중지했다가 통화가 끝나면 키 잠금을 다시 사용할 수 있습니다."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"동기화 설정 읽기"</string>
-    <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"앱이 계정의 동기화 설정을 읽을 수 있도록 허용합니다. 예를 들어, 계정에서 피플 앱을 동기화할지 여부를 확인할 수 있습니다."</string>
+    <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"앱이 계정의 동기화 설정을 읽을 수 있도록 허용합니다. 예를 들어, 계정에서 주소록 앱을 동기화할지 여부를 확인할 수 있습니다."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"동기화 사용 및 사용 중지 전환"</string>
-    <string name="permdesc_writeSyncSettings" msgid="8956262591306369868">"앱이 계정의 동기화 설정을 수정할 수 있도록 허용합니다. 예를 들어, 계정에서 피플 앱을 동기화할 목적으로 앱이 사용될 수 있습니다."</string>
+    <string name="permdesc_writeSyncSettings" msgid="8956262591306369868">"앱이 계정의 동기화 설정을 수정할 수 있도록 허용합니다. 예를 들어, 계정에서 주소록 앱을 동기화할 목적으로 앱이 사용될 수 있습니다."</string>
     <string name="permlab_readSyncStats" msgid="7396577451360202448">"동기화 통계 읽기"</string>
     <string name="permdesc_readSyncStats" msgid="1510143761757606156">"앱이 동기화된 일정의 기록이나 동기화된 데이터의 양 등을 포함하여 계정의 동기화 통계를 읽을 수 있도록 허용합니다."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"가입된 피드 읽기"</string>
@@ -993,6 +993,18 @@
     <string name="weeks" msgid="6509623834583944518">"주"</string>
     <string name="year" msgid="4001118221013892076">"년"</string>
     <string name="years" msgid="6881577717993213522">"년"</string>
+  <plurals name="duration_seconds">
+    <item quantity="one" msgid="6962015528372969481">"1초"</item>
+    <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g>초"</item>
+  </plurals>
+  <plurals name="duration_minutes">
+    <item quantity="one" msgid="4915414002546085617">"1분"</item>
+    <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g>분"</item>
+  </plurals>
+  <plurals name="duration_hours">
+    <item quantity="one" msgid="8917467491248809972">"1시간"</item>
+    <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g>시간"</item>
+  </plurals>
     <string name="VideoView_error_title" msgid="3534509135438353077">"영상 문제"</string>
     <string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"이 기기로 스트리밍하기에 적합하지 않은 동영상입니다."</string>
     <string name="VideoView_error_text_unknown" msgid="3450439155187810085">"동영상을 재생할 수 없습니다."</string>
@@ -1082,7 +1094,7 @@
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"알림 볼륨"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"기본 벨소리"</string>
     <string name="ringtone_default_with_actual" msgid="8129563480895990372">"기본 벨소리(<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
-    <string name="ringtone_silent" msgid="4440324407807468713">"무음"</string>
+    <string name="ringtone_silent" msgid="7937634392408977062">"없음"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"벨소리"</string>
     <string name="ringtone_unknown" msgid="5477919988701784788">"알 수 없는 벨소리"</string>
   <plurals name="wifi_available">
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index f2ad504..43ea17d 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -993,6 +993,18 @@
     <string name="weeks" msgid="6509623834583944518">"sav."</string>
     <string name="year" msgid="4001118221013892076">"metai"</string>
     <string name="years" msgid="6881577717993213522">"metai"</string>
+  <plurals name="duration_seconds">
+    <item quantity="one" msgid="6962015528372969481">"1 sek."</item>
+    <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> sek."</item>
+  </plurals>
+  <plurals name="duration_minutes">
+    <item quantity="one" msgid="4915414002546085617">"1 min."</item>
+    <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> min."</item>
+  </plurals>
+  <plurals name="duration_hours">
+    <item quantity="one" msgid="8917467491248809972">"1 val."</item>
+    <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> val."</item>
+  </plurals>
     <string name="VideoView_error_title" msgid="3534509135438353077">"Vaizdo įrašo problema"</string>
     <string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Šis vaizdo įrašas netinkamas srautiniu būdu perduoti į šį įrenginį."</string>
     <string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Negalima paleisti šio vaizdo įrašo."</string>
@@ -1082,7 +1094,7 @@
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Pranešimo apimtis"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Numatytasis skambėjimo tonas"</string>
     <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Numatytasis skambėjimo tonas (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
-    <string name="ringtone_silent" msgid="4440324407807468713">"Tylus"</string>
+    <string name="ringtone_silent" msgid="7937634392408977062">"Nėra"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Skambėjimo tonai"</string>
     <string name="ringtone_unknown" msgid="5477919988701784788">"Nežinomas skambėjimo tonas"</string>
   <plurals name="wifi_available">
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index ee0b023..d563a05 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -993,6 +993,18 @@
     <string name="weeks" msgid="6509623834583944518">"nedēļas"</string>
     <string name="year" msgid="4001118221013892076">"gads"</string>
     <string name="years" msgid="6881577717993213522">"gadi"</string>
+  <plurals name="duration_seconds">
+    <item quantity="one" msgid="6962015528372969481">"1 s"</item>
+    <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> s"</item>
+  </plurals>
+  <plurals name="duration_minutes">
+    <item quantity="one" msgid="4915414002546085617">"1 min"</item>
+    <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> min"</item>
+  </plurals>
+  <plurals name="duration_hours">
+    <item quantity="one" msgid="8917467491248809972">"1 h"</item>
+    <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> h"</item>
+  </plurals>
     <string name="VideoView_error_title" msgid="3534509135438353077">"Video problēma"</string>
     <string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Šis video nav derīgs straumēšanai uz šo ierīci."</string>
     <string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Nevar atskaņot šo video."</string>
@@ -1082,7 +1094,7 @@
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Paziņojumu skaļums"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Noklusējuma zvana signāls"</string>
     <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Noklusējuma zvana signāls (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
-    <string name="ringtone_silent" msgid="4440324407807468713">"Klusums"</string>
+    <string name="ringtone_silent" msgid="7937634392408977062">"Nav"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Zvana signāli"</string>
     <string name="ringtone_unknown" msgid="5477919988701784788">"Nezināms zvana signāls"</string>
   <plurals name="wifi_available">
diff --git a/core/res/res/values-mcc286/config.xml b/core/res/res/values-mcc286/config.xml
new file mode 100755
index 0000000..d99d051
--- /dev/null
+++ b/core/res/res/values-mcc286/config.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** 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.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+     for different hardware and product builds.  DO NOT TRANSLATE. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+    <!-- National Language Identifier codes for the following two config items.
+         (from 3GPP TS 23.038 V9.1.1 Table 6.2.1.2.4.1):
+          0  - reserved
+          1  - Turkish
+          2  - Spanish (single shift table only)
+          3  - Portuguese
+          4  - Bengali
+          5  - Gujarati
+          6  - Hindi
+          7  - Kannada
+          8  - Malayalam
+          9  - Oriya
+         10  - Punjabi
+         11  - Tamil
+         12  - Telugu
+         13  - Urdu
+         14+ - reserved -->
+
+    <!-- National language single shift tables to enable for SMS encoding.
+         Decoding is always enabled. 3GPP TS 23.038 states that this feature
+         should not be enabled until a formal request is issued by the relevant
+         national regulatory body. Array elements are codes from the table above.
+         Example 1: devices sold in Turkey must include table 1 to conform with
+           By-Law Number 27230. (http://www.btk.gov.tr/eng/pdf/2009/BY-LAW_SMS.pdf)
+         Example 2: devices sold in India should include tables 4 through 13
+           to enable use of the new Release 9 tables for Indic languages. -->
+    <integer-array name="config_sms_enabled_single_shift_tables"><item>1</item></integer-array>
+
+    <!-- National language locking shift tables to enable for SMS encoding.
+         Decoding is always enabled. 3GPP TS 23.038 states that this feature
+         should not be enabled until a formal request is issued by the relevant
+         national regulatory body. Array elements are codes from the table above.
+         Example 1: devices sold in Turkey must include table 1 after the
+           Turkish Telecommunication Authority requires locking shift encoding
+           to be enabled (est. July 2012). (http://www.btk.gov.tr/eng/pdf/2009/BY-LAW_SMS.pdf)
+           See also: http://www.mobitech.com.tr/tr/ersanozturkblog_en/index.php?entry=entry090223-160014
+         Example 2: devices sold in India should include tables 4 through 13
+         to enable use of the new Release 9 tables for Indic languages. -->
+    <!-- <integer-array name="config_sms_enabled_locking_shift_tables"></integer-array> -->
+
+</resources>
diff --git a/core/res/res/values-mcc450/config.xml b/core/res/res/values-mcc450/config.xml
new file mode 100644
index 0000000..2a2bd76
--- /dev/null
+++ b/core/res/res/values-mcc450/config.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources>
+
+    <!-- Whether camera shutter sound is forced or not  (country specific). -->
+    <bool name="config_camera_sound_forced">true</bool>
+
+</resources>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index e89f70f..ead43f1 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -993,6 +993,18 @@
     <string name="weeks" msgid="6509623834583944518">"minggu"</string>
     <string name="year" msgid="4001118221013892076">"tahun"</string>
     <string name="years" msgid="6881577717993213522">"tahun"</string>
+  <plurals name="duration_seconds">
+    <item quantity="one" msgid="6962015528372969481">"1 saat"</item>
+    <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> saat"</item>
+  </plurals>
+  <plurals name="duration_minutes">
+    <item quantity="one" msgid="4915414002546085617">"1 minit"</item>
+    <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> minit"</item>
+  </plurals>
+  <plurals name="duration_hours">
+    <item quantity="one" msgid="8917467491248809972">"1 jam"</item>
+    <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> jam"</item>
+  </plurals>
     <string name="VideoView_error_title" msgid="3534509135438353077">"Masalah video"</string>
     <string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Maaf, video ini tidak sah untuk penstriman ke peranti ini."</string>
     <string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Tidak dapat mainkan video ini."</string>
@@ -1082,7 +1094,7 @@
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Kelantangan pemberitahuan"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Nada dering lalai"</string>
     <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Nada dering lalai (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
-    <string name="ringtone_silent" msgid="4440324407807468713">"Senyap"</string>
+    <string name="ringtone_silent" msgid="7937634392408977062">"Tiada"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Nada dering"</string>
     <string name="ringtone_unknown" msgid="5477919988701784788">"Nada dering tidak diketahui"</string>
   <plurals name="wifi_available">
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 42df589..b715c9f 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -993,6 +993,18 @@
     <string name="weeks" msgid="6509623834583944518">"uker"</string>
     <string name="year" msgid="4001118221013892076">"år"</string>
     <string name="years" msgid="6881577717993213522">"år"</string>
+  <plurals name="duration_seconds">
+    <item quantity="one" msgid="6962015528372969481">"Ett sekund"</item>
+    <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> sekunder"</item>
+  </plurals>
+  <plurals name="duration_minutes">
+    <item quantity="one" msgid="4915414002546085617">"Ett minutt"</item>
+    <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> minutter"</item>
+  </plurals>
+  <plurals name="duration_hours">
+    <item quantity="one" msgid="8917467491248809972">"Én time"</item>
+    <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> timer"</item>
+  </plurals>
     <string name="VideoView_error_title" msgid="3534509135438353077">"Videoproblem"</string>
     <string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Denne videoen er ikke gyldig for direkteavspilling på enheten."</string>
     <string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Kan ikke spille av denne videoen."</string>
@@ -1082,7 +1094,7 @@
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Varslingsvolum"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Standard ringetone"</string>
     <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Standard ringetone (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
-    <string name="ringtone_silent" msgid="4440324407807468713">"Stille"</string>
+    <string name="ringtone_silent" msgid="7937634392408977062">"Ingen"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Ringetoner"</string>
     <string name="ringtone_unknown" msgid="5477919988701784788">"Ukjent ringetone"</string>
   <plurals name="wifi_available">
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 21fe1cc..0f0e3d9 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -993,6 +993,18 @@
     <string name="weeks" msgid="6509623834583944518">"weken"</string>
     <string name="year" msgid="4001118221013892076">"jaar"</string>
     <string name="years" msgid="6881577717993213522">"jaren"</string>
+  <plurals name="duration_seconds">
+    <item quantity="one" msgid="6962015528372969481">"1 seconde"</item>
+    <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> seconden"</item>
+  </plurals>
+  <plurals name="duration_minutes">
+    <item quantity="one" msgid="4915414002546085617">"1 minuut"</item>
+    <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> minuten"</item>
+  </plurals>
+  <plurals name="duration_hours">
+    <item quantity="one" msgid="8917467491248809972">"1 uur"</item>
+    <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> uur"</item>
+  </plurals>
     <string name="VideoView_error_title" msgid="3534509135438353077">"Probleem met video"</string>
     <string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Deze video kan niet worden gestreamd naar dit apparaat."</string>
     <string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Deze video kan niet worden afgespeeld."</string>
@@ -1082,7 +1094,7 @@
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Meldingsvolume"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Standaardbeltoon"</string>
     <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Standaardbeltoon (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
-    <string name="ringtone_silent" msgid="4440324407807468713">"Stil"</string>
+    <string name="ringtone_silent" msgid="7937634392408977062">"Geen"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Beltonen"</string>
     <string name="ringtone_unknown" msgid="5477919988701784788">"Onbekende beltoon"</string>
   <plurals name="wifi_available">
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index d0f1db3..417ee78 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -993,6 +993,18 @@
     <string name="weeks" msgid="6509623834583944518">"tygodni"</string>
     <string name="year" msgid="4001118221013892076">"rok"</string>
     <string name="years" msgid="6881577717993213522">"lat"</string>
+  <plurals name="duration_seconds">
+    <item quantity="one" msgid="6962015528372969481">"1 sekunda"</item>
+    <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> s"</item>
+  </plurals>
+  <plurals name="duration_minutes">
+    <item quantity="one" msgid="4915414002546085617">"1 minuta"</item>
+    <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> min"</item>
+  </plurals>
+  <plurals name="duration_hours">
+    <item quantity="one" msgid="8917467491248809972">"1 godzina"</item>
+    <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> godz."</item>
+  </plurals>
     <string name="VideoView_error_title" msgid="3534509135438353077">"Problem z filmem"</string>
     <string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Ten film nie nadaje się do strumieniowego przesyłania do tego urządzenia."</string>
     <string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Nie można odtworzyć tego filmu."</string>
@@ -1082,7 +1094,7 @@
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Głośność powiadomień"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Dzwonek domyślny"</string>
     <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Dzwonek domyślny (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
-    <string name="ringtone_silent" msgid="4440324407807468713">"Cichy"</string>
+    <string name="ringtone_silent" msgid="7937634392408977062">"Brak"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Dzwonki"</string>
     <string name="ringtone_unknown" msgid="5477919988701784788">"Nieznany dzwonek"</string>
   <plurals name="wifi_available">
@@ -1351,7 +1363,7 @@
     <string name="data_usage_limit_body" msgid="3317964706973601386">"Dotknij, aby włączyć."</string>
     <string name="data_usage_3g_limit_snoozed_title" msgid="7026739121138005231">"Przekroczono limit danych 2G/3G"</string>
     <string name="data_usage_4g_limit_snoozed_title" msgid="1106562779311209039">"Przekroczono limit danych 4G"</string>
-    <string name="data_usage_mobile_limit_snoozed_title" msgid="279240572165412168">"Przekroczono limit danych komór."</string>
+    <string name="data_usage_mobile_limit_snoozed_title" msgid="279240572165412168">"Przekroczenie limitu danych"</string>
     <string name="data_usage_wifi_limit_snoozed_title" msgid="8743856006384825974">"Przekroczono limit danych Wi-Fi"</string>
     <string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<xliff:g id="SIZE">%s</xliff:g> ponad określony limit"</string>
     <string name="data_usage_restricted_title" msgid="5965157361036321914">"Dane w tle są ograniczone"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index fd7211e..ba97b8f 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -762,7 +762,7 @@
     <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Tentar novamente"</string>
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Excedido o n.º máximo de tentativas de Desbloqueio Através do Rosto"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"A carregar, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
-    <string name="lockscreen_charged" msgid="321635745684060624">"Cobrado"</string>
+    <string name="lockscreen_charged" msgid="321635745684060624">"Carregado"</string>
     <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Ligue o carregador."</string>
     <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Nenhum cartão SIM"</string>
@@ -993,6 +993,18 @@
     <string name="weeks" msgid="6509623834583944518">"semanas"</string>
     <string name="year" msgid="4001118221013892076">"ano"</string>
     <string name="years" msgid="6881577717993213522">"anos"</string>
+  <plurals name="duration_seconds">
+    <item quantity="one" msgid="6962015528372969481">"1 segundo"</item>
+    <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> segundos"</item>
+  </plurals>
+  <plurals name="duration_minutes">
+    <item quantity="one" msgid="4915414002546085617">"1 minuto"</item>
+    <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> minutos"</item>
+  </plurals>
+  <plurals name="duration_hours">
+    <item quantity="one" msgid="8917467491248809972">"1 hora"</item>
+    <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> horas"</item>
+  </plurals>
     <string name="VideoView_error_title" msgid="3534509135438353077">"Problema com o vídeo"</string>
     <string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Este vídeo não é válido para transmissão em fluxo contínuo neste aparelho."</string>
     <string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Não é possível reproduzir este vídeo."</string>
@@ -1082,7 +1094,7 @@
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Volume de notificações"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Toque predefinido"</string>
     <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Toque predefinido (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
-    <string name="ringtone_silent" msgid="4440324407807468713">"Silencioso"</string>
+    <string name="ringtone_silent" msgid="7937634392408977062">"Nada"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Toques"</string>
     <string name="ringtone_unknown" msgid="5477919988701784788">"Toque desconhecido"</string>
   <plurals name="wifi_available">
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index ed656fe..5dfbe05 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -993,6 +993,18 @@
     <string name="weeks" msgid="6509623834583944518">"semanas"</string>
     <string name="year" msgid="4001118221013892076">"ano"</string>
     <string name="years" msgid="6881577717993213522">"anos"</string>
+  <plurals name="duration_seconds">
+    <item quantity="one" msgid="6962015528372969481">"Um segundo"</item>
+    <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> segundos"</item>
+  </plurals>
+  <plurals name="duration_minutes">
+    <item quantity="one" msgid="4915414002546085617">"Um minuto"</item>
+    <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> minutos"</item>
+  </plurals>
+  <plurals name="duration_hours">
+    <item quantity="one" msgid="8917467491248809972">"Uma hora"</item>
+    <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> horas"</item>
+  </plurals>
     <string name="VideoView_error_title" msgid="3534509135438353077">"Problema com o vídeo"</string>
     <string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Este vídeo não é válido para transmissão neste dispositivo."</string>
     <string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Não é possível reproduzir este vídeo."</string>
@@ -1082,7 +1094,7 @@
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Volume da notificação"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Toque padrão"</string>
     <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Toque padrão (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
-    <string name="ringtone_silent" msgid="4440324407807468713">"Silencioso"</string>
+    <string name="ringtone_silent" msgid="7937634392408977062">"Nenhum"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Toques"</string>
     <string name="ringtone_unknown" msgid="5477919988701784788">"Toque desconhecido"</string>
   <plurals name="wifi_available">
diff --git a/core/res/res/values-rm/strings.xml b/core/res/res/values-rm/strings.xml
index 0e7aaec..799b9a2 100644
--- a/core/res/res/values-rm/strings.xml
+++ b/core/res/res/values-rm/strings.xml
@@ -1558,6 +1558,12 @@
     <string name="weeks" msgid="6509623834583944518">"emnas"</string>
     <string name="year" msgid="4001118221013892076">"onn"</string>
     <string name="years" msgid="6881577717993213522">"onns"</string>
+    <!-- no translation found for duration_seconds:one (6962015528372969481) -->
+    <!-- no translation found for duration_seconds:other (1886107766577166786) -->
+    <!-- no translation found for duration_minutes:one (4915414002546085617) -->
+    <!-- no translation found for duration_minutes:other (3165187169224908775) -->
+    <!-- no translation found for duration_hours:one (8917467491248809972) -->
+    <!-- no translation found for duration_hours:other (3863962854246773930) -->
     <!-- no translation found for VideoView_error_title (3534509135438353077) -->
     <skip />
     <!-- no translation found for VideoView_error_text_invalid_progressive_playback (3186670335938670444) -->
@@ -1693,7 +1699,8 @@
     <skip />
     <string name="ringtone_default" msgid="3789758980357696936">"Tun da scalin predefinì"</string>
     <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Tun da scalin predefinì (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
-    <string name="ringtone_silent" msgid="4440324407807468713">"Silenzius"</string>
+    <!-- no translation found for ringtone_silent (7937634392408977062) -->
+    <skip />
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Tuns da scalin"</string>
     <string name="ringtone_unknown" msgid="5477919988701784788">"Tun da scalin nunenconuschent"</string>
   <plurals name="wifi_available">
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index f274acd..94f6263 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -993,6 +993,18 @@
     <string name="weeks" msgid="6509623834583944518">"săptămâni"</string>
     <string name="year" msgid="4001118221013892076">"an"</string>
     <string name="years" msgid="6881577717993213522">"ani"</string>
+  <plurals name="duration_seconds">
+    <item quantity="one" msgid="6962015528372969481">"O secundă"</item>
+    <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> (de) secunde"</item>
+  </plurals>
+  <plurals name="duration_minutes">
+    <item quantity="one" msgid="4915414002546085617">"Un minut"</item>
+    <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> (de) minute"</item>
+  </plurals>
+  <plurals name="duration_hours">
+    <item quantity="one" msgid="8917467491248809972">"O oră"</item>
+    <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> (de) ore"</item>
+  </plurals>
     <string name="VideoView_error_title" msgid="3534509135438353077">"Problemă video"</string>
     <string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Acest fişier video nu este valid pentru a fi transmis în flux către acest dispozitiv."</string>
     <string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Nu puteţi reda acest videoclip"</string>
@@ -1082,7 +1094,7 @@
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Volum notificare"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Ton de apel prestabilit"</string>
     <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Ton de apel prestabilit (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
-    <string name="ringtone_silent" msgid="4440324407807468713">"Silenţios"</string>
+    <string name="ringtone_silent" msgid="7937634392408977062">"Niciunul"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Tonuri de apel"</string>
     <string name="ringtone_unknown" msgid="5477919988701784788">"Ton de apel necunoscut"</string>
   <plurals name="wifi_available">
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 2ccd436..9ff53cd 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -993,6 +993,18 @@
     <string name="weeks" msgid="6509623834583944518">"нед."</string>
     <string name="year" msgid="4001118221013892076">"г."</string>
     <string name="years" msgid="6881577717993213522">"г."</string>
+  <plurals name="duration_seconds">
+    <item quantity="one" msgid="6962015528372969481">"1 сек."</item>
+    <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> сек."</item>
+  </plurals>
+  <plurals name="duration_minutes">
+    <item quantity="one" msgid="4915414002546085617">"1 мин."</item>
+    <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> мин."</item>
+  </plurals>
+  <plurals name="duration_hours">
+    <item quantity="one" msgid="8917467491248809972">"1 ч."</item>
+    <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> ч."</item>
+  </plurals>
     <string name="VideoView_error_title" msgid="3534509135438353077">"Ошибка"</string>
     <string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Это видео не предназначено для потокового воспроизведения на данном устройстве."</string>
     <string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Не удалось воспроизвести видео."</string>
@@ -1082,7 +1094,7 @@
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Громкость уведомлений"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Мелодия по умолчанию"</string>
     <string name="ringtone_default_with_actual" msgid="8129563480895990372">"По умолчанию (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
-    <string name="ringtone_silent" msgid="4440324407807468713">"Без звука"</string>
+    <string name="ringtone_silent" msgid="7937634392408977062">"Без звука"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Мелодии"</string>
     <string name="ringtone_unknown" msgid="5477919988701784788">"Неизвестная мелодия"</string>
   <plurals name="wifi_available">
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index c364380..8ea6632 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -993,6 +993,18 @@
     <string name="weeks" msgid="6509623834583944518">"týždne"</string>
     <string name="year" msgid="4001118221013892076">"rok"</string>
     <string name="years" msgid="6881577717993213522">"roky"</string>
+  <plurals name="duration_seconds">
+    <item quantity="one" msgid="6962015528372969481">"1 s"</item>
+    <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> s"</item>
+  </plurals>
+  <plurals name="duration_minutes">
+    <item quantity="one" msgid="4915414002546085617">"1 min."</item>
+    <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> min."</item>
+  </plurals>
+  <plurals name="duration_hours">
+    <item quantity="one" msgid="8917467491248809972">"1 hod."</item>
+    <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> hod."</item>
+  </plurals>
     <string name="VideoView_error_title" msgid="3534509135438353077">"Problém s videom"</string>
     <string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Je nám ľúto, ale toto video sa nedá streamovať do tohto zariadenia."</string>
     <string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Toto video nie je možné prehrať."</string>
@@ -1082,7 +1094,7 @@
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Hlasitosť upozornení"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Predvolený vyzváňací tón"</string>
     <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Predvolený vyzváňací tón (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
-    <string name="ringtone_silent" msgid="4440324407807468713">"Tichý"</string>
+    <string name="ringtone_silent" msgid="7937634392408977062">"Žiadny"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Vyzváňacie tóny"</string>
     <string name="ringtone_unknown" msgid="5477919988701784788">"Neznámy vyzváňací tón"</string>
   <plurals name="wifi_available">
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 7f94c204..e3802a5 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -993,6 +993,18 @@
     <string name="weeks" msgid="6509623834583944518">"tednov"</string>
     <string name="year" msgid="4001118221013892076">"leto"</string>
     <string name="years" msgid="6881577717993213522">"let"</string>
+  <plurals name="duration_seconds">
+    <item quantity="one" msgid="6962015528372969481">"1 sekunda"</item>
+    <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> s"</item>
+  </plurals>
+  <plurals name="duration_minutes">
+    <item quantity="one" msgid="4915414002546085617">"1 minuta"</item>
+    <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> min"</item>
+  </plurals>
+  <plurals name="duration_hours">
+    <item quantity="one" msgid="8917467491248809972">"1 ura"</item>
+    <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> h"</item>
+  </plurals>
     <string name="VideoView_error_title" msgid="3534509135438353077">"Težava z videoposnetkom"</string>
     <string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Ta videoposnetek ni veljaven za pretakanje v to napravo."</string>
     <string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Tega videoposnetka ni mogoče predvajati."</string>
@@ -1082,7 +1094,7 @@
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Glasnost obvestila"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Privzeta melodija zvonjenja"</string>
     <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Privzeta melodija zvonjenja (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
-    <string name="ringtone_silent" msgid="4440324407807468713">"Tiho"</string>
+    <string name="ringtone_silent" msgid="7937634392408977062">"Brez"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Melodije zvonjenja"</string>
     <string name="ringtone_unknown" msgid="5477919988701784788">"Neznana melodija zvonjenja"</string>
   <plurals name="wifi_available">
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 5a94aad..36994fb 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -993,6 +993,18 @@
     <string name="weeks" msgid="6509623834583944518">"недеље(а)"</string>
     <string name="year" msgid="4001118221013892076">"година"</string>
     <string name="years" msgid="6881577717993213522">"годинe(а)"</string>
+  <plurals name="duration_seconds">
+    <item quantity="one" msgid="6962015528372969481">"1 секунда"</item>
+    <item quantity="other" msgid="1886107766577166786">"Секунди: <xliff:g id="COUNT">%d</xliff:g>"</item>
+  </plurals>
+  <plurals name="duration_minutes">
+    <item quantity="one" msgid="4915414002546085617">"1 минут"</item>
+    <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> минута"</item>
+  </plurals>
+  <plurals name="duration_hours">
+    <item quantity="one" msgid="8917467491248809972">"1 сат"</item>
+    <item quantity="other" msgid="3863962854246773930">"Сати: <xliff:g id="COUNT">%d</xliff:g>"</item>
+  </plurals>
     <string name="VideoView_error_title" msgid="3534509135438353077">"Проблем са видео снимком"</string>
     <string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Овај видео не може да се стримује на овом уређају."</string>
     <string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Не можете да пустите овај видео."</string>
@@ -1082,7 +1094,7 @@
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Јачина звука обавештења"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Подразумевани звук звона"</string>
     <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Подразумевани звук звона (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
-    <string name="ringtone_silent" msgid="4440324407807468713">"Нечујно"</string>
+    <string name="ringtone_silent" msgid="7937634392408977062">"Без"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Звукови звона"</string>
     <string name="ringtone_unknown" msgid="5477919988701784788">"Непознати звук звона"</string>
   <plurals name="wifi_available">
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index c59491b..8058a8d 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -993,6 +993,18 @@
     <string name="weeks" msgid="6509623834583944518">"veckor"</string>
     <string name="year" msgid="4001118221013892076">"år"</string>
     <string name="years" msgid="6881577717993213522">"år"</string>
+  <plurals name="duration_seconds">
+    <item quantity="one" msgid="6962015528372969481">"1 sekund"</item>
+    <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> sekunder"</item>
+  </plurals>
+  <plurals name="duration_minutes">
+    <item quantity="one" msgid="4915414002546085617">"1 minut"</item>
+    <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> minuter"</item>
+  </plurals>
+  <plurals name="duration_hours">
+    <item quantity="one" msgid="8917467491248809972">"1 timme"</item>
+    <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> timmar"</item>
+  </plurals>
     <string name="VideoView_error_title" msgid="3534509135438353077">"Videoproblem"</string>
     <string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Videon kan tyvärr inte spelas upp i den här enheten."</string>
     <string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Det går inte att spela upp videon."</string>
@@ -1082,7 +1094,7 @@
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Meddelandevolym"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Standardringsignal"</string>
     <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Standardringsignal (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
-    <string name="ringtone_silent" msgid="4440324407807468713">"Tyst"</string>
+    <string name="ringtone_silent" msgid="7937634392408977062">"Ingen"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Ringsignaler"</string>
     <string name="ringtone_unknown" msgid="5477919988701784788">"Okänd ringsignal"</string>
   <plurals name="wifi_available">
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 5fc2a13..2789146 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -492,7 +492,7 @@
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"anzisha moja kwa moja usanidi wa simu ya CDMA"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"Inaruhusu programu kuanza ugawaji wa CDMA. Programu hasidi zinaweza anza ugawaji wa CDMA usio wa lazima."</string>
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"dhibiti arifa za usasishaji mahali"</string>
-    <string name="permdesc_locationUpdates" msgid="1120741557891438876">"Inaruhusu programu kuwezesha/kulemeza arifa za usasishaji za eneo kutoka kwa redio. Si ya matumizi na programu za kawaida."</string>
+    <string name="permdesc_locationUpdates" msgid="1120741557891438876">"Huruhusu kuwasha au kuzima arifa za masasisho ya mahali kutoka kwa redio. Sio ya kutumiwa kwenye programu za kawaida."</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"fikia mipangilio ya ukaguzi"</string>
     <string name="permdesc_checkinProperties" msgid="4024526968630194128">"Inaruhusu kusoma/kuandika kwa programu kufikia mipangilio iliyopakiwa na huduma ya kuangalia. Si ya matumizi na programu za kawaida."</string>
     <string name="permlab_bindGadget" msgid="776905339015863471">"chagua wijeti"</string>
@@ -993,6 +993,18 @@
     <string name="weeks" msgid="6509623834583944518">"wiki"</string>
     <string name="year" msgid="4001118221013892076">"mwaka"</string>
     <string name="years" msgid="6881577717993213522">"miaka"</string>
+  <plurals name="duration_seconds">
+    <item quantity="one" msgid="6962015528372969481">"Sekunde 1"</item>
+    <item quantity="other" msgid="1886107766577166786">"Sekunde <xliff:g id="COUNT">%d</xliff:g>"</item>
+  </plurals>
+  <plurals name="duration_minutes">
+    <item quantity="one" msgid="4915414002546085617">"Dakika 1"</item>
+    <item quantity="other" msgid="3165187169224908775">"Dakika <xliff:g id="COUNT">%d</xliff:g>"</item>
+  </plurals>
+  <plurals name="duration_hours">
+    <item quantity="one" msgid="8917467491248809972">"Saa 1"</item>
+    <item quantity="other" msgid="3863962854246773930">"Saa <xliff:g id="COUNT">%d</xliff:g>"</item>
+  </plurals>
     <string name="VideoView_error_title" msgid="3534509135438353077">"Shida ya video"</string>
     <string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Video hii si halali kutiririshwa kwa kifaa hiki."</string>
     <string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Haiwezi kucheza video hii."</string>
@@ -1082,7 +1094,7 @@
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Sauti ya arifa"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Toni mlio chaguo-msingi"</string>
     <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Toni mlio chaguo-msingi  (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
-    <string name="ringtone_silent" msgid="4440324407807468713">"Kimya"</string>
+    <string name="ringtone_silent" msgid="7937634392408977062">"Hamna"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Toni za mlio"</string>
     <string name="ringtone_unknown" msgid="5477919988701784788">"Mlio amabo haujulikani"</string>
   <plurals name="wifi_available">
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 0a86a86..38bf592 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -993,6 +993,18 @@
     <string name="weeks" msgid="6509623834583944518">"สัปดาห์"</string>
     <string name="year" msgid="4001118221013892076">"ปี"</string>
     <string name="years" msgid="6881577717993213522">" ปี"</string>
+  <plurals name="duration_seconds">
+    <item quantity="one" msgid="6962015528372969481">"1 วินาที"</item>
+    <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> วินาที"</item>
+  </plurals>
+  <plurals name="duration_minutes">
+    <item quantity="one" msgid="4915414002546085617">"1 นาที"</item>
+    <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> นาที"</item>
+  </plurals>
+  <plurals name="duration_hours">
+    <item quantity="one" msgid="8917467491248809972">"1 ชั่วโมง"</item>
+    <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> ชั่วโมง"</item>
+  </plurals>
     <string name="VideoView_error_title" msgid="3534509135438353077">"ปัญหาเกี่ยวกับวิดีโอ"</string>
     <string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"วิดีโอนี้ไม่สามารถสตรีมไปยังอุปกรณ์นี้"</string>
     <string name="VideoView_error_text_unknown" msgid="3450439155187810085">"ไม่สามารถเล่นวิดีโอนี้"</string>
@@ -1082,7 +1094,7 @@
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"ระดับเสียงของการแจ้งเตือน"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"เสียงเรียกเข้าเริ่มต้น"</string>
     <string name="ringtone_default_with_actual" msgid="8129563480895990372">"เสียงเรียกเข้าเริ่มต้น (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
-    <string name="ringtone_silent" msgid="4440324407807468713">"ปิดเสียง"</string>
+    <string name="ringtone_silent" msgid="7937634392408977062">"ไม่มี"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"เสียงเรียกเข้า"</string>
     <string name="ringtone_unknown" msgid="5477919988701784788">"ไม่ทราบเสียงเรียกเข้า"</string>
   <plurals name="wifi_available">
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 072f6df..e3260db 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -993,6 +993,18 @@
     <string name="weeks" msgid="6509623834583944518">"mga linggo"</string>
     <string name="year" msgid="4001118221013892076">"taon"</string>
     <string name="years" msgid="6881577717993213522">"mga taon"</string>
+  <plurals name="duration_seconds">
+    <item quantity="one" msgid="6962015528372969481">"1 segundo"</item>
+    <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> (na) segundo"</item>
+  </plurals>
+  <plurals name="duration_minutes">
+    <item quantity="one" msgid="4915414002546085617">"1 minuto"</item>
+    <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> (na) minuto"</item>
+  </plurals>
+  <plurals name="duration_hours">
+    <item quantity="one" msgid="8917467491248809972">"1 oras"</item>
+    <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> (na) oras"</item>
+  </plurals>
     <string name="VideoView_error_title" msgid="3534509135438353077">"Problema sa video"</string>
     <string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Hindi wasto ang video na ito para sa streaming sa device na ito."</string>
     <string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Hindi ma-play ang video na ito."</string>
@@ -1082,7 +1094,7 @@
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Volume ng notification"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Default na ringtone"</string>
     <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Default na ringtone (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
-    <string name="ringtone_silent" msgid="4440324407807468713">"Tahimik"</string>
+    <string name="ringtone_silent" msgid="7937634392408977062">"Wala"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Mga Ringtone"</string>
     <string name="ringtone_unknown" msgid="5477919988701784788">"Hindi kilalang ringtone"</string>
   <plurals name="wifi_available">
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index dbb7b0d..7940089 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -993,6 +993,18 @@
     <string name="weeks" msgid="6509623834583944518">"hafta"</string>
     <string name="year" msgid="4001118221013892076">"yıl"</string>
     <string name="years" msgid="6881577717993213522">"yıl"</string>
+  <plurals name="duration_seconds">
+    <item quantity="one" msgid="6962015528372969481">"1 saniye"</item>
+    <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> saniye"</item>
+  </plurals>
+  <plurals name="duration_minutes">
+    <item quantity="one" msgid="4915414002546085617">"1 dakika"</item>
+    <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> dakika"</item>
+  </plurals>
+  <plurals name="duration_hours">
+    <item quantity="one" msgid="8917467491248809972">"1 saat"</item>
+    <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> saat"</item>
+  </plurals>
     <string name="VideoView_error_title" msgid="3534509135438353077">"Video sorunu"</string>
     <string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Bu video bu cihazda akış için uygun değil."</string>
     <string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Bu video oynatılamıyor."</string>
@@ -1082,7 +1094,7 @@
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Bildirim ses düzeyi"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Varsayılan zil sesi"</string>
     <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Varsayılan zil sesi (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
-    <string name="ringtone_silent" msgid="4440324407807468713">"Sessiz"</string>
+    <string name="ringtone_silent" msgid="7937634392408977062">"Yok"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Zil sesleri"</string>
     <string name="ringtone_unknown" msgid="5477919988701784788">"Bilinmeyen zil sesi"</string>
   <plurals name="wifi_available">
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 6512007..7e5d711 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -993,6 +993,18 @@
     <string name="weeks" msgid="6509623834583944518">"тижн."</string>
     <string name="year" msgid="4001118221013892076">"рік"</string>
     <string name="years" msgid="6881577717993213522">"р."</string>
+  <plurals name="duration_seconds">
+    <item quantity="one" msgid="6962015528372969481">"1 с"</item>
+    <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> с"</item>
+  </plurals>
+  <plurals name="duration_minutes">
+    <item quantity="one" msgid="4915414002546085617">"1 хв"</item>
+    <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> хв"</item>
+  </plurals>
+  <plurals name="duration_hours">
+    <item quantity="one" msgid="8917467491248809972">"1 год"</item>
+    <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> год"</item>
+  </plurals>
     <string name="VideoView_error_title" msgid="3534509135438353077">"Проблема з відео"</string>
     <string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Відео не придатне для потокового передавання в цей пристрій."</string>
     <string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Неможливо відтворити це відео."</string>
@@ -1082,7 +1094,7 @@
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Гучність сповіщення"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Мелодія за умовч."</string>
     <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Мелодія за умовч. (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
-    <string name="ringtone_silent" msgid="4440324407807468713">"Без звуку"</string>
+    <string name="ringtone_silent" msgid="7937634392408977062">"Немає"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Мелодії"</string>
     <string name="ringtone_unknown" msgid="5477919988701784788">"Невідома мелодія"</string>
   <plurals name="wifi_available">
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 7fb3412..a6e5d4b 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -993,6 +993,18 @@
     <string name="weeks" msgid="6509623834583944518">"tuần"</string>
     <string name="year" msgid="4001118221013892076">"năm"</string>
     <string name="years" msgid="6881577717993213522">"năm"</string>
+  <plurals name="duration_seconds">
+    <item quantity="one" msgid="6962015528372969481">"1 giây"</item>
+    <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> giây"</item>
+  </plurals>
+  <plurals name="duration_minutes">
+    <item quantity="one" msgid="4915414002546085617">"1 phút"</item>
+    <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> phút"</item>
+  </plurals>
+  <plurals name="duration_hours">
+    <item quantity="one" msgid="8917467491248809972">"1 giờ"</item>
+    <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> giờ"</item>
+  </plurals>
     <string name="VideoView_error_title" msgid="3534509135438353077">"Sự cố video"</string>
     <string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Video này không hợp lệ để phát trực tuyến đến thiết bị này."</string>
     <string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Không thể phát video này."</string>
@@ -1082,7 +1094,7 @@
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Âm lượng thông báo"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Nhạc chuông mặc định"</string>
     <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Nhạc chuông mặc định (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
-    <string name="ringtone_silent" msgid="4440324407807468713">"Im lặng"</string>
+    <string name="ringtone_silent" msgid="7937634392408977062">"Không"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Nhạc chuông"</string>
     <string name="ringtone_unknown" msgid="5477919988701784788">"Nhạc chuông không xác định"</string>
   <plurals name="wifi_available">
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 251389b..425c497 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -993,6 +993,18 @@
     <string name="weeks" msgid="6509623834583944518">"周"</string>
     <string name="year" msgid="4001118221013892076">"年"</string>
     <string name="years" msgid="6881577717993213522">"年"</string>
+  <plurals name="duration_seconds">
+    <item quantity="one" msgid="6962015528372969481">"1 秒"</item>
+    <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> 秒"</item>
+  </plurals>
+  <plurals name="duration_minutes">
+    <item quantity="one" msgid="4915414002546085617">"1 分钟"</item>
+    <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> 分钟"</item>
+  </plurals>
+  <plurals name="duration_hours">
+    <item quantity="one" msgid="8917467491248809972">"1 小时"</item>
+    <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> 小时"</item>
+  </plurals>
     <string name="VideoView_error_title" msgid="3534509135438353077">"视频问题"</string>
     <string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"抱歉,该视频不适合在此设备上播放。"</string>
     <string name="VideoView_error_text_unknown" msgid="3450439155187810085">"无法播放此视频。"</string>
@@ -1082,7 +1094,7 @@
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"通知音量"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"默认铃声"</string>
     <string name="ringtone_default_with_actual" msgid="8129563480895990372">"默认铃声(<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
-    <string name="ringtone_silent" msgid="4440324407807468713">"静音"</string>
+    <string name="ringtone_silent" msgid="7937634392408977062">"无"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"铃声"</string>
     <string name="ringtone_unknown" msgid="5477919988701784788">"未知铃声"</string>
   <plurals name="wifi_available">
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 473b9d0..2ae304a 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -993,6 +993,18 @@
     <string name="weeks" msgid="6509623834583944518">"週"</string>
     <string name="year" msgid="4001118221013892076">"年"</string>
     <string name="years" msgid="6881577717993213522">"年"</string>
+  <plurals name="duration_seconds">
+    <item quantity="one" msgid="6962015528372969481">"1 秒"</item>
+    <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> 秒"</item>
+  </plurals>
+  <plurals name="duration_minutes">
+    <item quantity="one" msgid="4915414002546085617">"1 分鐘"</item>
+    <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> 分鐘"</item>
+  </plurals>
+  <plurals name="duration_hours">
+    <item quantity="one" msgid="8917467491248809972">"1 小時"</item>
+    <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> 小時"</item>
+  </plurals>
     <string name="VideoView_error_title" msgid="3534509135438353077">"影片發生問題"</string>
     <string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"這部影片的格式無效,因此無法在此裝置中串流播放。"</string>
     <string name="VideoView_error_text_unknown" msgid="3450439155187810085">"無法播放這部影片。"</string>
@@ -1082,7 +1094,7 @@
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"通知音量"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"預設鈴聲"</string>
     <string name="ringtone_default_with_actual" msgid="8129563480895990372">"預設鈴聲 (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
-    <string name="ringtone_silent" msgid="4440324407807468713">"靜音"</string>
+    <string name="ringtone_silent" msgid="7937634392408977062">"無"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"鈴聲"</string>
     <string name="ringtone_unknown" msgid="5477919988701784788">"未知的鈴聲"</string>
   <plurals name="wifi_available">
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index eb1cbfb..43ec792 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -993,6 +993,18 @@
     <string name="weeks" msgid="6509623834583944518">"amaviki"</string>
     <string name="year" msgid="4001118221013892076">"unyaka"</string>
     <string name="years" msgid="6881577717993213522">"iminyaka"</string>
+  <plurals name="duration_seconds">
+    <item quantity="one" msgid="6962015528372969481">"1 isekhondi"</item>
+    <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> amasekhondi"</item>
+  </plurals>
+  <plurals name="duration_minutes">
+    <item quantity="one" msgid="4915414002546085617">"1 iminithi"</item>
+    <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> amaminithi"</item>
+  </plurals>
+  <plurals name="duration_hours">
+    <item quantity="one" msgid="8917467491248809972">"1 ihora"</item>
+    <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> amahora"</item>
+  </plurals>
     <string name="VideoView_error_title" msgid="3534509135438353077">"Inkinga yevidiyo"</string>
     <string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Uxolo, le vidiyo ayilungele ukusakaza bukhomo kwale divaysi."</string>
     <string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Iyehluleka ukudlala levidiyo."</string>
@@ -1082,7 +1094,7 @@
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Ivolumu yesaziso"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Iringithoni emisiwe"</string>
     <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Iringithoni ezenzakalelayo <xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>"</string>
-    <string name="ringtone_silent" msgid="4440324407807468713">"Thulile"</string>
+    <string name="ringtone_silent" msgid="7937634392408977062">"Akunalutho"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Amaringithoni"</string>
     <string name="ringtone_unknown" msgid="5477919988701784788">"Iringithoni engaziwa"</string>
   <plurals name="wifi_available">
diff --git a/core/res/res/values/arrays.xml b/core/res/res/values/arrays.xml
index 1e966f7..f7ff77b 100644
--- a/core/res/res/values/arrays.xml
+++ b/core/res/res/values/arrays.xml
@@ -143,10 +143,6 @@
        <item>@drawable/menu_dropdown_panel_holo_dark</item>
        <item>@drawable/overscroll_edge</item>
        <item>@drawable/overscroll_glow</item>
-       <item>@drawable/popup_inline_error_above_holo_dark</item>
-       <item>@drawable/popup_inline_error_above_holo_light</item>
-       <item>@drawable/popup_inline_error_holo_dark</item>
-       <item>@drawable/popup_inline_error_holo_light</item>
        <item>@drawable/spinner_16_outer_holo</item>
        <item>@drawable/spinner_16_inner_holo</item>
        <item>@drawable/spinner_48_outer_holo</item>
@@ -257,8 +253,6 @@
        <item>@drawable/ab_solid_shadow_holo</item>
        <item>@drawable/item_background_holo_dark</item>
        <item>@drawable/item_background_holo_light</item>
-       <item>@drawable/ic_ab_back_holo_dark</item>
-       <item>@drawable/ic_ab_back_holo_light</item>
        <item>@drawable/fastscroll_thumb_holo</item>
        <item>@drawable/fastscroll_thumb_pressed_holo</item>
        <item>@drawable/fastscroll_thumb_default_holo</item>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 8e66a77..05130a1 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2082,11 +2082,11 @@
             <!-- Don't use a layer. -->
             <enum name="none" value="0" />
             <!-- Use a software layer. Refer to
-                 {@link android.view.View#setLayerType(int, android.graphics.Paint) for
+                 {@link android.view.View#setLayerType(int, android.graphics.Paint)} for
                  more information. -->
             <enum name="software" value="1" />
             <!-- Use a hardware layer. Refer to
-                 {@link android.view.View#setLayerType(int, android.graphics.Paint) for
+                 {@link android.view.View#setLayerType(int, android.graphics.Paint)} for
                  more information. -->
             <enum name="hardware" value="2" />
         </attr>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index f91df99..cb7804c 100755
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1006,9 +1006,9 @@
      -->
     <integer-array name="config_defaultNotificationVibePattern">
         <item>0</item>
+        <item>350</item>
         <item>250</item>
-        <item>250</item>
-        <item>250</item>
+        <item>350</item>
     </integer-array>
 
     <!-- Vibrator pattern to be used as the default for notifications
@@ -1017,8 +1017,11 @@
      -->
     <integer-array name="config_notificationFallbackVibePattern">
         <item>0</item>
-        <item>250</item>
-        <item>250</item>
-        <item>250</item>
+        <item>100</item>
+        <item>150</item>
+        <item>100</item>
     </integer-array>
+
+    <!-- Flag indicating if the speed up audio on mt call code should be executed -->
+    <bool name="config_speed_up_audio_on_mt_calls">false</bool>
 </resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 9932d1e..99fbf95 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -2838,6 +2838,21 @@
     <!-- Appened to express the value is this unit of time. -->
     <string name="years">years</string>
 
+    <!-- Phrase describing a time duration using seconds [CHAR LIMIT=16] -->
+    <plurals name="duration_seconds">
+        <item quantity="one">1 second</item>
+        <item quantity="other"><xliff:g id="count">%d</xliff:g> seconds</item>
+    </plurals>
+    <!-- Phrase describing a time duration using minutes [CHAR LIMIT=16] -->
+    <plurals name="duration_minutes">
+        <item quantity="one">1 minute</item>
+        <item quantity="other"><xliff:g id="count">%d</xliff:g> minutes</item>
+    </plurals>
+    <!-- Phrase describing a time duration using hours [CHAR LIMIT=16] -->
+    <plurals name="duration_hours">
+        <item quantity="one">1 hour</item>
+        <item quantity="other"><xliff:g id="count">%d</xliff:g> hours</item>
+    </plurals>
 
     <!-- Title for error alert when a video cannot be played.  it can be used by any app. -->
     <string name="VideoView_error_title">Video problem</string>
@@ -3079,7 +3094,7 @@
     <!-- Choice in the ringtone picker.  If chosen, the default ringtone will be used. This fills in the actual ringtone's title into the message. -->
     <string name="ringtone_default_with_actual">Default ringtone (<xliff:g id="actual_ringtone">%1$s</xliff:g>)</string>
     <!-- Choice in the ringtone picker.  If chosen, there will be silence instead of a ringtone played. -->
-    <string name="ringtone_silent">Silent</string>
+    <string name="ringtone_silent">None</string>
     <!-- The title of the ringtone picker dialog. -->
     <string name="ringtone_picker_title">Ringtones</string>
     <!-- If there is ever a ringtone set for some setting, but that ringtone can no longer be resolved, t his is shown instead.  For example, if the ringtone was on a SD card and it had been removed, this woudl be shown for ringtones on that SD card. -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 6858732..391320b 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -277,6 +277,7 @@
   <java-symbol type="bool" name="config_safe_media_volume_enabled" />
   <java-symbol type="bool" name="config_camera_sound_forced" />
   <java-symbol type="bool" name="config_dontPreferApn" />
+  <java-symbol type="bool" name="config_speed_up_audio_on_mt_calls" />
 
   <java-symbol type="integer" name="config_cursorWindowSize" />
   <java-symbol type="integer" name="config_longPressOnPowerBehavior" />
@@ -870,6 +871,9 @@
   <java-symbol type="plurals" name="abbrev_num_hours_ago" />
   <java-symbol type="plurals" name="abbrev_num_minutes_ago" />
   <java-symbol type="plurals" name="abbrev_num_seconds_ago" />
+  <java-symbol type="plurals" name="duration_hours" />
+  <java-symbol type="plurals" name="duration_minutes" />
+  <java-symbol type="plurals" name="duration_seconds" />
   <java-symbol type="plurals" name="in_num_days" />
   <java-symbol type="plurals" name="in_num_hours" />
   <java-symbol type="plurals" name="in_num_minutes" />
@@ -1108,6 +1112,7 @@
   <java-symbol type="layout" name="keyguard_multi_user_selector_widget" />
   <java-symbol type="layout" name="sms_short_code_confirmation_dialog" />
   <java-symbol type="layout" name="keyguard_add_widget" />
+  <java-symbol type="layout" name="action_bar_up_container" />
 
   <java-symbol type="anim" name="slide_in_child_bottom" />
   <java-symbol type="anim" name="slide_in_right" />
@@ -1814,5 +1819,4 @@
 
   <!-- From PinyinIME(!!!) -->
   <java-symbol type="string" name="inputMethod" />
-
 </resources>
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java
index 245f537..463e999 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java
@@ -60,13 +60,14 @@
 
     public static final String LOG_TAG = "ConnectivityManagerTestActivity";
     public static final int WAIT_FOR_SCAN_RESULT = 10 * 1000; //10 seconds
-    public static final int WIFI_SCAN_TIMEOUT = 50 * 1000;
-    public static final int SHORT_TIMEOUT = 5 * 1000;
-    public static final long LONG_TIMEOUT = 50 * 1000;
+    public static final int WIFI_SCAN_TIMEOUT = 50 * 1000; // 50 seconds
+    public static final int SHORT_TIMEOUT = 5 * 1000; // 5 seconds
+    public static final long LONG_TIMEOUT = 50 * 1000;  // 50 seconds
+    public static final long WIFI_CONNECTION_TIMEOUT = 5 * 60 * 1000; // 5 minutes
     // 2 minutes timer between wifi stop and start
-    public static final long  WIFI_STOP_START_INTERVAL = 2 * 60 * 1000;
+    public static final long  WIFI_STOP_START_INTERVAL = 2 * 60 * 1000; // 2 minutes
     // Set ping test timer to be 3 minutes
-    public static final long PING_TIMER = 3 * 60 *1000;
+    public static final long PING_TIMER = 3 * 60 *1000; // 3 minutes
     public static final int SUCCESS = 0;  // for Wifi tethering state change
     public static final int FAILURE = 1;
     public static final int INIT = -1;
@@ -573,7 +574,7 @@
         String ssid = config.SSID;
         config.SSID = convertToQuotedString(ssid);
 
-        //If Wifi is not enabled, enable it
+        // If Wifi is not enabled, enable it
         if (!mWifiManager.isWifiEnabled()) {
             log("Wifi is not enabled, enable it");
             mWifiManager.setWifiEnabled(true);
@@ -584,59 +585,16 @@
             }
         }
 
-        boolean foundApInScanResults = false;
-        for (int retry = 0; retry < 5; retry++) {
-            List<ScanResult> netList = mWifiManager.getScanResults();
-            if (netList != null) {
-                log("size of scan result list: " + netList.size());
-                for (int i = 0; i < netList.size(); i++) {
-                    ScanResult sr= netList.get(i);
-                    if (sr.SSID.equals(ssid)) {
-                        log("found " + ssid + " in the scan result list");
-                        log("retry: " + retry);
-                        foundApInScanResults = true;
-                        mWifiManager.connect(config,
-                                new WifiManager.ActionListener() {
-                                    public void onSuccess() {
-                                    }
-                                    public void onFailure(int reason) {
-                                        log("connect failure " + reason);
-                                    }
-                                });
-                        break;
-                   }
+        // Save network configuration and connect to network without scanning
+        mWifiManager.connect(config,
+            new WifiManager.ActionListener() {
+                public void onSuccess() {
                 }
-            }
-            if (foundApInScanResults) {
-                return true;
-            } else {
-                // Start an active scan
-                mWifiManager.startScanActive();
-                mScanResultIsAvailable = false;
-                long startTime = System.currentTimeMillis();
-                while (!mScanResultIsAvailable) {
-                    if ((System.currentTimeMillis() - startTime) > WIFI_SCAN_TIMEOUT) {
-                        log("wait for scan results timeout");
-                        return false;
-                    }
-                    // wait for the scan results to be available
-                    synchronized (this) {
-                        // wait for the scan result to be available
-                        try {
-                            this.wait(WAIT_FOR_SCAN_RESULT);
-                        } catch (InterruptedException e) {
-                            e.printStackTrace();
-                        }
-                        if ((mWifiManager.getScanResults() == null) ||
-                                (mWifiManager.getScanResults().size() <= 0)) {
-                            continue;
-                        }
-                        mScanResultIsAvailable = true;
-                    }
+                public void onFailure(int reason) {
+                    log("connect failure " + reason);
                 }
-            }
-        }
-        return false;
+            });
+        return true;
     }
 
     /*
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java
index 7928822..3111489 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java
@@ -126,7 +126,7 @@
         cmActivity.disableWifi();
 
         assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_WIFI,
-                State.DISCONNECTED, ConnectivityManagerTestActivity.LONG_TIMEOUT));
+                State.DISCONNECTED,  ConnectivityManagerTestActivity.LONG_TIMEOUT));
         assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_MOBILE,
                 State.CONNECTED, ConnectivityManagerTestActivity.LONG_TIMEOUT));
         // Wait for 10 seconds for broadcasts to be sent out
@@ -184,7 +184,7 @@
                 ConnectivityManagerTestActivity.LONG_TIMEOUT));
         log("wifi state is enabled");
         assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
-                ConnectivityManagerTestActivity.LONG_TIMEOUT));
+                ConnectivityManagerTestActivity.WIFI_CONNECTION_TIMEOUT));
         if (!mWifiOnlyFlag) {
             assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_MOBILE,
                     State.DISCONNECTED, ConnectivityManagerTestActivity.LONG_TIMEOUT));
@@ -217,7 +217,7 @@
         assertTrue(cmActivity.waitForWifiState(WifiManager.WIFI_STATE_ENABLED,
                 ConnectivityManagerTestActivity.LONG_TIMEOUT));
         assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
-                ConnectivityManagerTestActivity.LONG_TIMEOUT));
+                ConnectivityManagerTestActivity.WIFI_CONNECTION_TIMEOUT));
 
         sleep(ConnectivityManagerTestActivity.SHORT_TIMEOUT);
         // Disable Wifi
@@ -257,7 +257,7 @@
 
         // Wait for Wifi to be connected and mobile to be disconnected
         assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
-                ConnectivityManagerTestActivity.LONG_TIMEOUT));
+                ConnectivityManagerTestActivity.WIFI_CONNECTION_TIMEOUT));
         if (!mWifiOnlyFlag) {
             assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_MOBILE,
                     State.DISCONNECTED, ConnectivityManagerTestActivity.LONG_TIMEOUT));
@@ -279,10 +279,10 @@
 
         // connect to Wifi
         assertTrue("failed to connect to " + mTestAccessPoint,
-                   cmActivity.connectToWifi(mTestAccessPoint));
+                cmActivity.connectToWifi(mTestAccessPoint));
 
         assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
-            ConnectivityManagerTestActivity.LONG_TIMEOUT));
+                ConnectivityManagerTestActivity.WIFI_CONNECTION_TIMEOUT));
 
         // Wait for a few seconds to avoid the state that both Mobile and Wifi is connected
         sleep(ConnectivityManagerTestActivity.SHORT_TIMEOUT);
@@ -418,9 +418,9 @@
 
         // Connect to Wifi
         assertTrue("failed to connect to " + mTestAccessPoint,
-                   cmActivity.connectToWifi(mTestAccessPoint));
+                cmActivity.connectToWifi(mTestAccessPoint));
         assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
-                            ConnectivityManagerTestActivity.LONG_TIMEOUT));
+                ConnectivityManagerTestActivity.WIFI_CONNECTION_TIMEOUT));
 
         // validate state and broadcast
         if (!cmActivity.validateNetworkStates(ConnectivityManager.TYPE_WIFI)) {
@@ -454,7 +454,7 @@
                 cmActivity.connectToWifi(mTestAccessPoint));
 
         assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
-                ConnectivityManagerTestActivity.LONG_TIMEOUT));
+                ConnectivityManagerTestActivity.WIFI_CONNECTION_TIMEOUT));
 
         try {
             Thread.sleep(ConnectivityManagerTestActivity.SHORT_TIMEOUT);
@@ -484,7 +484,7 @@
         cmActivity.setAirplaneMode(getInstrumentation().getContext(), false);
 
         assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
-                            ConnectivityManagerTestActivity.LONG_TIMEOUT));
+                ConnectivityManagerTestActivity.WIFI_CONNECTION_TIMEOUT));
         if (!mWifiOnlyFlag) {
             assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_MOBILE,
                     State.DISCONNECTED, ConnectivityManagerTestActivity.LONG_TIMEOUT));
@@ -505,11 +505,11 @@
         assertNotNull("SSID is null", mTestAccessPoint);
         //Connect to mTestAccessPoint
         assertTrue("failed to connect to " + mTestAccessPoint,
-                   cmActivity.connectToWifi(mTestAccessPoint));
+                cmActivity.connectToWifi(mTestAccessPoint));
         assertTrue(cmActivity.waitForWifiState(WifiManager.WIFI_STATE_ENABLED,
                 ConnectivityManagerTestActivity.LONG_TIMEOUT));
         assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
-                            ConnectivityManagerTestActivity.LONG_TIMEOUT));
+                ConnectivityManagerTestActivity.WIFI_CONNECTION_TIMEOUT));
         assertNotNull("Not associated with any AP",
                       cmActivity.mWifiManager.getConnectionInfo().getBSSID());
 
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiConnectionTest.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiConnectionTest.java
index 81075ef..de0298e 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiConnectionTest.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiConnectionTest.java
@@ -118,7 +118,7 @@
 
         // step 2: verify Wifi state and network state;
         assertTrue(mAct.waitForNetworkState(ConnectivityManager.TYPE_WIFI,
-                State.CONNECTED, 6 * ConnectivityManagerTestActivity.LONG_TIMEOUT));
+                State.CONNECTED, ConnectivityManagerTestActivity.WIFI_CONNECTION_TIMEOUT));
 
         // step 3: verify the current connected network is the given SSID
         assertNotNull("Wifi connection returns null", mAct.mWifiManager.getConnectionInfo());
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java
index 7bfb594..53876a5 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java
@@ -248,7 +248,7 @@
         assertTrue(mAct.waitForWifiState(WifiManager.WIFI_STATE_ENABLED,
                 ConnectivityManagerTestActivity.SHORT_TIMEOUT));
         assertTrue(mAct.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
-                ConnectivityManagerTestActivity.LONG_TIMEOUT));
+                ConnectivityManagerTestActivity.WIFI_CONNECTION_TIMEOUT));
         // Run ping test to verify the data connection
         assertTrue("Wi-Fi is connected, but no data connection.", mAct.pingTest(null));
 
@@ -302,7 +302,7 @@
                     ConnectivityManagerTestActivity.SHORT_TIMEOUT));
             assertTrue("Wait for Wi-Fi connection timeout after wake up",
                     mAct.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
-                    6 * ConnectivityManagerTestActivity.LONG_TIMEOUT));
+                    ConnectivityManagerTestActivity.WIFI_CONNECTION_TIMEOUT));
             long connectionTime = System.currentTimeMillis() - startTime;
             sum += connectionTime;
             log("average reconnection time is: " + sum/(i+1));
diff --git a/core/tests/coretests/src/android/text/format/DateUtilsTest.java b/core/tests/coretests/src/android/text/format/DateUtilsTest.java
new file mode 100644
index 0000000..cf42bb1
--- /dev/null
+++ b/core/tests/coretests/src/android/text/format/DateUtilsTest.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.text.format;
+
+import android.test.suitebuilder.annotation.SmallTest;
+
+import junit.framework.TestCase;
+
+public class DateUtilsTest extends TestCase {
+    @SmallTest
+    public void testFormatDurationSeconds() throws Exception {
+        assertEquals("0 seconds", DateUtils.formatDuration(0));
+        assertEquals("0 seconds", DateUtils.formatDuration(1));
+        assertEquals("0 seconds", DateUtils.formatDuration(499));
+        assertEquals("1 second", DateUtils.formatDuration(500));
+        assertEquals("1 second", DateUtils.formatDuration(1000));
+        assertEquals("2 seconds", DateUtils.formatDuration(1500));
+    }
+
+    @SmallTest
+    public void testFormatDurationMinutes() throws Exception {
+        assertEquals("59 seconds", DateUtils.formatDuration(59000));
+        assertEquals("60 seconds", DateUtils.formatDuration(59500));
+        assertEquals("1 minute", DateUtils.formatDuration(60000));
+        assertEquals("2 minutes", DateUtils.formatDuration(120000));
+    }
+
+    @SmallTest
+    public void testFormatDurationHours() throws Exception {
+        assertEquals("59 minutes", DateUtils.formatDuration(3540000));
+        assertEquals("1 hour", DateUtils.formatDuration(3600000));
+        assertEquals("48 hours", DateUtils.formatDuration(172800000));
+    }
+}
diff --git a/data/etc/platform.xml b/data/etc/platform.xml
index 13d1791..83ecdd9 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -134,6 +134,7 @@
     <assign-permission name="android.permission.ACCESS_NETWORK_STATE" uid="shell" />
     <assign-permission name="android.permission.ACCESS_WIFI_STATE" uid="shell" />
     <assign-permission name="android.permission.BLUETOOTH" uid="shell" />
+    <assign-permission name="android.permission.EXPAND_STATUS_BAR" uid="shell" />
     <!-- System tool permissions granted to the shell. -->
     <assign-permission name="android.permission.GET_TASKS" uid="shell" />
     <assign-permission name="android.permission.CHANGE_CONFIGURATION" uid="shell" />
diff --git a/data/fonts/DroidSansThai.ttf b/data/fonts/DroidSansThai.ttf
index c078be0..15b00c2 100644
--- a/data/fonts/DroidSansThai.ttf
+++ b/data/fonts/DroidSansThai.ttf
Binary files differ
diff --git a/data/fonts/fallback_fonts.xml b/data/fonts/fallback_fonts.xml
index 50ff437..999ddc4 100644
--- a/data/fonts/fallback_fonts.xml
+++ b/data/fonts/fallback_fonts.xml
@@ -103,6 +103,11 @@
     </family>
     <family>
         <fileset>
+            <file>Lohit-Telugu.ttf</file>
+        </fileset>
+    </family>
+    <family>
+        <fileset>
             <file>DroidSansFallback.ttf</file>
         </fileset>
     </family>
@@ -111,13 +116,10 @@
             <file lang="ja">MTLmr3m.ttf</file>
         </fileset>
     </family>
-    <!--
-        Fonts below this point have problematic glyphs and should not be moved
-        higher in the fallback list until those glyphs have been fixed.
+    <!-- Note: complex scripts (i.e. those requiring shaping in Harfbuzz) have
+         a cumulative limit of 64k glyphs. Thus, if they are placed after the
+         large fonts such as DroidSansFallback, they are likely to render
+         incorrectly. Please use caution when putting fonts toward the end of
+         the list.
     -->
-    <family>
-        <fileset>
-            <file>Lohit-Telugu.ttf</file> <!-- masks U+FFBC-10007 -->
-        </fileset>
-    </family>
 </familyset>
diff --git a/data/sounds/AudioPackage10.mk b/data/sounds/AudioPackage10.mk
index cb55bba..b40e385 100755
--- a/data/sounds/AudioPackage10.mk
+++ b/data/sounds/AudioPackage10.mk
@@ -29,6 +29,7 @@
 	$(LOCAL_PATH)/effects/ogg/Undock.ogg:system/media/audio/ui/Undock.ogg \
 	$(LOCAL_PATH)/effects/ogg/Lock.ogg:system/media/audio/ui/Lock.ogg \
 	$(LOCAL_PATH)/effects/ogg/Unlock.ogg:system/media/audio/ui/Unlock.ogg \
+	$(LOCAL_PATH)/effects/ogg/WirelessChargingStarted.ogg:system/media/audio/ui/WirelessChargingStarted.ogg \
 	$(LOCAL_PATH)/notifications/ogg/Adara.ogg:system/media/audio/notifications/Adara.ogg \
 	$(LOCAL_PATH)/notifications/ogg/Alya.ogg:system/media/audio/notifications/Alya.ogg \
 	$(LOCAL_PATH)/notifications/ogg/Arcturus.ogg:system/media/audio/notifications/Arcturus.ogg \
diff --git a/data/sounds/effects/ogg/LowBattery.ogg b/data/sounds/effects/ogg/LowBattery.ogg
index 710e385..ab9eba3 100644
--- a/data/sounds/effects/ogg/LowBattery.ogg
+++ b/data/sounds/effects/ogg/LowBattery.ogg
Binary files differ
diff --git a/data/sounds/effects/ogg/WirelessChargingStarted.ogg b/data/sounds/effects/ogg/WirelessChargingStarted.ogg
new file mode 100644
index 0000000..66f6cd2
--- /dev/null
+++ b/data/sounds/effects/ogg/WirelessChargingStarted.ogg
Binary files differ
diff --git a/docs/downloads/training/BitmapFun.zip b/docs/downloads/training/BitmapFun.zip
index 61b537d..48bea78 100644
--- a/docs/downloads/training/BitmapFun.zip
+++ b/docs/downloads/training/BitmapFun.zip
Binary files differ
diff --git a/docs/downloads/training/InteractiveChart.zip b/docs/downloads/training/InteractiveChart.zip
new file mode 100644
index 0000000..95248ad
--- /dev/null
+++ b/docs/downloads/training/InteractiveChart.zip
Binary files differ
diff --git a/docs/html/_redirects.yaml b/docs/html/_redirects.yaml
index 2ca77dd..d89934f 100644
--- a/docs/html/_redirects.yaml
+++ b/docs/html/_redirects.yaml
@@ -24,6 +24,9 @@
 - from: /sdk/installing/next.html
   to: /training/basics/firstapp/index.html
 
+- from: /sdk/ndk/overview.html
+  to: /tools/sdk/ndk/index.html
+
 - from: /sdk/ndk/...
   to: /tools/sdk/ndk/...
 
@@ -113,13 +116,14 @@
 - from: /guide/appendix/install-location.html
   to: /guide/topics/data/install-location.html
 
-- from: /guide/basics/what-is-android.html
+- from: /guide/basics/...
   to: /about/index.html
 
 - from: /guide/topics/security/security.html
   to: /training/articles/security-tips.html
-#  type: permanent
-#  comment: Move content and then adjust this
+
+- from: /guide/topics/security/index.html
+  to: /training/articles/security-tips.html
 
 - from: /guide/appendix/market-filters.html
   to: /google/play/filters.html
@@ -262,6 +266,9 @@
 - from: /training/cloudsync/aesync.html
   to: /google/gcm/index.html
 
+- from: /training/basics/location/...
+  to: /training/location/...
+
 # -------------------- MISC ----------------------
 
 - from: /shareables/...
diff --git a/docs/html/about/dashboards/index.jd b/docs/html/about/dashboards/index.jd
index 93876f8..6956634 100644
--- a/docs/html/about/dashboards/index.jd
+++ b/docs/html/about/dashboards/index.jd
@@ -1,107 +1,65 @@
 page.title=Dashboards
-header.hide=1
 @jd:body
 
+<style>
+div.chart,
+div.screens-chart {
+  display:none;
+}
+tr .total {
+  background-color:transparent;
+  border:0;
+  color:#666;
+}
+tr th.total {
+  font-weight:bold;
+}
+</style>
+
+
+
+
+<div class="sidebox">
+<h2>Google Play Install Stats</h2>
+<p>The Google Play Developer Console also provides <a
+href="{@docRoot}distribute/googleplay/about/distribution.html#stats">detailed statistics</a>
+about your users' devices. Those stats may help you prioritize the device profiles for which
+you optimize your app.</p>
+</div>
+
+<p>This page provides information about the relative number of devices that share a certain
+characteristic, such as Android version or screen size. This information may
+help you prioritize efforts for <a
+href="{@docRoot}training/basics/supporting-devices/index.html">supporting different devices</a>.</p>
+
+<p>Each snapshot of data represents all the devices that visited the Google Play Store in the
+prior 14 days.</p>
+
+<p class="note"><strong>Note:</strong> Beginning in April, 2013, these charts are now built
+using data collected from each device when the user visits the Google Play Store. Previously, the
+data was collected when the device simply checked-in to Google servers. We believe the new
+data more accurately reflects those users who are most engaged in the Android and Google Play
+ecosystem.</p>
 
 
 <h2 id="Platform">Platform Versions</h2>
 
-<p>This page provides data about the relative number of active devices
-running a given version of the Android platform. This can help you
-understand the landscape of device distribution and decide how to prioritize
-the development of your application features for the devices currently in
-the hands of users. For information about how to target your application to devices based on
-platform version, read about <a 
-href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#ApiLevels">API levels</a>.</p>
+<p>This section provides data about the relative number of devices running a given version of
+the Android platform.</p>
+
+<p>For information about how to target your application to devices based on
+platform version, read <a 
+href="{@docRoot}training/basics/supporting-devices/platforms.html">Supporting Different
+Platform Versions</a>.</p>
 
 
-<h3 id="PlatformCurrent">Current Distribution</h3>
-
-<p>The following pie chart and table is based on the number of Android devices that have accessed
-Google Play within a 14-day period ending on the data collection date noted below.</p>
-
-<div class="col-5" style="margin-left:0">
-
-
-<table>
-<tr>
-  <th>Version</th>
-  <th>Codename</th>
-  <th>API</th>
-  <th>Distribution</th>
-</tr>
-<tr><td><a href="/about/versions/android-1.6.html">1.6</a></td><td>Donut</td>    <td>4</td><td>0.2%</td></tr>
-<tr><td><a href="/about/versions/android-2.1.html">2.1</a></td><td>Eclair</td>   <td>7</td><td>1.9%</td></tr>
-<tr><td><a href="/about/versions/android-2.2.html">2.2</a></td><td>Froyo</td>    <td>8</td><td>7.6%</td></tr>
-<tr><td><a href="/about/versions/android-2.3.html">2.3 - 2.3.2</a>
-                                   </td><td rowspan="2">Gingerbread</td>    <td>9</td><td>0.2%</td></tr>
-<tr><td><a href="/about/versions/android-2.3.3.html">2.3.3 - 2.3.7
-        </a></td><!-- Gingerbread -->                                       <td>10</td><td>44%</td></tr>
-<tr><td><a href="/about/versions/android-3.1.html">3.1</a></td>
-                                                   <td rowspan="2">Honeycomb</td>      <td>12</td><td>0.3%</td></tr>
-<tr><td><a href="/about/versions/android-3.2.html">3.2</a></td>      <!-- Honeycomb --><td>13</td><td>0.9%</td></tr>
-<tr><td><a href="/about/versions/android-4.0.3.html">4.0.3 - 4.0.4</a></td>
-                                                            <td>Ice Cream Sandwich</td><td>15</td><td>28.6%</td></tr> 
-<tr><td><a href="/about/versions/android-4.1.html">4.1</a></td>
-                                                   <td rowspan="2">Jelly Bean</td><td>16</td><td>14.9%</td></tr>
-<tr><td><a href="/about/versions/android-4.2.html">4.2</a></td><!--Jelly Bean-->  <td>17</td><td>1.6%</td></tr>  
-</table>
-
+<div id="version-chart">
 </div>
 
-<div class="col-8" style="margin-right:0">
-<img style="margin-left:30px" alt=""
-src="//chart.apis.google.com/chart?&cht=p&chs=460x245&chf=bg,s,00000000&chd=t:2.0,7.6,44.2,1.2,28.6,16.5&chl=Eclair%20%26%20older|Froyo|Gingerbread|Honeycomb|Ice%20Cream%20Sandwich|Jelly%20Bean&chco=c4df9b,6fad0c"
-/>
 
-</div><!-- end dashboard-panel -->
-
-<p style="clear:both"><em>Data collected during a 14-day period ending on March 4, 2013</em></p>
-<!--
-<p style="font-size:.9em">* <em>Other: 0.1% of devices running obsolete versions</em></p>
--->
-
-<h3 id="PlatformHistorical">Historical Distribution</h3>
-
-<p>The following stacked line graph provides a history of the relative number of
-active Android devices running different versions of the Android platform. It also provides a
-valuable perspective of how many devices your application is compatible with, based on the
-platform version.</p>
-
-<p>Notice that the platform versions are stacked on top of each other with the oldest active
-version at the top. This format indicates the total percent of active devices that are compatible
-with a given version of Android. For example, if you develop your application for
-the version that is at the very top of the chart, then your application is
-compatible with 100% of active devices (and all future versions), because all Android APIs are
-forward compatible. Or, if you develop your application for a version lower on the chart,
-then it is currently compatible with the percentage of devices indicated on the y-axis, where the
-line for that version meets the y-axis on the right.</p>
-
-<p>Each dataset in the timeline is based on the number of Android devices that accessed
-Google Play within a 14-day period ending on the date indicated on the x-axis.</p>
-
-<img alt="" height="250" width="660"
-src="//chart.apis.google.com/chart?&cht=lc&chs=660x250&chxt=x,x,y,r&chf=bg,s,00000000&chxr=0,0,12|1,0,12|2,0,100|3,0,100&chxl=0%3A%7C09/01%7C09/15%7C10/01%7C10/15%7C11/01%7C11/15%7C12/01%7C12/15%7C01/01%7C01/15%7C02/01%7C02/15%7C03/01%7C1%3A%7C2012%7C%7C%7C%7C%7C%7C%7C%7C2013%7C%7C%7C%7C2013%7C2%3A%7C0%25%7C25%25%7C50%25%7C75%25%7C100%25%7C3%3A%7C0%25%7C25%25%7C50%25%7C75%25%7C100%25&chxp=0,0,1,2,3,4,5,6,7,8,9,10,11,12&chxtc=0,5&chd=t:99.3,99.4,99.5,99.5,99.5,99.6,100.0,100.0,100.0,100.0,100.0,100.0,100.0|95.6,95.8,96.1,96.3,96.4,96.7,96.9,97.2,97.4,97.4,97.6,97.7,97.9|81.4,82.3,83.2,83.8,84.7,85.6,86.4,87.0,88.2,88.8,89.4,89.9,90.3|23.7,25.5,27.4,28.7,31.1,33.0,35.4,36.8,40.3,42.0,43.6,45.1,46.0|21.5,23.5,25.5,26.8,29.4,31.4,33.8,35.2,38.8,40.7,42.3,43.9,44.8|1.1,1.4,1.8,2.1,3.2,4.8,6.5,7.5,9.9,11.7,13.3,14.8,16.1&chm=b,c3df9b,0,1,0|tFroyo,689326,1,0,15,,t::-5|b,b4db77,1,2,0|tGingerbread,547a19,2,0,15,,t::-5|b,a5db51,2,3,0|b,96dd28,3,4,0|tIce%20Cream%20Sandwich,293f07,4,0,15,,t::-5|b,83c916,4,5,0|tJelly%20Bean,131d02,5,9,15,,t::-5|B,6fad0c,5,6,0&chg=7,25&chdl=Eclair|Froyo|Gingerbread|Honeycomb|Ice%20Cream%20Sandwich|Jelly%20Bean&chco=add274,9dd14f,8ece2a,7ab61c,659b11,507d08"
-/>
-<p><em>Last historical dataset collected during a 14-day period ending on March 1, 2013</em></p>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+<p style="clear:both"><em>Data collected during a 14-day period ending on May 1, 2013.
+<br/>Any versions with less than 0.1% distribution are not shown.</em>
+</p>
 
 
 
@@ -111,72 +69,22 @@
 <h2 id="Screens">Screen Sizes and Densities</h2>
 
 
-<img alt="" style="float:right;"
-src="//chart.googleapis.com/chart?cht=p&chs=400x250&chf=bg,s,00000000&chco=c4df9b,6fad0c&chl=Xlarge%7CLarge%7CNormal%7CSmall&chd=t%3A4.6,6.1,86.6,2.7" />
-
-
-<img alt="" style="float:right;clear:right"
-src="//chart.googleapis.com/chart?cht=p&chs=400x250&chf=bg,s,00000000&chco=c4df9b,6fad0c&chl=ldpi%7Cmdpi%7Chdpi%7Cxhdpi&chd=t%3A2.2,18,51.1,28.7" />
-
-
-<p>This section provides data about the relative number of active devices that have a particular
+<p>This section provides data about the relative number of devices that have a particular
 screen configuration, defined by a combination of screen size and density. To simplify the way that
 you design your user interfaces for different screen configurations, Android divides the range of
-actual screen sizes and densities into:</p> 
- 
-<ul> 
-<li>A set of four generalized <strong>sizes</strong>: <em>small</em>, <em>normal</em>,
-<em>large</em>, and <em>xlarge</em></em></li>
-<li>A set of four generalized <strong>densities</strong>: <em>ldpi</em> (low), <em>mdpi</em>
-(medium), <em>hdpi</em> (high), and <em>xhdpi</em> (extra high)</li>
-</ul> 
+actual screen sizes and densities into several buckets as expressed by the table below.</p>
 
 <p>For information about how you can support multiple screen configurations in your
-application, see <a href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple
+application, read <a href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple
 Screens</a>.</p>
 
-<p class="note"><strong>Note:</strong> This data is based on the number
-of Android devices that have accessed Google Play within a 7-day period
-ending on the data collection date noted below.</p>
+
+<div id="screens-chart">
+</div>
 
 
-<table style="width:350px">
-<tr>
-<th></th>
-<th scope="col">ldpi</th>
-<th scope="col">mdpi</th>
-<th scope="col">hdpi</th>
-<th scope="col">xhdpi</th>
-</tr>
-<tr><th scope="row">small</th> 
-<td>1.7%</td>     <!-- small/ldpi -->
-<td></td>     <!-- small/mdpi -->
-<td>1.0%</td> <!-- small/hdpi -->
-<td></td>     <!-- small/xhdpi -->
-</tr> 
-<tr><th scope="row">normal</th> 
-<td>0.4%</td>  <!-- normal/ldpi -->
-<td>11%</td> <!-- normal/mdpi -->
-<td>50.1%</td> <!-- normal/hdpi -->
-<td>25.1%</td>      <!-- normal/xhdpi -->
-</tr> 
-<tr><th scope="row">large</th> 
-<td>0.1%</td>     <!-- large/ldpi -->
-<td>2.4%</td> <!-- large/mdpi -->
-<td></td>     <!-- large/hdpi -->
-<td>3.6%</td>     <!-- large/xhdpi -->
-</tr> 
-<tr><th scope="row">xlarge</th> 
-<td></td>     <!-- xlarge/ldpi -->
-<td>4.6%</td> <!-- xlarge/mdpi -->
-<td></td>     <!-- xlarge/hdpi -->
-<td></td>     <!-- xlarge/xhdpi -->
-</tr> 
-</table>
-
-<p style="clear:both"><em>Data collected during a 7-day period ending on October 1, 2012</em></p>
-
-
+<p style="clear:both"><em>Data collected during a 14-day period ending on May 1, 2013
+<br/>Any screen configurations with less than 0.1% distribution are not shown.</em></p>
 
 
 
@@ -187,14 +95,14 @@
 
 <h2 id="OpenGL">Open GL Version</h2>
 
-<p>This section provides data about the relative number of active devices that support a particular
+<p>This section provides data about the relative number of devices that support a particular
 version of OpenGL ES. Note that support for one particular version of OpenGL ES also implies
 support for any lower version (for example, support for version 2.0 also implies support for
 1.1).</p>
 
 
 <img alt="" style="float:right"
-src="//chart.googleapis.com/chart?cht=p&chs=400x250&chco=c4df9b,6fad0c&chl=GL%201.1%20only|GL%202.0%20%26%201.1&chd=t%3A9.2,90.8&chf=bg,s,00000000" />
+src="//chart.googleapis.com/chart?cht=p&chs=400x250&chco=c4df9b,6fad0c&chl=GL%201.1%20only|GL%202.0%20%26%201.1&chd=t%3A0.2,99.8&chf=bg,s,00000000" />
 
 <p>To declare which version of OpenGL ES your application requires, you should use the {@code
 android:glEsVersion} attribute of the <a
@@ -204,10 +112,6 @@
 &lt;supports-gl-texture&gt;}</a> element to declare the GL compression formats that your application
 uses.</p>
 
-<p class="note"><strong>Note:</strong> This data is based on the number
-of Android devices that have accessed Google Play within a 7-day period
-ending on the data collection date noted below.</p>
-
 
 <table style="width:350px">
 <tr>
@@ -216,14 +120,348 @@
 </tr>
 <tr>
 <td>1.1 only</th>
-<td>9.2%</td>
+<td>0.2%</td>
 </tr>
 <tr>
 <td>2.0 &amp; 1.1</th>
-<td>90.8%</td>
+<td>99.8%</td>
 </tr>
 </table>
 
 
 
-<p style="clear:both"><em>Data collected during a 7-day period ending on October 1, 2012</em></p>
+<p style="clear:both"><em>Data collected during a 14-day period ending on May 1, 2013</em></p>
+
+
+
+
+
+
+
+
+
+
+
+
+
+<script>
+var VERSION_DATA =
+[
+  {
+    "chart": "//chart.googleapis.com/chart?chs=500x250&cht=p&chf=bg%2Cs%2C00000000&chd=t%3A1.8%2C3.7%2C38.5%2C0.1%2C27.5%2C28.4&chco=c4df9b%2C6fad0c&chl=Eclair%7CFroyo%7CGingerbread%7CHoneycomb%7CIce%20Cream%20Sandwich%7CJelly%20Bean",
+    "data": [
+      {
+        "api": 4,
+        "name": "Donut",
+        "perc": "0.1"
+      },
+      {
+        "api": 7,
+        "name": "Eclair",
+        "perc": "1.7"
+      },
+      {
+        "api": 8,
+        "name": "Froyo",
+        "perc": "3.7"
+      },
+      {
+        "api": 9,
+        "name": "Gingerbread",
+        "perc": "0.1"
+      },
+      {
+        "api": 10,
+        "name": "Gingerbread",
+        "perc": "38.4"
+      },
+      {
+        "api": 13,
+        "name": "Honeycomb",
+        "perc": "0.1"
+      },
+      {
+        "api": 15,
+        "name": "Ice Cream Sandwich",
+        "perc": "27.5"
+      },
+      {
+        "api": 16,
+        "name": "Jelly Bean",
+        "perc": "26.1"
+      },
+      {
+        "api": 17,
+        "name": "Jelly Bean",
+        "perc": "2.3"
+      }
+    ]
+  }
+];
+
+
+
+
+
+var SCREEN_DATA =
+[
+
+  {
+    "data": {
+      "Large": {
+        "hdpi": "0.4",
+        "ldpi": "0.6",
+        "mdpi": "2.9",
+        "tvdpi": "1.0",
+        "xhdpi": "0.7"
+      },
+      "Normal": {
+        "hdpi": "37.3",
+        "ldpi": "0.1",
+        "mdpi": "16.1",
+        "xhdpi": "24.9",
+        "xxhdpi": "1.3"
+      },
+      "Small": {
+        "ldpi": "9.8"
+      },
+      "Xlarge": {
+        "hdpi": "0.1",
+        "ldpi": "0.2",
+        "mdpi": "4.5",
+        "xhdpi": "0.1"
+      }
+    },
+    "densitychart": "//chart.googleapis.com/chart?chs=400x250&cht=p&chf=bg%2Cs%2C00000000&chd=t%3A10.7%2C23.5%2C1.0%2C37.8%2C25.7%2C1.3&chco=c4df9b%2C6fad0c&chl=ldpi%7Cmdpi%7Ctvdpi%7Chdpi%7Cxhdpi%7Cxxhdpi",
+    "layoutchart": "//chart.googleapis.com/chart?chs=400x250&cht=p&chf=bg%2Cs%2C00000000&chd=t%3A4.9%2C5.6%2C79.7%2C9.8&chco=c4df9b%2C6fad0c&chl=Xlarge%7CLarge%7CNormal%7CSmall"
+  }
+];
+
+
+
+var VERSION_NAMES =
+[
+  {"api":0},{"api":1},{"api":2},{"api":3},
+  { 
+    "api":4,
+    "link":"<a href='/about/versions/android-1.6.html'>1.6</a>",
+    "codename":"Donut",
+  },
+  { "api":5},
+  { "api":6},
+  { 
+    "api":7,
+    "link":"<a href='/about/versions/android-2.1.html'>2.1</a>",
+    "codename":"Eclair",
+  },
+  {
+    "api":8,
+    "link":"<a href='/about/versions/android-2.2.html'>2.2</a>",
+    "codename":"Froyo"
+  },
+  {
+    "api":9,
+    "link":"<a href='/about/versions/android-2.3.html'>2.3 -<br>2.3.2</a>",
+    "codename":"Gingerbread"
+  },
+  {
+    "api":10,
+    "link":"<a href='/about/versions/android-2.3.3.html'>2.3.3 -<br>2.3.7</a>",
+    "codename":"Gingerbread"
+  },
+  { "api":11},
+  {
+    "api":12,
+    "link":"<a href='/about/versions/android-3.1.html'>3.1</a>",
+    "codename":"Honeycomb"
+  },
+  {
+    "api":13,
+    "link":"<a href='/about/versions/android-3.2.html'>3.2</a>",
+    "codename":"Honeycomb"
+  },
+  { "api":14},
+  {
+    "api":15,
+    "link":"<a href='/about/versions/android-4.0.html'>4.0.3 -<br>4.0.4</a>",
+    "codename":"Ice Cream Sandwich"
+  },
+  {
+    "api":16,
+    "link":"<a href='/about/versions/android-4.1.html'>4.1.x</a>",
+    "codename":"Jelly Bean"
+  },
+  {
+    "api":17,
+    "link":"<a href='/about/versions/android-4.2.html'>4.2.x</a>",
+    "codename":"Jelly Bean"
+  }
+];
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+$(document).ready(function(){
+  // for each set of data (each month)
+  $.each(VERSION_DATA, function(i, set) {
+
+    // set up wrapper divs
+    var $div = $('<div class="chart"'
+         + ((i == 0) ? ' style="display:block"' : '')
+         + ' >');
+    var $divtable = $('<div class="col-5" style="margin-left:0">');
+    var $divchart = $('<div class="col-8" style="margin-right:0">');
+
+    // set up a new table
+    var $table = $("<table>");
+    var $trh = $("<tr><th>Version</th>"
+                   + "<th>Codename</th>"
+                   + "<th>API</th>"
+                   + "<th>Distribution</th></tr>");
+    $table.append($trh);
+
+    // loop each data set (each api level represented in stats)
+    $.each(set.data, function(i, data) {
+      // check if we need to rowspan the codename
+      var rowspan = 1;
+      // must not be first row
+      if (i > 0) {
+        // if this row's codename is the same as previous row codename
+        if (data.name == set.data[i-1].name) {
+          rowspan = 0;
+        // otherwise, as long as this is not the last row
+        } else if (i < (set.data.length - 1)) {
+          // increment rowspan for each subsequent row w/ same codename
+          while (data.name == set.data[i+rowspan].name) {
+            rowspan++;
+            // unless we've reached the last row
+            if ((i + rowspan) >= set.data.length) break;
+          }
+        }
+      }
+
+      // create table row and get corresponding version info from VERSION_NAMES
+      var $tr = $("<tr>");
+      $tr.append("<td>" + VERSION_NAMES[data.api].link + "</td>");
+      if (rowspan > 0) {
+        $tr.append("<td rowspan='" + rowspan + "'>" + VERSION_NAMES[data.api].codename + "</td>");
+      }
+      $tr.append("<td>" + data.api + "</td>");
+      $tr.append("<td>" + data.perc + "%</td>");
+      $table.append($tr);
+    });
+
+    // create chart image
+    var $chart = $('<img style="margin-left:30px" alt="" src="' + set.chart + '" />');
+
+    // stack up and insert the elements
+    $divtable.append($table);
+    $divchart.append($chart);
+    $div.append($divtable).append($divchart);
+    $("#version-chart").append($div);
+  });
+
+
+
+  var SCREEN_SIZES = ["Small","Normal","Large","Xlarge"];
+  var SCREEN_DENSITIES = ["ldpi","mdpi","tvdpi","hdpi","xhdpi","xxhdpi"];
+
+
+  // for each set of screens data (each month)
+  $.each(SCREEN_DATA, function(i, set) {
+
+    // set up wrapper divs
+    var $div = $('<div class="screens-chart"'
+         + ((i == 0) ? ' style="display:block"' : '')
+         + ' >');
+
+    // set up a new table
+    var $table = $("<table>");
+    var $trh = $("<tr><th></th></tr>");
+    $.each(SCREEN_DENSITIES, function(i, density) {
+      $trh.append("<th scope='col'>" + density + "</th>");
+    });
+    $trh.append("<th scope='col' class='total'>Total</th>");
+    $table.append($trh);
+
+    // array to hold totals for each density
+    var densityTotals = new Array(SCREEN_DENSITIES.length);
+    $.each(densityTotals, function(i, total) {
+      densityTotals[i] = 0; // make them all zero to start
+    });
+
+    // loop through each screen size
+    $.each(SCREEN_SIZES, function(i, size) {
+      // if there are any devices of this size
+      if (typeof set.data[size] != "undefined") {
+        // create table row and insert data
+        var $tr = $("<tr>");
+        $tr.append("<th scope='row'>" + size + "</th>");
+        // variable to sum all densities for this size
+        var total = 0;
+        // loop through each density
+        $.each(SCREEN_DENSITIES, function(i, density) {
+          var num = typeof set.data[size][density] != "undefined" ? set.data[size][density] : 0;
+          $tr.append("<td>" + (num != 0 ? num + "%" : "") + "</td>");
+          total += parseFloat(num);
+          densityTotals[i] += parseFloat(num);
+        })
+        $tr.append("<td class='total'>" + total.toFixed(1) + "%</td>");
+        $table.append($tr);
+      }
+    });
+
+    // create row of totals for each density
+    var $tr = $("<tr><th class='total'>Total</th></tr>");
+    $.each(densityTotals, function(i, total) {
+      $tr.append("<td class='total'>" + total.toFixed(1) + "%</td>");
+    });
+    $table.append($tr);
+
+    // create charts
+    var $sizechart = $('<img style="float:left;width:380px" alt="" src="'
+            + set.layoutchart + '" />');
+    var $densitychart = $('<img style="float:left;width:380px" alt="" src="'
+            + set.densitychart + '" />');
+
+    // stack up and insert the elements
+    $div.append($table).append($sizechart).append($densitychart);
+    $("#screens-chart").append($div);
+  });
+
+
+});
+
+
+
+function changeVersionDate() {
+  var date = $('#date-versions option:selected').val();
+
+  $(".chart").hide();
+  $(".chart."+date+"").show();
+}
+
+
+function changeScreensVersionDate() {
+  var date = $('#date-screens option:selected').val();
+
+  $(".screens-chart").hide();
+  $(".screens-chart."+date+"").show();
+}
+
+</script>
diff --git a/docs/html/about/versions/android-1.1.jd b/docs/html/about/versions/android-1.1.jd
index b61f186..b2a1615 100644
--- a/docs/html/about/versions/android-1.1.jd
+++ b/docs/html/about/versions/android-1.1.jd
@@ -1,4 +1,5 @@
 page.title=Android 1.1 Version Notes
+excludeFromSuggestions=true
 sdk.version=1.1_r1
 sys.date=February 2009
 @jd:body
diff --git a/docs/html/about/versions/android-1.5-highlights.jd b/docs/html/about/versions/android-1.5-highlights.jd
index ff64e8c..dd4d218 100644
--- a/docs/html/about/versions/android-1.5-highlights.jd
+++ b/docs/html/about/versions/android-1.5-highlights.jd
@@ -1,4 +1,5 @@
 page.title=Android 1.5 Platform Highlights
+excludeFromSuggestions=true
 @jd:body
 
 <p>
diff --git a/docs/html/about/versions/android-1.5.jd b/docs/html/about/versions/android-1.5.jd
index 78dcbd7..ca8771b 100644
--- a/docs/html/about/versions/android-1.5.jd
+++ b/docs/html/about/versions/android-1.5.jd
@@ -1,4 +1,5 @@
 page.title=Android 1.5 Platform
+excludeFromSuggestions=true
 sdk.platform.version=1.5
 sdk.platform.apiLevel=3
 sdk.platform.majorMinor=major
diff --git a/docs/html/about/versions/android-1.6-highlights.jd b/docs/html/about/versions/android-1.6-highlights.jd
index 0c56e8e..88c0f55 100644
--- a/docs/html/about/versions/android-1.6-highlights.jd
+++ b/docs/html/about/versions/android-1.6-highlights.jd
@@ -1,4 +1,5 @@
 page.title=Android 1.6 Platform Highlights
+excludeFromSuggestions=true
 sdk.date=September 2009
 
 @jd:body
diff --git a/docs/html/about/versions/android-1.6.jd b/docs/html/about/versions/android-1.6.jd
index 2a66cd3..313b77a 100644
--- a/docs/html/about/versions/android-1.6.jd
+++ b/docs/html/about/versions/android-1.6.jd
@@ -1,4 +1,5 @@
 page.title=Android 1.6 Platform
+excludeFromSuggestions=true
 sdk.platform.version=1.6
 sdk.platform.apiLevel=4
 sdk.platform.majorMinor=minor
diff --git a/docs/html/about/versions/android-2.0-highlights.jd b/docs/html/about/versions/android-2.0-highlights.jd
index bec49a3..3b23e4d 100644
--- a/docs/html/about/versions/android-2.0-highlights.jd
+++ b/docs/html/about/versions/android-2.0-highlights.jd
@@ -1,4 +1,5 @@
 page.title=Android 2.0 Platform Highlights
+excludeFromSuggestions=true
 sdk.date=October 2009
 
 @jd:body
diff --git a/docs/html/about/versions/android-2.0.1.jd b/docs/html/about/versions/android-2.0.1.jd
index bcba717..ba00231 100644
--- a/docs/html/about/versions/android-2.0.1.jd
+++ b/docs/html/about/versions/android-2.0.1.jd
@@ -1,4 +1,5 @@
 page.title=Android 2.0.1, Release 1
+excludeFromSuggestions=true
 sdk.platform.version=2.0.1
 sdk.platform.apiLevel=6
 sdk.platform.majorMinor=minor
diff --git a/docs/html/about/versions/android-2.0.jd b/docs/html/about/versions/android-2.0.jd
index 7a12e48..82bb78f 100644
--- a/docs/html/about/versions/android-2.0.jd
+++ b/docs/html/about/versions/android-2.0.jd
@@ -1,4 +1,5 @@
 page.title=Android 2.0, Release 1
+excludeFromSuggestions=true
 sdk.platform.version=2.0
 sdk.platform.apiLevel=5
 sdk.platform.majorMinor=major
diff --git a/docs/html/about/versions/android-2.1.jd b/docs/html/about/versions/android-2.1.jd
index 3cb0708..2d5988a 100644
--- a/docs/html/about/versions/android-2.1.jd
+++ b/docs/html/about/versions/android-2.1.jd
@@ -1,4 +1,5 @@
 page.title=Android 2.1 Platform
+excludeFromSuggestions=true
 sdk.platform.version=2.1
 sdk.platform.apiLevel=7
 sdk.platform.majorMinor=minor
diff --git a/docs/html/about/versions/android-2.2-highlights.jd b/docs/html/about/versions/android-2.2-highlights.jd
index 334d036..afbf26b 100644
--- a/docs/html/about/versions/android-2.2-highlights.jd
+++ b/docs/html/about/versions/android-2.2-highlights.jd
@@ -1,4 +1,5 @@
 page.title=Android 2.2 Platform Highlights
+excludeFromSuggestions=true
 
 @jd:body
 
diff --git a/docs/html/about/versions/android-2.2.jd b/docs/html/about/versions/android-2.2.jd
index 64ddca4..bd0f071 100644
--- a/docs/html/about/versions/android-2.2.jd
+++ b/docs/html/about/versions/android-2.2.jd
@@ -1,4 +1,5 @@
 page.title=Android 2.2 APIs
+excludeFromSuggestions=true
 sdk.platform.version=2.2
 sdk.platform.apiLevel=8
 sdk.platform.majorMinor=minor
diff --git a/docs/html/about/versions/android-2.3.3.jd b/docs/html/about/versions/android-2.3.3.jd
index 3b40831..eec0735 100644
--- a/docs/html/about/versions/android-2.3.3.jd
+++ b/docs/html/about/versions/android-2.3.3.jd
@@ -1,4 +1,5 @@
 page.title=Android 2.3.3 APIs
+excludeFromSuggestions=true
 sdk.platform.version=2.3.3
 sdk.platform.apiLevel=10
 
diff --git a/docs/html/about/versions/android-2.3.4.jd b/docs/html/about/versions/android-2.3.4.jd
index b80b4b2..963df9a 100644
--- a/docs/html/about/versions/android-2.3.4.jd
+++ b/docs/html/about/versions/android-2.3.4.jd
@@ -1,4 +1,5 @@
 page.title=Android 2.3.4 APIs
+excludeFromSuggestions=true
 sdk.platform.version=2.3.4
 sdk.platform.apiLevel=10
 
diff --git a/docs/html/about/versions/android-2.3.jd b/docs/html/about/versions/android-2.3.jd
index 4feff51..4b8ef91 100644
--- a/docs/html/about/versions/android-2.3.jd
+++ b/docs/html/about/versions/android-2.3.jd
@@ -1,4 +1,5 @@
 page.title=Android 2.3 APIs
+excludeFromSuggestions=true
 sdk.platform.version=2.3
 sdk.platform.apiLevel=9
 
diff --git a/docs/html/about/versions/android-3.0.jd b/docs/html/about/versions/android-3.0.jd
index d0b41d3..f319fed 100644
--- a/docs/html/about/versions/android-3.0.jd
+++ b/docs/html/about/versions/android-3.0.jd
@@ -1,4 +1,5 @@
 page.title=Android 3.0 APIs
+excludeFromSuggestions=true
 sdk.platform.version=3.0
 sdk.platform.apiLevel=11
 @jd:body
diff --git a/docs/html/about/versions/android-3.1.jd b/docs/html/about/versions/android-3.1.jd
index 8681327..c22dfaa 100644
--- a/docs/html/about/versions/android-3.1.jd
+++ b/docs/html/about/versions/android-3.1.jd
@@ -1,4 +1,5 @@
 page.title=Android 3.1 APIs
+excludeFromSuggestions=true
 sdk.platform.version=3.1
 sdk.platform.apiLevel=12
 @jd:body
diff --git a/docs/html/about/versions/android-3.2.jd b/docs/html/about/versions/android-3.2.jd
index 17f4d85..ef95337 100644
--- a/docs/html/about/versions/android-3.2.jd
+++ b/docs/html/about/versions/android-3.2.jd
@@ -1,4 +1,5 @@
 page.title=Android 3.2 APIs
+excludeFromSuggestions=true
 sdk.platform.version=3.2
 sdk.platform.apiLevel=13
 @jd:body
diff --git a/docs/html/about/versions/android-4.0.3.jd b/docs/html/about/versions/android-4.0.3.jd
index dc69c99..5fa8547 100644
--- a/docs/html/about/versions/android-4.0.3.jd
+++ b/docs/html/about/versions/android-4.0.3.jd
@@ -1,4 +1,5 @@
 page.title=Android 4.0.3 APIs
+excludeFromSuggestions=true
 sdk.platform.version=4.0.3
 sdk.platform.apiLevel=15
 @jd:body
diff --git a/docs/html/about/versions/android-4.0.jd b/docs/html/about/versions/android-4.0.jd
index f2fd0c4..c1a9180 100644
--- a/docs/html/about/versions/android-4.0.jd
+++ b/docs/html/about/versions/android-4.0.jd
@@ -1,4 +1,5 @@
 page.title=Android 4.0 APIs
+excludeFromSuggestions=true
 sdk.platform.version=4.0
 sdk.platform.apiLevel=14
 @jd:body
diff --git a/docs/html/about/versions/android-4.1.jd b/docs/html/about/versions/android-4.1.jd
index 60ed7f0..060f0f4 100644
--- a/docs/html/about/versions/android-4.1.jd
+++ b/docs/html/about/versions/android-4.1.jd
@@ -1,4 +1,5 @@
 page.title=Android 4.1 APIs
+excludeFromSuggestions=true
 sdk.platform.version=4.1
 sdk.platform.apiLevel=16
 @jd:body
diff --git a/docs/html/about/versions/android-4.2.jd b/docs/html/about/versions/android-4.2.jd
index b02c1d1..73d51c5 100644
--- a/docs/html/about/versions/android-4.2.jd
+++ b/docs/html/about/versions/android-4.2.jd
@@ -1,4 +1,5 @@
 page.title=Android 4.2 APIs
+excludeFromSuggestions=true
 sdk.platform.version=4.2
 sdk.platform.apiLevel=17
 @jd:body
diff --git a/docs/html/about/versions/jelly-bean.jd b/docs/html/about/versions/jelly-bean.jd
index acb2538..71957be 100644
--- a/docs/html/about/versions/jelly-bean.jd
+++ b/docs/html/about/versions/jelly-bean.jd
@@ -904,7 +904,7 @@
 
 <h3>Media codec access</h3>
 
-<p>Android 4.1 provides low-level access to platform hardware and software codecs. Apps can query the system to discover what <strong>low-level media codecs</strong> are available on the device and then and use them in the ways they need. For example, you can now create multiple instances of a media codec, queue input buffers, and receive output buffers in return. In addition, the media codec framework supports protected content. Apps can query for an available codec that is able to play protected content with a DRM solution available on the the device.</p>
+<p>Android 4.1 provides low-level access to platform hardware and software codecs. Apps can query the system to discover what <strong>low-level media codecs</strong> are available on the device and then and use them in the ways they need. For example, you can now create multiple instances of a media codec, queue input buffers, and receive output buffers in return. In addition, the media codec framework supports protected content. Apps can query for an available codec that is able to play protected content with a DRM solution available on the device.</p>
 
 <h3>USB Audio</h3>
 
diff --git a/docs/html/design/building-blocks/buttons.jd b/docs/html/design/building-blocks/buttons.jd
index 82e2477..600ec6c 100644
--- a/docs/html/design/building-blocks/buttons.jd
+++ b/docs/html/design/building-blocks/buttons.jd
@@ -1,4 +1,5 @@
 page.title=Buttons
+page.tags="button","input"
 @jd:body
 
 <p>A button consists of text and/or an image that clearly communicates what action will occur when the
diff --git a/docs/html/design/building-blocks/dialogs.jd b/docs/html/design/building-blocks/dialogs.jd
index a2ece2e..2f6ca27 100644
--- a/docs/html/design/building-blocks/dialogs.jd
+++ b/docs/html/design/building-blocks/dialogs.jd
@@ -1,4 +1,5 @@
 page.title=Dialogs
+page.tags="dialog","alert","popup","toast"
 @jd:body
 
 <p>Dialogs prompt the user for decisions or additional information required by the app to continue a
diff --git a/docs/html/design/building-blocks/grid-lists.jd b/docs/html/design/building-blocks/grid-lists.jd
index 775ebcc..8c82ba9 100644
--- a/docs/html/design/building-blocks/grid-lists.jd
+++ b/docs/html/design/building-blocks/grid-lists.jd
@@ -1,4 +1,5 @@
 page.title=Grid Lists
+page.tags="gridview","layout","listview"
 @jd:body
 
 <img src="{@docRoot}design/media/gridview_overview.png">
diff --git a/docs/html/design/building-blocks/lists.jd b/docs/html/design/building-blocks/lists.jd
index aaa86b8..16927a6 100644
--- a/docs/html/design/building-blocks/lists.jd
+++ b/docs/html/design/building-blocks/lists.jd
@@ -1,4 +1,5 @@
 page.title=Lists
+page.tags="listview","layout"
 @jd:body
 
 <p>Lists present multiple line items in a vertical arrangement. They can be used for data selection as
diff --git a/docs/html/design/building-blocks/pickers.jd b/docs/html/design/building-blocks/pickers.jd
index b328df9..47363d0 100644
--- a/docs/html/design/building-blocks/pickers.jd
+++ b/docs/html/design/building-blocks/pickers.jd
@@ -1,4 +1,5 @@
 page.title=Pickers
+page.tags="datepicker","timepicker"
 @jd:body
 
 <p>Pickers provide a simple way to select a single value from a set. In addition to touching the
diff --git a/docs/html/design/building-blocks/progress.jd b/docs/html/design/building-blocks/progress.jd
index 7342387..60ad2ca 100644
--- a/docs/html/design/building-blocks/progress.jd
+++ b/docs/html/design/building-blocks/progress.jd
@@ -1,4 +1,5 @@
 page.title=Progress &amp; Activity
+page.tags="progressbar","download","network"
 @jd:body
 
 <p>Progress bars and activity indicators signal to users that something is happening that will take a moment.</p>
diff --git a/docs/html/design/building-blocks/scrolling.jd b/docs/html/design/building-blocks/scrolling.jd
index 7695157..66999f9 100644
--- a/docs/html/design/building-blocks/scrolling.jd
+++ b/docs/html/design/building-blocks/scrolling.jd
@@ -1,4 +1,5 @@
 page.title=Scrolling
+page.tags="scrollview","listview"
 @jd:body
 
 <p>Scrolling allows the user to navigate to content in the overflow using a swipe gesture. The
diff --git a/docs/html/design/building-blocks/seek-bars.jd b/docs/html/design/building-blocks/seek-bars.jd
index 3407ddd..9d38e36 100644
--- a/docs/html/design/building-blocks/seek-bars.jd
+++ b/docs/html/design/building-blocks/seek-bars.jd
@@ -1,4 +1,5 @@
 page.title=Seek Bars and Sliders
+page.tags="seekbar","progressbar"
 @jd:body
 
 <p>Interactive sliders make it possible to select a value from a continuous or discrete range of values
diff --git a/docs/html/design/building-blocks/spinners.jd b/docs/html/design/building-blocks/spinners.jd
index 279565f..3550b0c 100644
--- a/docs/html/design/building-blocks/spinners.jd
+++ b/docs/html/design/building-blocks/spinners.jd
@@ -1,4 +1,5 @@
 page.title=Spinners
+page.tags="spinner","dropdown"
 @jd:body
 
 <p>Spinners provide a quick way to select one value from a set. In the default state, a spinner shows
diff --git a/docs/html/design/building-blocks/switches.jd b/docs/html/design/building-blocks/switches.jd
index d9cfd07..0b195b9 100644
--- a/docs/html/design/building-blocks/switches.jd
+++ b/docs/html/design/building-blocks/switches.jd
@@ -1,4 +1,5 @@
 page.title=Switches
+page.tags="switch","checkbox","radiobutton","button"
 @jd:body
 
 <p>Switches allow the user to select options. There are three kinds of switches: checkboxes, radio
diff --git a/docs/html/design/building-blocks/tabs.jd b/docs/html/design/building-blocks/tabs.jd
index 0a0f907..79cc9c7 100644
--- a/docs/html/design/building-blocks/tabs.jd
+++ b/docs/html/design/building-blocks/tabs.jd
@@ -1,4 +1,5 @@
 page.title=Tabs
+page.tags="tabs","actionbar","navigation","viewpager"
 @jd:body
 
 <img src="{@docRoot}design/media/tabs_overview.png">
diff --git a/docs/html/design/building-blocks/text-fields.jd b/docs/html/design/building-blocks/text-fields.jd
index 563f247..82321f0 100644
--- a/docs/html/design/building-blocks/text-fields.jd
+++ b/docs/html/design/building-blocks/text-fields.jd
@@ -1,4 +1,5 @@
 page.title=Text Fields
+page.tags="text","edittext","input"
 @jd:body
 
 <p>Text fields allow the user to type text into your app. They can be either single line or multi-line.
diff --git a/docs/html/design/patterns/accessibility.jd b/docs/html/design/patterns/accessibility.jd
index 2c3333f..5f46082 100644
--- a/docs/html/design/patterns/accessibility.jd
+++ b/docs/html/design/patterns/accessibility.jd
@@ -1,4 +1,5 @@
 page.title=Accessibility
+page.tags="accessibility","navigation","input"
 @jd:body
 
 <p>One of Android's missions is to organize the world's information and make it universally accessible and useful. Accessibility is the measure of how successfully a product can be used by people with varying abilities. Our mission applies to all users-including people with disabilities such as visual impairment, color deficiency, hearing loss, and limited dexterity.</p>
diff --git a/docs/html/design/patterns/actionbar.jd b/docs/html/design/patterns/actionbar.jd
index 265ccde..da9c3c3 100644
--- a/docs/html/design/patterns/actionbar.jd
+++ b/docs/html/design/patterns/actionbar.jd
@@ -1,4 +1,5 @@
 page.title=Action Bar
+page.tags="actionbar","navigation"
 @jd:body
 
 <img src="{@docRoot}design/media/action_bar_pattern_overview.png">
diff --git a/docs/html/design/patterns/app-structure.jd b/docs/html/design/patterns/app-structure.jd
index 04af57b..1809ecd 100644
--- a/docs/html/design/patterns/app-structure.jd
+++ b/docs/html/design/patterns/app-structure.jd
@@ -1,4 +1,5 @@
 page.title=Application Structure
+page.tags="navigation","layout","tablet"
 @jd:body
 
 <p>Apps come in many varieties that address very different needs. For example:</p>
diff --git a/docs/html/design/patterns/compatibility.jd b/docs/html/design/patterns/compatibility.jd
index 84ae337..3a56f52 100644
--- a/docs/html/design/patterns/compatibility.jd
+++ b/docs/html/design/patterns/compatibility.jd
@@ -1,4 +1,5 @@
 page.title=Backwards Compatibility
+page.tags="support"
 @jd:body
 
 <p>Significant changes in Android 3.0 included:</p>
diff --git a/docs/html/design/patterns/confirming-acknowledging.jd b/docs/html/design/patterns/confirming-acknowledging.jd
index ce0631b..e347231 100644
--- a/docs/html/design/patterns/confirming-acknowledging.jd
+++ b/docs/html/design/patterns/confirming-acknowledging.jd
@@ -1,4 +1,5 @@
 page.title=Confirming &amp; Acknowledging
+page.tags="dialog","toast","notification"
 @jd:body
 
 <p>In some situations, when a user invokes an action in your app, it's a good idea to <em>confirm</em> or <em>acknowledge</em> that action through text.</p>
diff --git a/docs/html/design/patterns/gestures.jd b/docs/html/design/patterns/gestures.jd
index e579cee..127a1c8 100644
--- a/docs/html/design/patterns/gestures.jd
+++ b/docs/html/design/patterns/gestures.jd
@@ -1,4 +1,5 @@
 page.title=Gestures
+page.tags="gesture","input","touch"
 @jd:body
 
 <p>Gestures allow users to interact with your app by manipulating the screen objects you provide. The
diff --git a/docs/html/design/patterns/help.jd b/docs/html/design/patterns/help.jd
index cdac54d..a32fb25 100644
--- a/docs/html/design/patterns/help.jd
+++ b/docs/html/design/patterns/help.jd
@@ -1,4 +1,5 @@
 page.title=Help
+page.tags="settings","preferences"
 @jd:body
 
 <p>We wish we could guarantee that if you follow every piece of advice on this website, everyone will be able to learn and use your app without a hitch. Sadly, that's not the case.</p>
diff --git a/docs/html/design/patterns/multi-pane-layouts.jd b/docs/html/design/patterns/multi-pane-layouts.jd
index e607676..cbf29cb 100644
--- a/docs/html/design/patterns/multi-pane-layouts.jd
+++ b/docs/html/design/patterns/multi-pane-layouts.jd
@@ -1,4 +1,5 @@
 page.title=Multi-pane Layouts
+page.tags="tablet","navigation","layout","fragment"
 @jd:body
 
 <p>When writing an app for Android, keep in mind that Android devices come in many different screen
diff --git a/docs/html/design/patterns/navigation.jd b/docs/html/design/patterns/navigation.jd
index 656e6e5..b717884 100644
--- a/docs/html/design/patterns/navigation.jd
+++ b/docs/html/design/patterns/navigation.jd
@@ -1,4 +1,5 @@
 page.title=Navigation with Back and Up
+page.tags="navigation","activity","task"
 @jd:body
 
 <p>Consistent navigation is an essential component of the overall user experience. Few things frustrate
diff --git a/docs/html/design/patterns/notifications.jd b/docs/html/design/patterns/notifications.jd
index 0665774..3ae827e 100644
--- a/docs/html/design/patterns/notifications.jd
+++ b/docs/html/design/patterns/notifications.jd
@@ -1,4 +1,5 @@
 page.title=Notifications
+page.tags="notification"
 @jd:body
 
 <p>The notification system allows your app to keep the user informed about events, such as new chat messages or a calendar event. Think of notifications as a news channel that alerts the user to important events as they happen or a log that chronicles events while the user is not paying attention.</p>
diff --git a/docs/html/design/patterns/selection.jd b/docs/html/design/patterns/selection.jd
index e9d22e6..d16e86c 100644
--- a/docs/html/design/patterns/selection.jd
+++ b/docs/html/design/patterns/selection.jd
@@ -1,4 +1,5 @@
 page.title=Selection
+page.tags="actionmode","navigation","contextual"
 @jd:body
 
 <p>Android 3.0 changed the <em>long press</em> gesture&mdash;that is, a touch that's held in the same position for a moment&mdash;to be the global gesture to select data.. This affects the way you should
diff --git a/docs/html/design/patterns/settings.jd b/docs/html/design/patterns/settings.jd
index fef7585..4748e48 100644
--- a/docs/html/design/patterns/settings.jd
+++ b/docs/html/design/patterns/settings.jd
@@ -1,4 +1,5 @@
 page.title=Settings
+page.tags="preferences","sharedpreferences"
 @jd:body
 
 <p>Settings is a place in your app where users indicate their preferences for how your app should
diff --git a/docs/html/design/patterns/swipe-views.jd b/docs/html/design/patterns/swipe-views.jd
index daddd31..f18fc63 100644
--- a/docs/html/design/patterns/swipe-views.jd
+++ b/docs/html/design/patterns/swipe-views.jd
@@ -1,4 +1,5 @@
 page.title=Swipe Views
+page.tags="viewpager","navigation","tabs"
 @jd:body
 
 <p>Efficient navigation is one of the cornerstones of a well-designed app. While apps are generally
diff --git a/docs/html/design/patterns/widgets.jd b/docs/html/design/patterns/widgets.jd
index 54726b1..3152e91 100644
--- a/docs/html/design/patterns/widgets.jd
+++ b/docs/html/design/patterns/widgets.jd
@@ -1,4 +1,5 @@
 page.title=Widgets
+page.tags="appwidget","home"
 @jd:body
 
 <p>Widgets are an essential aspect of home screen customization. You can imagine them as "at-a-glance" views of an app's most important data and functionality that is accessible right from the user's home screen. Users can move widgets across their home screen panels, and, if supported, resize them to tailor the amount of information within a widget to their preference.</p>
@@ -15,7 +16,7 @@
 <div class="layout-content-row">
   <div class="layout-content-col span-6">
     <h3>Collection widgets</h3>
-    <p>As the name implies, collection widgets specialize on displaying multitude elements of the same type, such as a collection of pictures from a gallery app, a collection of articles from a news app or a collection of emails/messages from a communication app. Collection widgets typically focus on two use cases: browsing the collection, and opening an element of the collection to its detail view for consumption. Collection widgets can scroll vertically.</p>
+    <p>As the name implies, collection widgets specialize in displaying multitude elements of the same type, such as a collection of pictures from a gallery app, a collection of articles from a news app or a collection of emails/messages from a communication app. Collection widgets typically focus on two use cases: browsing the collection, and opening an element of the collection to its detail view for consumption. Collection widgets can scroll vertically.</p>
   </div>
   <div class="layout-content-col span-3">
     <img src="{@docRoot}design/media/widgets_collection_gmail.png">
@@ -136,4 +137,4 @@
   <li>Choose the right widget type for your purpose.</li>
   <li>For resizable widgets, plan how the content for your widget should adapt to different sizes.</li>
   <li>Make your widget orientation and device independent by ensuring that the layout is capable of stretching and contracting.</li>
-</ul>
\ No newline at end of file
+</ul>
diff --git a/docs/html/design/style/iconography.jd b/docs/html/design/style/iconography.jd
index ce11cf7..1475e5c 100644
--- a/docs/html/design/style/iconography.jd
+++ b/docs/html/design/style/iconography.jd
@@ -1,4 +1,5 @@
 page.title=Iconography
+page.tags="icons"
 @jd:body
 
 <img src="{@docRoot}design/media/iconography_overview.png">
diff --git a/docs/html/design/style/metrics-grids.jd b/docs/html/design/style/metrics-grids.jd
index e2b9ab5..3116ff6d 100644
--- a/docs/html/design/style/metrics-grids.jd
+++ b/docs/html/design/style/metrics-grids.jd
@@ -1,4 +1,5 @@
 page.title=Metrics and Grids
+page.tags="layout","screens"
 @jd:body
 
 <p>Devices vary not only in physical size, but also in screen density (<acronym title="Dots per
diff --git a/docs/html/design/style/touch-feedback.jd b/docs/html/design/style/touch-feedback.jd
index 5fe72a7..340a3a4 100644
--- a/docs/html/design/style/touch-feedback.jd
+++ b/docs/html/design/style/touch-feedback.jd
@@ -1,4 +1,5 @@
 page.title=Touch Feedback
+page.tags="input","button"
 @jd:body
 
 <div class="layout-content-row" style="margin-bottom: -100px">
diff --git a/docs/html/design/style/typography.jd b/docs/html/design/style/typography.jd
index 427b8c6..114d13b 100644
--- a/docs/html/design/style/typography.jd
+++ b/docs/html/design/style/typography.jd
@@ -1,4 +1,5 @@
 page.title=Typography
+page.tags="textview","font"
 @jd:body
 
 <div class="layout-content-row">
diff --git a/docs/html/design/style/writing.jd b/docs/html/design/style/writing.jd
index 919ea7aa..5358847 100644
--- a/docs/html/design/style/writing.jd
+++ b/docs/html/design/style/writing.jd
@@ -1,4 +1,5 @@
 page.title=Writing Style
+page.tags="dialog","toast","notification"
 @jd:body
 
 <p>When choosing words for your app:</p>
diff --git a/docs/html/develop/index.jd b/docs/html/develop/index.jd
index 190a6d9..0cb2635 100644
--- a/docs/html/develop/index.jd
+++ b/docs/html/develop/index.jd
@@ -345,7 +345,7 @@
   var playlistId = "PLWz5rJ2EKKc_XOgcRukSoKKjewFJZrKV0"; /* DevBytes */
   var script = "<script type='text/javascript' src='//gdata.youtube.com/feeds/api/playlists/"
                 + playlistId +
-                "?v=2&alt=json-in-script&max-results=10&callback=renderDevelopersLivePlaylist&orderby=published'><\/script > ";
+                "?v=2&alt=json-in-script&max-results=10&callback=renderDevelopersLivePlaylist&orderby=reversedPosition'><\/script > ";
   $("body").append(script);
 }
 
diff --git a/docs/html/distribute/googleplay/about/visibility.jd b/docs/html/distribute/googleplay/about/visibility.jd
index 4957c0f..18f60e9 100644
--- a/docs/html/distribute/googleplay/about/visibility.jd
+++ b/docs/html/distribute/googleplay/about/visibility.jd
@@ -39,7 +39,7 @@
 </div>
 
 <div>
-<p>Google Play is also a top destination for visitors from the the web. Anyone
+<p>Google Play is also a top destination for visitors from the web. Anyone
 with a browser can explore everything that Google Play has to offer from its <a
 href="http://play.google.com/store">web site</a>. Android users can even buy and
 install the apps they want and Google Play pushes them automatically to their
@@ -159,7 +159,7 @@
 
 <h4>Featured and Staff Picks</h4>
 
-<p>Each week the the Google Play editorial staff selects a new set of apps to
+<p>Each week the Google Play editorial staff selects a new set of apps to
 promote in its popular <em>Featured</em> and <em>Staff Picks</em> collections.
 </p>
 
diff --git a/docs/html/distribute/googleplay/promote/brand.jd b/docs/html/distribute/googleplay/promote/brand.jd
index cea6d2c..265584f 100644
--- a/docs/html/distribute/googleplay/promote/brand.jd
+++ b/docs/html/distribute/googleplay/promote/brand.jd
@@ -172,5 +172,22 @@
     see <a href="{@docRoot}distribute/googleplay/promote/linking.html">Linking to your products</a></p>
 
 
-<p>If you are not sure you meet these brand guidelines, <a href=
-            "http://services.google.com/permissions/application">please contact us</a>. </p>
+
+<h2 id="Questions">Questions</h2>
+
+<p>To view our full guidelines or for any further brand usage questions, please contact our
+Android Partner Marketing team:</p>
+<ul>
+  <li>For North and South America, please contact <a
+  href="mailto:android-brand-approvals@google.com?Subject=Brand%20Approval%20Questions"
+  >android-brand-approvals@google.com</a></li>
+
+  <li>For Europe and Emerging Markets, please contact <a
+  href="mailto:emea-android-brand@google.com?Subject=Brand%20Approval%20Questions"
+  >emea-android-brand@google.com</a></li>
+
+  <li>For Asia and Pacific-America, please contact <a
+  href="mailto:apac-android-brand-approvals@google.com?Subject=Brand%20Approval%20Questions"
+  >apac-android-brand-approvals@google.com</a></li>
+</ul>
+
diff --git a/docs/html/google/backup/signup.jd b/docs/html/google/backup/signup.jd
index d5c26a1..70f7de2 100644
--- a/docs/html/google/backup/signup.jd
+++ b/docs/html/google/backup/signup.jd
@@ -225,7 +225,7 @@
     } else if ($("input#agree").is(':checked')
         && packagename.length
         && packagename != DEFAULT_TEXT) {
-      window.location = "http://play.google.com/apps/publish/GetBackupApiKey?p=" +
+      window.location = "https://play.google.com/apps/publish/v2/GetBackupApiKey?p=" +
                       encodeURIComponent(packagename);
     } else {
       $("label#agreeLabel,label#pnameLabel").parent().stop().animate({color: "#258AAF"}, 200,
diff --git a/docs/html/google/gcm/gcm.jd b/docs/html/google/gcm/gcm.jd
index 11b5a6c..ce28fb8 100644
--- a/docs/html/google/gcm/gcm.jd
+++ b/docs/html/google/gcm/gcm.jd
@@ -149,7 +149,16 @@
 it to the 3rd-party application server, which uses it to identify each device 
 that has registered to receive messages for a given Android application. In other words,
 a registration ID is tied to a particular Android application running on a particular
-device.</td>
+device.
+<br/>
+<br/>
+<strong>Note:</strong> If you use 
+<a href="https://developer.android.com/google/backup/index.html">backup and restore</a>,
+you should explicitly avoid backing up registration IDs. When you back up
+a device, apps back up shared prefs indiscriminately. If you don't explicitly
+exclude the GCM registration ID, it could get reused on a new device,
+which would cause delivery errors.
+</td>
   </tr>
   <tr>
     <td><strong>Google User Account</strong></td>
@@ -295,6 +304,13 @@
   </li>
 </ul>
 
+<p class="note"><strong>Note:</strong> This section describes how to
+write an app without using the 
+<a href="{@docRoot}reference/com/google/android/gcm/package-summary.html">helper libraries</a>. 
+For details on writing
+an app that uses the helper libraries (which is the recommended and
+simpler approach), see <a href="gs.html">GCM: Getting Started</a>.
+
 <h3 id="manifest">Creating the Manifest</h3>
 
 <p>Every Android application must have an <code>AndroidManifest.xml</code> file (with
@@ -585,6 +601,7 @@
 could not run properly. </li>
 </ul>
 
+
 <h2 id="server">Role of the 3rd-party Application Server</h2>
 
 <p>Before you can write client Android applications that use the GCM feature, you must
@@ -758,9 +775,15 @@
   <pre class="prettyprint">collapse_key=score_update&amp;time_to_live=108&amp;delay_while_idle=1&amp;data.score=4x8&amp;data.time=15:16.2342&amp;registration_id=42
   </pre>
 
-  <p class="note"><strong>Note:</strong> If your organization has a firewall that restricts the traffic to or from the Internet, you'll need to configure it to allow connectivity with GCM. The ports to open are: 5228, 5229, and 5230. GCM typically only uses 5228, but it sometimes uses 5229 and 5230.
-GCM doesn't provide specific IPs. It changes IPs frequently. We recommend against using ACLs but if you must use them, take a broad approach such as the method suggested in <a href="http://support.google.com/code/bin/answer.py?hl=en&answer=62464">this support link</a>.
-</p>
+<p class="note"><strong>Note:</strong> If your organization has a firewall 
+that restricts the traffic to or 
+from the Internet, you need to configure it to allow connectivity with GCM in order for
+your Android devices to receive messages. 
+The ports to open are: 5228, 5229, and 5230. GCM typically only uses 5228, but
+it sometimes uses 5229 and 5230. GCM doesn't provide specific IPs, so you should allow
+your firewall to accept outgoing connections to all IP addresses
+contained in the IP blocks listed in Google's ASN of 15169.</p>
+
 
 <h4 id="response">Response format</h4>
 
@@ -770,7 +793,7 @@
   <li>The GCM server rejects the request.</li>
 </ul>
 
-<p>When the messge is processed successfully, the HTTP response has a 200 status and the body contains more information about the status of the message (including possible errors). When the request is rejected, 
+<p>When the message is processed successfully, the HTTP response has a 200 status and the body contains more information about the status of the message (including possible errors). When the request is rejected, 
 the HTTP response contains a non-200 status code (such as 400, 401, or 503).</p>
 
 <p>The following table summarizes the statuses that the HTTP response header might contain. Click the troubleshoot link for advice on how to deal with each type of error.</p>
@@ -825,7 +848,7 @@
     <td>Array of objects representing the status of the messages processed. The objects are listed in the same order as the request (i.e., for each registration ID in the request, its result is listed in the same index in the response) and they can have these fields:<br>
       <ul>
         <li><code>message_id</code>: String representing the message when it was successfully processed.</li>
-        <li><code>registration_id</code>: If set,  means that GCM processed the message but it has another canonical registration ID for that device, so sender should replace the IDs on future requests (otherwise they might be rejected). This field is never set if there is an error in the request.<br />
+        <li><code>registration_id</code>: If set,  means that GCM processed the message but it has another canonical registration ID for that device, so sender should replace the IDs on future requests (otherwise they might be rejected). This field is never set if there is an error in the request.
         </li>
         <li><code>error</code>: String describing an error that occurred while processing the message for that recipient. The possible values are the same as documented in the above table, plus &quot;Unavailable&quot;  (meaning GCM servers were busy and could not process the message for that  particular recipient, so it could be retried).</li>
     </ul></td>
diff --git a/docs/html/google/gcm/gs.jd b/docs/html/google/gcm/gs.jd
index 37ef684..e96b204 100644
--- a/docs/html/google/gcm/gs.jd
+++ b/docs/html/google/gcm/gs.jd
@@ -1,4 +1,5 @@
 page.title=GCM: Getting Started
+page.tags="cloud","push","messaging"
 @jd:body
 
 <div id="qv-wrapper">
@@ -86,8 +87,15 @@
 
 <h2 id="libs">Install the Helper Libraries</h2>
 <p>To perform the steps described in the following sections, you must first install the 
-<a href="{@docRoot}reference/com/google/android/gcm/package-summary.html">helper libraries</a>. 
-From the SDK Manager, install <strong>Extras &gt; Google Cloud Messaging for Android Library</strong>. This creates a <code>gcm</code> directory under <code><em>YOUR_SDK_ROOT</em>/extras/google/</code> containing these subdirectories: <code>gcm-client</code>, <code>gcm-server</code>, <code>samples/gcm-demo-client</code>, <code>samples/gcm-demo-server</code>, and <code>samples/gcm-demo-appengine</code>.</p>
+<a href="{@docRoot}reference/com/google/android/gcm/package-summary.html">helper libraries</a>. Note that while using the helper libraries is recommended, it is not required. See the <a href="gcm.html#writing_apps">GCM Architectural Overview</a> for a description of how to write apps without using the helper libraries.
+
+<p>To install the helper libraries, choose 
+<strong>Extras &gt; Google Cloud Messaging for Android Library</strong>
+from the SDK Manager. This creates a <code>gcm</code> directory under
+<code><em>YOUR_SDK_ROOT</em>/extras/google/</code> containing these
+subdirectories: <code>gcm-client</code>, <code>gcm-server</code>,
+<code>samples/gcm-demo-client</code>, <code>samples/gcm-demo-server</code>,
+and <code>samples/gcm-demo-appengine</code>.</p>
 
 <p class="note"><strong>Note:</strong> If you don't see <strong>Extras &gt; Google Cloud Messaging for Android Library</strong> in the SDK Manager, make sure you are running version 20 or higher. Be sure to restart the SDK Manager after updating it.</p>
 
diff --git a/docs/html/google/google_toc.cs b/docs/html/google/google_toc.cs
index 81982a1..fa9b9c9 100644
--- a/docs/html/google/google_toc.cs
+++ b/docs/html/google/google_toc.cs
@@ -27,19 +27,24 @@
       <li><a href="<?cs var:toroot?>google/play-services/setup.html">
           <span class="en">Setup</span></a>
       </li>
-
-      <li><a href="<?cs var:toroot?>google/play-services/auth.html">
-          <span class="en">Authorization</span></a>
+      <li><a href="<?cs var:toroot?>google/play-services/games.html">
+          <span class="en">Games</span></a>
       </li>
-
       <li><a href="<?cs var:toroot?>google/play-services/plus.html">
           <span class="en">Google+</span></a>
       </li>
-
       <li><a href="<?cs var:toroot?>google/play-services/maps.html">
           <span class="en">Google Maps</span></a>
       </li>
-
+      <li><a href="<?cs var:toroot?>google/play-services/location.html">
+          <span class="en">Location</span></a>
+      </li>
+      <li><a href="<?cs var:toroot?>google/play-services/gcm.html">
+          <span class="en">GCM</span></a>
+      </li>
+      <li><a href="<?cs var:toroot?>google/play-services/auth.html">
+          <span class="en">Authorization</span></a>
+      </li>
       <li id="gms-tree-list" class="nav-section">
         <div class="nav-section-header">
           <a href="<?cs var:toroot ?>reference/gms-packages.html">
diff --git a/docs/html/google/play-services/auth.jd b/docs/html/google/play-services/auth.jd
index 8e11131..3ccc81a 100644
--- a/docs/html/google/play-services/auth.jd
+++ b/docs/html/google/play-services/auth.jd
@@ -1,4 +1,5 @@
 page.title=Authorization
+page.tags="AccountManager","oauth2"
 @jd:body
 
 <div id="qv-wrapper">
diff --git a/docs/html/google/play-services/games.jd b/docs/html/google/play-services/games.jd
new file mode 100644
index 0000000..8555b94
--- /dev/null
+++ b/docs/html/google/play-services/games.jd
@@ -0,0 +1,69 @@
+page.title=Google Play Games
+header.hide=1
+
+@jd:body
+
+<div class="landing-banner">
+        
+<div class="col-6">
+  <img src="{@docRoot}images/google/game_services.png" alt="">
+</div>
+<div class="col-6">
+
+<h1 itemprop="name" style="margin-bottom:0;">Google Play Games Platform Services</h1>
+  <p itemprop="description">
+  Google Play Games Platform Services lets you integrate popular gaming features such as achievements, leaderboards, and real-time multiplayer gameplay in your apps. Players can sign in using their Google+ identities and share their gaming experience with friends.
+  </p>
+  <p>Visit <a class="external-link"
+    href="https://developers.google.com/games/services/">developers.google.com/games/services</a> for more information about integrating game services into your app.
+</p>
+</div>
+</div>
+
+<div class="landing-docs">
+  <div class="col-6 normal-links">
+    <h3 style="clear:left">Key Developer Features</h3>
+    <h4>Drive engagement with leaderboards</h4>
+    <p>Let players compare scores with friends using leaderboards or see how they rank against other players worldwide. Games Platform Services  automatically maintains daily, weekly, and all-time high scores. <a class="external-link" href="https://developers.google.com/games/services/android/leaderboards">Build leaderboards</a>.</p>
+    
+    <h4>Reward players with achievements</h4>
+    <p>Add hidden and incremental achievements to encourage users to explore your game in new and interesting ways. You can use the built-in UI for Android to display achievement progress.
+    <a class="external-link" href="https://developers.google.com/games/services/android/achievements">Add achievements to your game</a>.</p>
+    </a>
+
+    <h4>Create real-time multiplayer games</h4>
+    <p>Make your game more dynamic by letting multiple players compete or cooperate simultaneously. You can use the Games Platform Services API to invite game participants or auto-match players anonymously, and exchange data between game clients. <a class="external-link" href="https://developers.google.com/games/services/android/multiplayer">Develop real-time multiplayer games</a>.</p>
+    
+    <h4>Save game progress to the cloud</h4>
+    <p>Store game data on Google servers using Cloud Save. Synchronize game progress seamlessly across all your users' devices. <a class="external-link" href="https://developers.google.com/games/services/android/cloudsave">Save games in the cloud</a>.</p>
+  </div>
+
+
+  <div class="col-6 normal-links">
+    <h3 style="clear:left">Getting Started</h3>
+    <h4>1. Get the Google Play services SDK</h4>
+    <p>The Games Platform Services API for Android is part of the Google Play services platform.</p>
+    <p>To use game services, <a href="{@docRoot}google/play-services/setup.html">set up</a>
+      the Google Play services SDK. Then, see the <a class="external-link"
+      href="https://developers.google.com/games/services/android/quickstart">
+      Getting Started guide</a> to set up your app.
+    </p>
+            
+    <h4>2. Run the sample</h4>
+    
+    <p>Once you've installed the Google Play services package, <a class="external-link"
+      href="https://developers.google.com/games/services/downloads/">download the game services samples</a> to learn how to use the major components of the Games Platform Services APIs.
+    </p>
+    
+    <h4>3. Read the documentation</h4>
+    
+    <p>Read the <a class="external-link" href="https://developers.google.com/games/services/terms">
+    API Terms of Service</a>.</p> 
+    <p>Detailed documentation for the Games Platform Services is available at <a class="external-link"
+    href="https://developers.google.com/games/services/">developers.google.com/games/services</a>.
+    </p>
+    <p>For quick access while developing your Android apps, the
+      <a href="{@docRoot}reference/com/google/android/gms/games/package-summary.html">Games Platform Services API for Android reference</a> is available here on developer.android.com.</p>
+  </div>
+
+</div>
diff --git a/docs/html/google/play-services/gcm.jd b/docs/html/google/play-services/gcm.jd
new file mode 100644
index 0000000..67b55ea
--- /dev/null
+++ b/docs/html/google/play-services/gcm.jd
@@ -0,0 +1,69 @@
+page.title=GCM Extensions for Android
+page.tags="cloud","push","messaging"
+header.hide=1
+@jd:body
+
+<div class="landing-banner">
+        
+<div class="col-6">
+  <img src="" alt="">
+</div>
+<div class="col-6">
+
+  <h1 itemprop="name" style="margin-bottom:0;">GCM Extensions for Android</h1>
+   <p itemprop="description">
+GCM extension APIs make it easier to take advantage of enhanced messaging capabilities in your apps, and they can help you simplify your implementation of Google Cloud Messaging.</p>
+
+<p>You can use GCM extensions in any new or existing GCM implementation to build powerful multi-device messaging and presence features for your users.</p>
+
+</div>
+</div>
+
+
+<div class="landing-docs">
+  <div class="col-6 normal-links">
+    <h3 style="clear:left">Key Developer Features</h3>
+
+    <h4>Faster, easier GCM setup</h4>
+    <p>Streamlined registration makes it simple and fast to add GCM support to your Android app. <a href="{@docRoot}google/play-services/gcm/gs.html">Learn more &raquo;</a></p>
+
+
+    <h4>Bidirectional messaging over XMPP</h4>
+    <p>GCM's Cloud Connection Service (CCS) lets you communicate with Android devices over a persistent XMPP connection. Communication is asynchronous and bidirectional, and you can use the service in tandem with existing GCM APIs. You can use <a href="https://services.google.com/fb/forms/gcm/">this form</a> to sign up for CCS. <a href="{@docRoot}google/gcm/ccs.html">Learn more &raquo;</a></p>
+
+   <!-- <p>To get started, sign up using <a href="https://services.google.com/fb/forms/gcm/">this form</a> and then learn how to <a href="{@docRoot}google/gcm/ccs.html">send XMPP messages</a>.</p> -->
+    
+    <h4>Seamless multi-device messaging</h4>
+    <p>New user notifications let you send a single message simultaneously to all of a user's Android devices. </p>
+
+    <p>GCM lets you map all of a user's multiple devices to a single notification key, which you can then reference as the target for messages that you are sending to that user. 
+    <a href="{@docRoot}google/gcm/notifications.html">Learn more &raquo;</a></p>
+    </a>
+    
+
+  </div>
+
+
+  <div class="col-6 normal-links">
+    <h3 style="clear:left">Getting Started</h3>
+    <h4>1. Get the Google Play services SDK</h4>
+    <p>The GCM Extension APIs are part of the Google Play services platform. To use the APIs, <a href="{@docRoot}google/play-services/setup.html">set up
+      the Google Play services SDK</a>. 
+    </p>
+            
+    <h4>2. Create a Google APIs project</h4>
+    
+    <p>To use GCM, you need to set up a Google APIs project and get an application key. If you are already using GCM, you can use your existing project and key. <a href="{@docRoot}google/play-services/gcm/gs.html#google_apis">Learn more &raquo;</a></p>
+
+    <h4>3. Set up GCM in your app</h4>
+    
+    <p>To send and receive messages over GCM, you need to update the manifest and add code to register with GCM and handle messages. See <a href="{@docRoot}google/play-services/gcm/gs.html#manifest">Get Started</a> for details.
+    </p>
+    
+    <h4>4. Integrate GCM with your backend servers</h4>
+
+    <p>A complete GCM implementation requires a server-side implementation, in addition to the client implementation in your app. For complete information, make sure to read the <a href="{@docRoot}google/gcm/index.html">Google Cloud Messaging documentation</a>. 
+
+  </div>
+
+</div>
diff --git a/docs/html/google/play-services/location.jd b/docs/html/google/play-services/location.jd
new file mode 100644
index 0000000..430aaeb
--- /dev/null
+++ b/docs/html/google/play-services/location.jd
@@ -0,0 +1,89 @@
+page.title=Location APIs
+page.tags="location","geofence", "geofencing", "activity recognition", "activity detection", "gps"
+header.hide=1
+@jd:body
+
+
+    <div class="landing-banner">
+
+<div class="col-6">
+    <img src="{@docRoot}images/google/gps-location.png" alt="Location APIs Logo">
+</div>
+
+<div class="col-6">
+
+<h1 itemprop="name" style="margin-bottom:0;">Location APIs</h1>
+<p itemprop="description">
+    The location APIs make it easy for you to build location-aware applications, without needing to
+    focus on the details of the underlying location technology. They also let you minimize
+    power consumption by using all of the capabilities of the device hardware.
+</p>
+
+<p>
+    To get started, first <a href="{@docRoot}google/play-services/setup.html">set up</a>
+    the Google Play services SDK. You can learn how to use the APIs in the training
+    class <a href="{@docRoot}training/basics/location/index.html">Making Your App Location Aware</a>, 
+    and details are available in the <a href="{@docRoot}reference/com/google/android/location/package-summary.html">Location API reference</a>. To look at a code example, <a href="">download the sample app</a>.
+</p>
+</div>
+</div>
+<div class="landing-docs">
+  <h3 style="clear:left">Key Developer Features</h3>
+  <div class="layout-content-row">
+  <div class="layout-content-col span-6">
+
+
+
+<h4 style="font-weight:bold">Fused location provider</h4>
+<ul>
+    <li>
+        <em>Simple APIs</em>: Lets you specify high-level needs like "high accuracy" or "low power", instead of
+        having to worry about location providers.
+    </li>
+    <li>
+        <em>Always-on location</em>: Gives your apps immediate access to the best, most recent location.
+    </li>
+    <li>
+        <em>Power-efficiency</em>: Minimizes your app's use of power. Based on all incoming location requests and available sensors, fused location provider chooses the most efficient way to meet those needs.
+    </li>
+    <li>
+        <em>Versatility</em>: Meets a wide range of needs, from foreground uses that need highly accurate
+        location to background uses that need periodic location updates with negligible power impact.
+    </li>
+
+</ul>
+
+<h4 style="font-weight:bold">Geofencing APIs</h4>
+<ul>
+    <li>
+        <em>Simple but powerful APIs</em>: Allows batch addition and removal of geofences. Ability to manage
+        multiple geofences at the same time. Ability to filter alerts for both entry and exit or
+        entry only or exit only.
+    </li>
+    <li>
+        <em>Optimized for battery</em>: Adjusts location updates based on user’s proximity to the geofence
+        and user’s modality (still, walking, driving, and so on).
+    </li>
+</ul>
+</div>
+
+<div class="layout-content-col span-6">
+<h4 style="font-weight:bold">Activity recognition</h4>
+<ul>
+    <li>
+        Uses low-power sensors to recognize the user's current physical activity, such as walking,
+        cycling, or driving, or remaining still.
+    </li>
+    <li>
+        Great for adding movement awareness to location awareness. Apps can adjust the amount of
+        location awareness they provide, based on the current user movement. For example, a
+        navigation app can request more frequent updates when the user is driving.
+    </li>
+    <li>
+        Features for advanced applications: For advanced applications that want to do their own
+        post-processing, this API also makes available confidence values for each of the activities.
+        It also includes two activities that indicate unreliable measurements: unknown and tilt.
+    </li>
+</ul>
+</div>
+</div>
\ No newline at end of file
diff --git a/docs/html/google/play-services/maps.jd b/docs/html/google/play-services/maps.jd
index 5a4aaf4..965444a 100644
--- a/docs/html/google/play-services/maps.jd
+++ b/docs/html/google/play-services/maps.jd
@@ -1,4 +1,5 @@
 page.title=Google Maps Android API
+page.tags="mapview","location"
 header.hide=1
 
 @jd:body
diff --git a/docs/html/google/play-services/plus.jd b/docs/html/google/play-services/plus.jd
index de921be..e126dad 100644
--- a/docs/html/google/play-services/plus.jd
+++ b/docs/html/google/play-services/plus.jd
@@ -1,4 +1,5 @@
 page.title=Google+ Platform for Android
+page.tags="authentication","signin","social"
 header.hide=1
 
 @jd:body
diff --git a/docs/html/google/play-services/setup.jd b/docs/html/google/play-services/setup.jd
index 0cf2df3..a960a18 100644
--- a/docs/html/google/play-services/setup.jd
+++ b/docs/html/google/play-services/setup.jd
@@ -1,4 +1,4 @@
-page.title=Setup
+page.title=Setup Google Play Services SDK
 @jd:body
 
 
diff --git a/docs/html/google/play/billing/billing_integrate.jd b/docs/html/google/play/billing/billing_integrate.jd
index 297e906..57227a8 100755
--- a/docs/html/google/play/billing/billing_integrate.jd
+++ b/docs/html/google/play/billing/billing_integrate.jd
@@ -19,6 +19,7 @@
        <li><a href="#Subs">Implementing Subscriptions</a><li>
        </ol>
     </li>
+    <li><a href="#billing-security">Securing Your App</a>
   </ol>
   <h2>Reference</h2>
   <ol>
@@ -40,31 +41,63 @@
 
 <p class="note"><strong>Note:</strong> To see a complete implementation and learn how to test your application, see the <a href="{@docRoot}training/in-app-billing/index.html">Selling In-app Products</a> training class. The training class provides a complete sample In-app Billing application, including convenience classes to handle key tasks related to setting up your connection, sending billing requests and processing responses from Google Play, and managing background threading so that you can make In-app Billing calls from your main activity.</p>
 
-<p>Before you start, be sure that you read the <a href="{@docRoot}google/play/billing/billing_overview.html">In-app Billing Overview</a> to familiarize yourself with concepts that will make it easier for you to implement In-app Billing.</p>
+<p>Before you start, be sure that you read the <a href="{@docRoot}google/play/billing/billing_overview.html">In-app Billing Overview</a> to familiarize yourself with 
+concepts that will make it easier for you to implement In-app Billing.</p>
 
-<p>To implement In-app Billing in your application, you need to do the following:</p>
+<p>To implement In-app Billing in your application, you need to do the 
+following:</p>
 <ol>
   <li>Add the In-app Billing library to your project.</li>
   <li>Update your {@code AndroidManifest.xml} file.</li>
-  <li>Create a {@code ServiceConnection} and bind it to {@code IInAppBillingService}.</li>
-  <li>Send In-app Billing requests from your application to {@code IInAppBillingService}.</li>
+  <li>Create a {@code ServiceConnection} and bind it to 
+{@code IInAppBillingService}.</li>
+  <li>Send In-app Billing requests from your application to 
+{@code IInAppBillingService}.</li>
   <li>Handle In-app Billing responses from Google Play.</li>
 </ol>
 
 <h2 id="billing-add-aidl">Adding the AIDL file to your project</h2>
 
-<p>The {@code TriviaDriva} sample application contains an Android Interface Definition Language (AIDL) file which defines the interface to Google Play's In-app Billing service. When you add this file to your project, the Android build environment creates an interface file (<code>IIAppBillingService.java</code>). You can then use this interface to make billing requests by invoking IPC method calls.</p>
+<p>{@code IInAppBillingService.aidl} is an Android Interface Definition 
+Language (AIDL) file that defines the interface to the In-app Billing Version 
+3 service. You will use this interface to make billing requests by invoking IPC 
+method calls.</p>
+<p>To get the AIDL file:</p>
+<ol>
+<li>Open the <a href="{@docRoot}tools/help/sdk-manager.html">Android SDK Manager</a>.</li>
+<li>In the SDK Manager, expand the {@code Extras} section.</li>
+<li>Select <strong>Google Play Billing Library</strong>.</li>
+<li>Click <strong>Install packages</strong> to complete the download.</li>
+</ol>
+<p>The {@code IInAppBillingService.aidl} file will be installed to {@code &lt;sdk&gt;/extras/google/play_billing/}.</p>
 
-<p>To add the In-app Billing Version 3 library to your project:</p>
+<p>To add the AIDL to your project:</p>
 <ol>
 <li>Copy the {@code IInAppBillingService.aidl} file to your Android project.
   <ul>
-  <li>If you are using Eclipse: Import the {@code IInAppBillingService.aidl} file into your {@code /src} directory. Eclipse automatically generates the interface file when you build your project.</li>
-  <li>If you are developing in a non-Eclipse environment: Create the following directory {@code /src/com/android/vending/billing} and copy the {@code IInAppBillingService.aidl} file into this directory. Put the AIDL file into your project and use the Ant tool to build your project so that the
+  <li>If you are using Eclipse: 
+     <ol type="a">
+        <li>If you are starting from an existing Android project, open the project 
+in Eclipse. If you are creating a new Android project from scratch, click 
+<strong>File</strong> &gt; <strong>New</strong> &gt; <strong>Android Application 
+Project</strong>, then follow the instructions in the <strong>New Android 
+Application</strong> wizard to create a new project in your workspace.</li>
+	<li>In the {@code /src} directory, click <strong>File</strong> &gt; 
+<strong>New</strong> &gt; <strong>Package</strong>, then create a package named {@code com.android.vending.billing}.</li>
+	<li>Copy the {@code IInAppBillingService.aidl} file from {@code &lt;sdk&gt;/extras/google/play_billing/} and paste it into the {@code src/com.android.vending.billing/} 
+folder in your workspace.</li>
+     </ol>
+  </li>
+  <li>If you are developing in a non-Eclipse environment: Create the following 
+directory {@code /src/com/android/vending/billing} and copy the 
+{@code IInAppBillingService.aidl} file into this directory. Put the AIDL file 
+into your project and use the Ant tool to build your project so that the
 <code>IInAppBillingService.java</code> file gets generated.</li>
   </ul>
 </li>
-<li>Build your application. You should see a generated file named {@code IInAppBillingService.java} in the {@code /gen} directory of your project.</li>
+<li>Build your application. You should see a generated file named 
+{@code IInAppBillingService.java} in the {@code /gen} directory of your 
+project.</li>
 </ol>
 
 
@@ -329,6 +362,34 @@
 the user. Once a subscription expires without renewal, it will no longer appear 
 in the returned {@code Bundle}.</p>
 
+<h2 id="billing-security">Securing Your Application</h2>
+
+<p>To help ensure the integrity of the transaction information that is sent to 
+your application, Google Play signs the JSON string that contains the response 
+data for a purchase order. Google Play uses the private key that is associated 
+with your application in the Developer Console to create this signature. The 
+Developer Console generates an RSA key pair for each application.<p>
+
+<p class="note"><strong>Note:</strong>To find the public key portion of this key 
+pair, open your application's details in the Developer Console, then click on 
+<strong>Services & APIs</strong>, and look at the field titled 
+<strong>Your License Key for This Application</strong>.</p>
+
+<p>The Base64-encoded RSA public key generated by Google Play is in binary 
+encoded, X.509 subjectPublicKeyInfo DER SEQUENCE format. It is the same public 
+key that is used with Google Play licensing.</p>
+
+<p>When your application receives this signed response you can 
+use the public key portion of your RSA key pair to verify the signature. 
+By performing signature verification you can detect responses that have 
+been tampered with or that have been spoofed. You can perform this signature 
+verification step in your application; however, if your application connects 
+to a secure remote server then we recommend that you perform the signature 
+verification on that server.</p>
+
+<p>For more information about best practices for security and design, see <a
+href="{@docRoot}google/play/billing/billing_best_practices.html">Security and Design</a>.</p>
+
 
 
 
diff --git a/docs/html/google/play/billing/billing_reference.jd b/docs/html/google/play/billing/billing_reference.jd
index 1410e65..e168d70 100755
--- a/docs/html/google/play/billing/billing_reference.jd
+++ b/docs/html/google/play/billing/billing_reference.jd
@@ -143,7 +143,9 @@
   </tr>
   <tr>
     <td>{@code INAPP_DATA_SIGNATURE}</td>
-    <td>String containing the signature of the purchase data that was signed with the private key of the developer.</td>
+    <td>String containing the signature of the purchase data that was signed 
+with the private key of the developer. The data signature uses the 
+RSASSA-PKCS1-v1_5 scheme.</td>
   </tr>
 </table>
 </p>
diff --git a/docs/html/google/play/billing/billing_subscriptions.jd b/docs/html/google/play/billing/billing_subscriptions.jd
index fe56f44..92725cf 100644
--- a/docs/html/google/play/billing/billing_subscriptions.jd
+++ b/docs/html/google/play/billing/billing_subscriptions.jd
@@ -3,26 +3,7 @@
 parent.link=index.html
 @jd:body
 
-<!--notice block -->
-    <div style="background-color:#fffbd9;width:100%;margin-bottom:1em;padding:8px 8px 1px;">
-      <p><em>15 February 2013</em></p>
-      <p>In-app Billing V3 now supports subscriptions and you can get
-        started developing today. A small app update is currently being
-        rolled out to Android devices. This process is automatic and
-        most devices will get the update in the next few days. However,
-        if you wish to get the update today to start developing right
-        away, simply reboot your device. </p>
-
-      <p>However, we recommend that you <em>do not publish</em> an app with 
-        V3 subscriptions until all Android devices have received the update. We'll
-        notify you here that all devices have received the update and its safe
-        to publish your apps that use V3 subscriptions. </p>
-    </div>
-
-<!-- Use non-standard wrapper to support notice block. Restore standard 
-     wrapper when notice is removed. -->
-<!--<div id="qv-wrapper"> -->
-<div id="qv-wrapper" style="margin-top:.25em;">
+<div id="qv-wrapper">
 <div id="qv">
   <h2>Quickview</h2>
   <ul>
diff --git a/docs/html/google/play/billing/v2/api.jd b/docs/html/google/play/billing/v2/api.jd
index 9d3a045..7e386a2 100644
--- a/docs/html/google/play/billing/v2/api.jd
+++ b/docs/html/google/play/billing/v2/api.jd
@@ -1,4 +1,5 @@
 page.title=In-app Billing Version 2
+excludeFromSuggestions=true
 @jd:body
 
 <div style="background-color:#fffdeb;width:100%;margin-bottom:1em;padding:.5em;">In-app Billing Version 2 is superseded. Please <a href="{@docRoot}google/play/billing/billing_overview.html#migration">migrate to Version 3</a> at your earliest convenience.</div>
diff --git a/docs/html/google/play/billing/v2/billing_integrate.jd b/docs/html/google/play/billing/v2/billing_integrate.jd
index 5ab1577..ca41e0b 100755
--- a/docs/html/google/play/billing/v2/billing_integrate.jd
+++ b/docs/html/google/play/billing/v2/billing_integrate.jd
@@ -1,4 +1,5 @@
 page.title=Implementing In-app Billing <span style="font-size:16px;">(IAB Version 2)</span>
+excludeFromSuggestions=true
 @jd:body
 
 <div style="background-color:#fffdeb;width:100%;margin-bottom:1em;padding:.5em;">In-app Billing Version 2 is superseded. Please <a href="{@docRoot}google/play/billing/billing_overview.html#migration">migrate to Version 3</a> at your earliest convenience.</div>
diff --git a/docs/html/google/play/billing/v2/billing_reference.jd b/docs/html/google/play/billing/v2/billing_reference.jd
index 84576bc..a946295 100644
--- a/docs/html/google/play/billing/v2/billing_reference.jd
+++ b/docs/html/google/play/billing/v2/billing_reference.jd
@@ -1,4 +1,5 @@
 page.title=In-app Billing Reference <span style="font-size:16px;">(IAB Version 2)</span>
+excludeFromSuggestions=true
 @jd:body
 
 <div style="background-color:#fffdeb;width:100%;margin-bottom:1em;padding:.5em;">In-app Billing Version 2 is superseded. Please <a href="{@docRoot}google/play/billing/billing_overview.html#migration">migrate to Version 3</a> at your earliest convenience.</div>
diff --git a/docs/html/google/play/billing/v2/billing_subscriptions.jd b/docs/html/google/play/billing/v2/billing_subscriptions.jd
index 856ecd7..db18a53 100755
--- a/docs/html/google/play/billing/v2/billing_subscriptions.jd
+++ b/docs/html/google/play/billing/v2/billing_subscriptions.jd
@@ -1,4 +1,5 @@
 page.title=Implementing Subscriptions  <span style="font-size:16px;">(IAB Version 2)</span>
+excludeFromSuggestions=true
 @jd:body
 
 <div style="background-color:#fffdeb;width:100%;margin-bottom:1em;padding:.5em;">In-app Billing Version 2 is superseded. Please <a href="{@docRoot}google/play/billing/billing_overview.html#migration">migrate to Version 3</a> at your earliest convenience.</div>
diff --git a/docs/html/google/play/licensing/adding-licensing.jd b/docs/html/google/play/licensing/adding-licensing.jd
index f991e14..93561f6 100644
--- a/docs/html/google/play/licensing/adding-licensing.jd
+++ b/docs/html/google/play/licensing/adding-licensing.jd
@@ -598,15 +598,15 @@
 <p>First, open the class file of the application's main Activity and import
 {@code LicenseChecker} and {@code LicenseCheckerCallback} from the LVL package.</p>
 
-<pre>    import com.android.vending.licensing.LicenseChecker;
-    import com.android.vending.licensing.LicenseCheckerCallback;</pre>
+<pre>    import com.google.android.vending.licensing.LicenseChecker;
+    import com.google.android.vending.licensing.LicenseCheckerCallback;</pre>
 
 <p>If you are using the default {@code Policy} implementation provided with the LVL,
 ServerManagedPolicy, import it also, together with the AESObfuscator. If you are
 using a custom {@code Policy} or {@code Obfuscator}, import those instead. </p>
 
-<pre>    import com.android.vending.licensing.ServerManagedPolicy;
-    import com.android.vending.licensing.AESObfuscator;</pre>
+<pre>    import com.google.android.vending.licensing.ServerManagedPolicy;
+    import com.google.android.vending.licensing.AESObfuscator;</pre>
 
 <h3 id="lc-impl">Implement LicenseCheckerCallback as a private inner class</h3>
 
@@ -853,37 +853,39 @@
 
 <h3 id="account-key">Embed your public key for licensing</h3>
 
-<p>For each publisher account, the Google Play service automatically
-generates a  2048-bit RSA public/private key pair that is used exclusively for
-licensing. The key pair is uniquely associated with the publisher account and is
-shared across all applications that are published through the account. Although
-associated with a publisher account, the key pair is <em>not</em> the same as
-the key that you use to sign your applications (or derived from it).</p>
+<p>For each application, the Google Play service automatically
+generates a  2048-bit RSA public/private key pair that is used for 
+licensing and in-app billing. The key pair is uniquely associated with the 
+application. Although associated with the application, the key pair is 
+<em>not</em> the same as the key that you use to sign your applications (or derived from it).</p>
 
 <p>The Google Play Developer Console exposes the public key for licensing to any
-developer signed in to the publisher account, but it keeps the private key
+developer signed in to the Developer Console, but it keeps the private key
 hidden from all users in a secure location. When an application requests a
 license check for an application published in your account, the licensing server
-signs the license response using the private key of your account's key pair.
+signs the license response using the private key of your application's key pair.
 When the LVL receives the response, it uses the public key provided by the
 application to verify the signature of the license response. </p>
 
-<p>To add licensing to an application, you must obtain your publisher account's
+<p>To add licensing to an application, you must obtain your application's
 public key for licensing and copy it into your application. Here's how to find
-your account's public key for licensing:</p>
+your application's public key for licensing:</p>
 
 <ol>
 <li>Go to the Google Play <a
 href="http://play.google.com/apps/publish">Developer Console</a> and sign in.
 Make sure that you sign in to the account from which the application you are
 licensing is published (or will be published). </li>
-<li>In the account home page, locate the "Edit profile" link and click it. </li>
-<li>In the Edit Profile page, locate the "Licensing" pane, shown below. Your
-public key for licensing is given in the "Public key" text box. </li>
+<li>In the application details page, locate the <strong>Services & APIs</strong> 
+link and click it. </li>
+<li>In the <strong>Services & APIs</strong> page, locate the 
+<strong>Licensing & In-App Billing</strong> section. Your public key for 
+licensing is given in the 
+<strong>Your License Key For This Application</strong> field. </li>
 </ol>
 
 <p>To add the public key to your application, simply copy/paste the key string
-from the text box into your application as the value of the String variable
+from the field into your application as the value of the String variable
 <code>BASE64_PUBLIC_KEY</code>. When you are copying, make sure that you have
 selected the entire key string, without omitting any characters. </p>
 
@@ -965,16 +967,6 @@
 </ul>
 </div>
 
-
-
-
-
-
-
-
-
-
-
 <h2 id="app-obfuscation">Obfuscating Your Code</h2>
 
 <p>To ensure the security of your application, particularly for a paid
diff --git a/docs/html/google/play/licensing/index.jd b/docs/html/google/play/licensing/index.jd
index a13be10..6632fc0 100644
--- a/docs/html/google/play/licensing/index.jd
+++ b/docs/html/google/play/licensing/index.jd
@@ -16,7 +16,7 @@
 
 <p>The licensing service is a secure means of controlling access to your applications. When an
 application checks the licensing status, the Google Play server signs the licensing status
-response using a key pair that is uniquely associated with the publisher account. Your application
+response using a key pair that is uniquely associated with the application. Your application
 stores the public key in its compiled <code>.apk</code> file and uses it to verify the licensing
 status response.</p>
 
diff --git a/docs/html/google/play/licensing/licensing-reference.jd b/docs/html/google/play/licensing/licensing-reference.jd
index 4240097..7bfa61a 100644
--- a/docs/html/google/play/licensing/licensing-reference.jd
+++ b/docs/html/google/play/licensing/licensing-reference.jd
@@ -186,7 +186,7 @@
 </tr>
 <tr>
 <td>{@code ERROR_SERVER_FAILURE}</td>
-<td>Server error &mdash; the server could not load the publisher account's key
+<td>Server error &mdash; the server could not load the application's key
 pair for licensing.</td>
 <td>No</td>
 <td></td>
diff --git a/docs/html/google/play/licensing/overview.jd b/docs/html/google/play/licensing/overview.jd
index 2434a4c..4e1a9c9 100644
--- a/docs/html/google/play/licensing/overview.jd
+++ b/docs/html/google/play/licensing/overview.jd
@@ -38,13 +38,13 @@
 the result to your application, which can allow or disallow further use of the
 application as needed.</p>
 
-<p class="note"><strong>Note:</strong> If a paid application has been uploaded to Google Play but
-saved only as a draft application (the app is unpublished), the licensing server considers all users
-to be licensed users of the application (because it's not even possible to purchase the app).
-This exception is necessary in order for you to perform testing of your licensing
+<p class="note"><strong>Note:</strong> If a paid application has been uploaded 
+to Google Play, but saved only as a draft application (the app is 
+unpublished), the licensing server considers all users to be licensed users of 
+the application (because it's not even possible to purchase the app). This 
+exception is necessary in order for you to perform testing of your licensing 
 implementation.</p>
 
-
 <div class="figure" style="width:469px">
 <img src="{@docRoot}images/licensing_arch.png" alt=""/>
 <p class="img-caption"><strong>Figure 1.</strong> Your application initiates a
@@ -102,10 +102,11 @@
 server and you.</p>
 
 <p>The licensing service generates a single licensing key pair for each
-publisher account and exposes the public key in your account's profile page. You must copy the
-public key from the web site and embed it in your application source code. The server retains the
-private key internally and uses it to sign license responses for the applications you
-publish with that account.</p>
+application and exposes the public key in your application's 
+<strong>Services & APIs</strong> page in the Developer Console. You must copy 
+the public key from the Developer Console and embed it in your application 
+source code. The server retains the private key internally and uses it to sign 
+license responses for the applications you publish with that account.</p>
 
 <p>When your application receives a signed response, it uses the embedded public
 key to verify the data. The use of public key cryptography in the licensing
@@ -221,7 +222,7 @@
 <p>Licensing lets you move to a license-based model that is enforceable on
 all devices that have access to Google Play. Access is not bound to the
 characteristics of the host device, but to your
-publisher account on Google Play (through the app's public key) and the
+application on Google Play (through the app's public key) and the
 licensing policy that you define. Your application can be installed and
 managed on any device on any storage, including SD card.</p>
 
diff --git a/docs/html/guide/appendix/app-intents.jd b/docs/html/guide/appendix/app-intents.jd
index 110196c..8898927 100644
--- a/docs/html/guide/appendix/app-intents.jd
+++ b/docs/html/guide/appendix/app-intents.jd
@@ -1,4 +1,5 @@
 page.title=Reference of Available Intents
+excludeFromSuggestions=true
 @jd:body
 
 <p>This document describes the default applications and settings that Google provides
diff --git a/docs/html/guide/appendix/g-app-intents.jd b/docs/html/guide/appendix/g-app-intents.jd
index 10ec01e..9ec72db 100644
--- a/docs/html/guide/appendix/g-app-intents.jd
+++ b/docs/html/guide/appendix/g-app-intents.jd
@@ -1,4 +1,5 @@
 page.title=Intents List: Invoking Google Applications on Android Devices
+excludeFromSuggestions=true
 @jd:body
 
 <div class="sidebox-wrapper">
diff --git a/docs/html/guide/appendix/glossary.jd b/docs/html/guide/appendix/glossary.jd
index 94cb0f0..af60eb7 100644
--- a/docs/html/guide/appendix/glossary.jd
+++ b/docs/html/guide/appendix/glossary.jd
@@ -1,4 +1,5 @@
 page.title=Glossary
+excludeFromSuggestions=true
 @jd:body
 
 <p>The list below defines some of the basic terminology of the Android platform. </p>
diff --git a/docs/html/guide/basics/appmodel.jd b/docs/html/guide/basics/appmodel.jd
deleted file mode 100644
index 323fc9b..0000000
--- a/docs/html/guide/basics/appmodel.jd
+++ /dev/null
@@ -1,261 +0,0 @@
-page.title=Application Model
-@jd:body
-<h1>Android Application Model: Applications, Tasks, Processes, and Threads</h1>
-
-<p>In most operating systems, there is a strong 1-to-1 correlation between
-the executable image (such as the .exe on Windows) that an application lives in,
-the process it runs in, and the icon and application the user interacts with.
-In Android these associations are much more fluid, and it is important to
-understand how the various pieces can be put together.</p>
-
-<p>Because of the flexible nature of Android applications, there is some
-basic terminology that needs to be understood when implementing the
-various pieces of an application:</p>
-
-<ul>
-<li><p>An <strong>android package</strong> (or <strong>.apk</strong> for short)
-is the file containing an application's code and its resources.  This is the
-file that an application is distributed in and downloaded by the user when
-installing that application on their device.</p></li>
-
-<li><p>A <strong>task</strong> is generally what the user perceives as
-an "application" that can be launched: usually a task has an icon in the
-home screen through which it is accessed, and it is available as a top-level
-item that can be brought to the foreground in front of other
-tasks.</p></li>
-
-<li><p>A <strong>process</strong> is a low-level kernel process in which
-an application's code is running.  Normally all of the code in a
-.apk is run in one, dedicated process for that .apk; however, the
-{@link android.R.styleable#AndroidManifestApplication_process process} tag
-can be used to modify where that code is run, either for
-{@link android.R.styleable#AndroidManifestApplication the entire .apk}
-or for individual
-{@link android.R.styleable#AndroidManifestActivity activity},
-{@link android.R.styleable#AndroidManifestReceiver receiver},
-{@link android.R.styleable#AndroidManifestService service}, or
-{@link android.R.styleable#AndroidManifestProvider provider}, components.</p></li>
-</ul>
-
-<h2 id="Tasks">Tasks</h2>
-
-<p>A key point here is: <em>when the user sees as an "application," what
-they are actually dealing with is a task</em>.  If you just create a .apk
-with a number of activities, one of which is a top-level entry point (via
-an {@link android.R.styleable#AndroidManifestIntentFilter intent-filter} for
-the action <code>android.intent.action.MAIN</code> and
-category <code>android.intent.category.LAUNCHER</code>), then there will indeed
-be one task created for your .apk, and any activities you start from there
-will also run as part of that task.</p>
-
-<p>A task, then, from the user's perspective your application; and from the
-application developer's perspective it is one or more activities the user
-has traversed through in that task and not yet closed, or an activity stack.
-A new task is created by
-starting an activity Intent with the {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK
-Intent.FLAG_ACTIVITY_NEW_TASK} flag; this Intent will be used as the root Intent of
-the task, defining what task it is.  Any activity started without this flag
-will run in the same task as the activity that is starting it (unless that
-activity has requested a special launch mode, as discussed later).  Tasks can
-be re-ordered: if you use FLAG_ACTIVITY_NEW_TASK but there is already a task
-running for that Intent, the current task's activity stack will be brought
-to the foreground instead of starting a new task.</p>
-
-<p>FLAG_ACTIVITY_NEW_TASK must only be used with care: using it says that,
-from the user's perspective, a new application starts at this point.  If this
-is not the behavior you desire, you should not be creating a new task.  In
-addition, you should only use the new task flag if it is possible for the user
-to navigate from home back to where they are and launch the same Intent as a
-new task.  Otherwise, if the user presses HOME instead of BACK from the task
-you have launched, your task and its activities will be ordered behind the
-home screen without a way to return to them.</p>
-
-<h3>Task Affinities</h3>
-
-<p>In some cases Android needs to know which task an activity belongs to even when
-it is not being launched in to a specific task.  This is accomplished through
-task affinities, which provide a unique static name for the task that one or more
-activities are intended to run in.  The default task affinity for an activity
-is the name of the .apk package name the activity is implemented in.  This
-provides the normally expected behavior, where all of the activities in a
-particular .apk are part of a single application to the user.</p>
-
-<p>When starting a new activity without the
-{@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK
-Intent.FLAG_ACTIVITY_NEW_TASK} flag, task affinities have no impact on the
-task the new activity will run in: it will always run in the task of the
-activity that is starting it.  However, if the NEW_TASK flag is being used,
-then the affinity will be used to determine if a task already exists with
-the same affinity.  If so, that task will be brought to the front and the
-new activity launched at the top of that task.</p>
-
-<p>This behavior is most useful for situations where you must use the
-NEW_TASK flag, in particular launching activities from status bar notifications
-or home screen shortcuts.  The result is that, when the user launches your
-application this way, its current task state will be brought to the foreground,
-and the activity they now want to look at placed on top of it.</p>
-
-<p>You can assign your own task affinities in your manifest's
-{@link android.R.styleable#AndroidManifestApplication application} tag for
-all activities in the .apk, or the
-{@link android.R.styleable#AndroidManifestActivity activity} tag of
-individual activities.  Some examples of how this can be used are:</p>
-
-<ul>
-<li>If your .apk contains multiple top-level applications that the user can
-launch, then you will probably want to assign different affinities to each
-of the activities that the users sees for your .apk.  A good convention for
-coming up with distinct names is to append your .apk's package name with
-a colon separated string.  For example, the "com.android.contacts" .apk
-may have the affinities "com.android.contacts:Dialer" and
-"com.android.contacts:ContactsList".</ul>
-<li>If you are replacing a notification, shortcut, or other such "inner"
-activity of an application that can be launched from outside of it, you may
-need to explicitly set the taskAffinity of your replacement activity to be
-the same as the application you are replacing.  For example, if you are
-replacing the contacts details view (which the user can make and invoke
-shortcuts to), you would want to set the taskAffinity to
-"com.android.contacts".</li>
-</ul>
-
-<h3>Launch Modes and Launch Flags</h3>
-
-<p>The main way you control how activities interact with tasks is through
-the activity's
-{@link android.R.styleable#AndroidManifestActivity_launchMode launchMode}
-attribute and the {@link android.content.Intent#setFlags flags} associated
-with an Intent.  These two parameters can work together in various ways
-to control the outcome of the activity launch, as described in their
-associated documentation.  Here we will look at some common use cases and
-combinations of these parameters.</p>
-
-<p>The most common launch mode you will use (besides the default
-<code>standard</code> mode) is <code>singleTop</code>.  This does not have
-an impact on tasks; it just avoids starting the same activity multiple times
-on the top of a stack.
-
-<p>The <code>singleTask</code> launch mode has a major
-impact on tasks: it causes the activity to always be started in
-a new task (or its existing task to be brought to the foreground).  Using
-this mode requires a lot of care in how you interact with the rest of the
-system, as it impacts every path in to the activity.  It should only be used
-with activities that are front doors to the application (that is, which
-support the MAIN action and LAUNCHER category).</p>
-
-<p>The <code>singleInstance</code> launch mode is even more specialized, and
-should only be used in applications that are implemented entirely as one
-activity.</p>
-
-<p>A situation you will often run in to is when another entity (such as the
-{@link android.app.SearchManager} or {@link android.app.NotificationManager})
-starts one of your activities.  In this case, the
-{@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK
-Intent.FLAG_ACTIVITY_NEW_TASK} flag must be used, because the activity is
-being started outside of a task (and the application/task may not even
-exist).  As described previously, the standard behavior in this situation
-is to bring to the foreground the current task matching the new activity's
-affinity and start the new activity at the top of it.  There are, however,
-other types of behavior that you can implement.</p>
-
-<p>One common approach is to also use the
-{@link android.content.Intent#FLAG_ACTIVITY_CLEAR_TOP
-Intent.FLAG_ACTIVITY_CLEAR_TOP} flag in conjunction with NEW_TASK.  By doing so,
-if your task is already running, then it will be brought to the foreground,
-all of the activities on its stack cleared except the root activity, and the
-root activity's {@link android.app.Activity#onNewIntent} called with the
-Intent being started.  Note that the activity often also use the <code>singleTop</code>
-or <code>singleTask</code> launch mode when using this approach, so that
-the current instance is given the new intent instead of requiring that it
-be destroyed and a new instance started.</p>
-
-<p>Another approach you can take is to set the notification activity's
-<code>android:taskAffinity</code> to the empty string "" (indicating no affinity)
-and setting the
-<code>{@link android.R.styleable#AndroidManifestActivity_noHistory
-android:noHistory}</code> and
-<code>{@link android.R.styleable#AndroidManifestActivity_excludeFromRecents
-android:excludeFromRecents}</code> attributes.
-This approach is useful if you would like the notification
-to take the user to a separate activity describing it, rather than return
-to the application's task.  By specifying these attributes, the activity will
-be finished whether the user leaves it with BACK or HOME and it will not
-show up in the recent tasks list; if the <code>noHistory</code> attribute
-isn't specified, pressing HOME will result in the activity and its task
-remaining in the system, possibly with no way to return to it.</p>
-
-<p>Be sure to read the documentation on the
-{@link android.R.styleable#AndroidManifestActivity_launchMode launchMode attribute}
-and the {@link android.content.Intent#setFlags Intent flags} for the details
-on these options.</p>
-
-<h2 id="Processes">Processes</h2>
-
-<p>In Android, processes are entirely an implementation detail of applications
-and not something the user is normally aware of.  Their main uses are simply:</p>
-
-<ul>
-<li> Improving stability or security by putting untrusted or unstable code
-into another process.
-<li> Reducing overhead by running the code of multiple .apks in the same
-process.
-<li> Helping the system manage resources by putting heavy-weight code in
-a separate process that can be killed independently of other parts of the
-application.
-</ul>
-
-<p>As described previously, the
-{@link android.R.styleable#AndroidManifestApplication_process process} attribute
-is used to control the process that particular application components run in.
-Note that this attribute can not be used to violate security of the system: if
-two .apks that are not sharing the same user ID try to run in the same process,
-this will not be allowed and different distinct processes will be created for
-each of them.</p>
-
-<p>See the <a href="{@docRoot}devel/security.html">security</a> document for
-more information on these security restrictions.</p>
-
-<h2 id="Threads">Threads</h2>
-
-<p>Every process has one or more threads running in it.  In most situations, Android
-avoids creating additional threads in a process, keeping an application
-single-threaded unless it creates its own threads.  An important repercussion
-of this is that all calls to {@link android.app.Activity},
-{@link android.content.BroadcastReceiver}, and {@link android.app.Service}
-instances are made only from the main thread of the process they are running in.</p>
-
-<p>Note that a new thread is <strong>not</strong> created for each
-Activity, BroadcastReceiver, Service, or ContentProvider instance:
-these application components are instantiated in the desired process (all in the
-same process unless otherwise specified), in the main thread of that process.
-This means that none of these components (including services) should perform
-long or blocking operations (such as networking calls or computation loops)
-when called by the system, since this will block
-all other components in the process.  You can use the standard library
-{@link java.lang.Thread} class or Android's {@link android.os.HandlerThread}
-convenience class to perform long operations on another thread.</p>
-
-<p>There are a few important exceptions to this threading rule:</p>
-
-<ul>
-<li><p>Calls on to an {@link android.os.IBinder} or interface implemented on
-an IBinder are dispatched from the thread calling them or a thread pool in the
-local process if coming from another process, <em>not</em>
-from the main thread of their process.  In particular, calls on to the IBinder
-of a {@link android.app.Service} will be called this way.  (Though
-calls to methods on Service itself are done from the main thread.)
-This means that <em>implementations of IBinder interfaces must always be
-written in a thread-safe way, since they can be called from any number of
-arbitrary threads at the same time</em>.</p></li>
-
-<li><p>Calls to the main methods of {@link android.content.ContentProvider}
-are dispatched from the calling thread or main thread as with IBinder.  The
-specific methods are documented in the ContentProvider class.
-This means that <em>implementations of these methods must always be
-written in a thread-safe way, since they can be called from any number of
-arbitrary threads at the same time</em>.</p></li>
-
-<li><p>Calls on {@link android.view.View} and its subclasses are made from the
-thread that the view's window is running in.  Normally this will be the main
-thread of the process, however if you create a thread and show a window from
-there then the window's view hierarchy will be called from that thread.</p></li>
-</ul>
diff --git a/docs/html/guide/basics/building-blocks.jd b/docs/html/guide/basics/building-blocks.jd
deleted file mode 100644
index b8a609e..0000000
--- a/docs/html/guide/basics/building-blocks.jd
+++ /dev/null
@@ -1,76 +0,0 @@
-page.title=Building Blocks
-@jd:body
-<h1>Android Building Blocks</h1>
-
-<p>You can think of an Android application as a collection of components, of
-various kinds. These components are for the most part quite loosely coupled,
-to the degree where you can accurately describe them as a federation of
-components rather than a single cohesive application.</p>
-
-<p>Generally, these components all run in the same system process. It's
-possible (and quite common) to create multiple threads within that process,
-and it's also possible to create completely separate child processes if you
-need to. Such cases are pretty uncommon though, because Android tries very
-hard to make processes transparent to your code.</p>
-
-<p>These are the most important parts of the Android APIs:</p>
-
-<dl>
-    <dt><a href="{@docRoot}devel/bblocks-manifest.html">AndroidManifest.xml</a></dt>
-    <dd>The AndroidManifest.xml file is the control file that tells the system
-    what to do with all the top-level components (specifically activities,
-    services, intent receivers, and content providers described below)
-    you've created.  For instance, this is the
-    "glue" that actually specifies which Intents your Activities receive.</dd>
-    
-    <dt>{@link android.app.Activity Activities}</dt>
-    <dd>An Activity is, fundamentally, an object that has a life cycle. An
-    Activity is a chunk of code that does some work; if necessary, that work
-    can include displaying a UI to the user. It doesn't have to, though - some
-    Activities never display UIs. Typically, you'll designate one of your
-    application's Activities as the entry point to your application. </dd>
-  
-  
-    <dt>{@link android.view.View Views}</dt>
-    <dd>A View is an object that knows how to draw itself to the screen.
-    Android user interfaces are comprised of trees of Views. If you want to
-    perform some custom graphical technique (as you might if you're writing a
-    game, or building some unusual new user interface widget) then you'd
-    create a View.</dd>
-  
-  
-    <dt>{@link android.content.Intent Intents}</dt>
-    <dd>An Intent is a simple message object that represents an "intention" to
-    do something. For example, if your application wants to display a web
-    page, it expresses its "Intent" to view the URI by creating an Intent
-    instance and handing it off to the system. The system locates some other
-    piece of code (in this case, the Browser) that knows how to handle that
-    Intent, and runs it. Intents can also be used to broadcast interesting
-    events (such as a notification) system-wide.</dd>
-  
-  
-    <dt>{@link android.app.Service Services}</dt>
-    <dd>A Service is a body of code that runs in the background. It can run in
-    its own process, or in the context of another application's process,
-    depending on its needs. Other components "bind" to a Service and invoke
-    methods on it via remote procedure calls. An example of a Service is a
-    media player; even when the user quits the media-selection UI, she
-    probably still intends for her music to keep playing. A Service keeps the
-    music going even when the UI has completed.</dd>
-  
-  
-    <dt>{@link android.app.NotificationManager Notifications}</dt>
-    <dd>A Notification is a small icon that appears in the status bar. Users
-    can interact with this icon to receive information. The most well-known
-    notifications are SMS messages, call history, and voicemail, but
-    applications can create their own. Notifications are the
-    strongly-preferred mechanism for alerting the user of something that needs
-    their attention.</dd>
-    
-    <dt>{@link android.content.ContentProvider ContentProviders}</dt>
-    <dd>A ContentProvider is a data storehouse that provides access to data on
-    the device; the classic example is the ContentProvider that's used to
-    access the user's list of contacts. Your application can access data that
-    other applications have exposed via a ContentProvider, and you can also
-    define your own ContentProviders to expose data of your own.</dd>
-</dl>
diff --git a/docs/html/guide/basics/fixme-gs-core-packages.jd b/docs/html/guide/basics/fixme-gs-core-packages.jd
deleted file mode 100644
index 5281990..0000000
--- a/docs/html/guide/basics/fixme-gs-core-packages.jd
+++ /dev/null
@@ -1,92 +0,0 @@
-page.title=Getting Started
-@jd:body
-<h1>Getting Started with Android</h1>
- 
-<p>To get started with Android, please read the following sections first:</p>
-<dl>
-    <dt><a href="{@docRoot}intro/installing.html">Installing the SDK and
-    Plugin</a></dt>
-    <dd>How to install the Android SDK and Eclipse plugin.</dd>
-    <dt><a href="{@docRoot}intro/develop-and-debug.html">Developing and Debugging</a></dt>
-    <dd>An introduction to developing and debugging Android applications in Eclipse,
-    plus information on using other IDEs.</dd>
-    <dt><a href="{@docRoot}intro/hello-android.html">Hello Android</a></dt>
-    <dd>Writing your first Android Application, the ever popular Hello World,
-    Android style.</dd>
-    <dt><a href="{@docRoot}intro/anatomy.html">Anatomy of an App</a></dt>
-    <dd>A guide to the structure and architecture of an Android
-    Application. This guide will help you understand the pieces that make up
-    an Android app.</dd>
-    <dt><a href="{@docRoot}intro/tutorial.html">Notepad Tutorial</a></dt>
-    <dd>This tutorial document will lead you through
-    constructing a real Android Application: A notepad which can create, edit
-    and delete notes, and covers many of the basic concepts with practical
-    examples.</dd>
-    <dt><a href="{@docRoot}intro/tools.html">Development Tools</a></dt>
-    <dd>The
-    command line tools included with the SDK, what they do, and how to use
-    them.</dd>
-    <dt><a href="{@docRoot}intro/appmodel.html">Application Model</a></dt>
-    <dd>A guide to Applications, Tasks, Processes, and Threads.
-    These are the elements that define the way your application is run by the 
-    system and presented to the user.</dd>
-    <dt><a href="{@docRoot}intro/lifecycle.html">Application Life Cycle</a></dt>
-    <dd>The important life-cycle details for
-    Applications and the Activities running inside of them.</dd>
-
-</dl>
-
-<h2>Other Introductory Material</h2>
-<p>After reading the sections above, the following Getting Started information is also very useful:</p>
-
-
-<h3>Core Packages</h3>
-<p> These are the basic packages that make up the Android SDK for writing
-applications. The packages are organized as layers, listed here from
-lowest-level to highest.</p>
-
-<dl>
-    <dt>{@link android.util}</dt>
-    <dd>contains various low-level utility classes, such
-    as specialized container classes, XML utilities, etc.</dd>
-    <dt>{@link android.os}</dt>
-    <dd> provides basic operating system services, message
-    passing, and inter-process communication.</dd>
-    <dt>{@link android.graphics}</dt><dd>is the core rendering package.</dd>
-    <dt>{@link android.text}, {@link android.text.method}, {@link
-    android.text.style}, and {@link android.text.util} </dt>
-    <dd>supply a rich set of
-    text processing tools, supporting rich text, input methods, etc.</dd>
-    <dt>{@link android.database}</dt>
-    <dd>contains low-level APIs for working with
-    databases.</dd>
-    <dt>{@link android.content}</dt>
-    <dd>provides various services for accessing data
-    on the device: applications installed on the device and their associated
-    resources, and content providers for persistent dynamic data.</dd>
-    <dt>{@link android.view}</dt>
-    <dd>is the core user-interface framework.</dd>
-    <dt>{@link android.widget}</dt>
-    <dd>supplies standard user interface elements
-    (lists, buttons, layout managers, etc) built from the view package.</dd>
-    <dt>{@link android.app}</dt>
-    <dd>provides the high-level application model,
-    implemented using Activities.</dd>
-</dl>
-
-<h3>Other Notable Packages</h3>
-
-<p> These packages provide additional domain-specific features of the Android
-platform. They are not necessary for basic application development.</p>
-
-<dl>
-    <dt>{@link android.provider}</dt>
-    <dd>contains definitions for various standard
-    content providers included with the platform.</dd>
-    <dt>{@link android.telephony}</dt>
-    <dd>provides APIs for interacting with the
-    device's phone stack.</dd>
-    <dt>{@link android.webkit}</dt>
-    <dd>includes various APIs for working with
-    web-based content.</dd>
-</dl>
diff --git a/docs/html/guide/basics/index.html b/docs/html/guide/basics/index.html
deleted file mode 100644
index 4881acf..0000000
--- a/docs/html/guide/basics/index.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<html>
-<head>
-<meta http-equiv="refresh" content="0;url=../index.html">
-</head>
-<body>
-<a href="../index.html">click here</a> if you are not redirected.
-</body>
-</html>
\ No newline at end of file
diff --git a/docs/html/guide/components/activities.jd b/docs/html/guide/components/activities.jd
index 2897804..1cbaa79 100644
--- a/docs/html/guide/components/activities.jd
+++ b/docs/html/guide/components/activities.jd
@@ -1,4 +1,5 @@
 page.title=Activities
+page.tags="activity","intent"
 @jd:body
 
 <div id="qv-wrapper">
diff --git a/docs/html/guide/components/fragments.jd b/docs/html/guide/components/fragments.jd
index 7747b31..32c9f99 100644
--- a/docs/html/guide/components/fragments.jd
+++ b/docs/html/guide/components/fragments.jd
@@ -172,7 +172,7 @@
 
 <p>Most applications should implement at least these three methods for every fragment, but there are
 several other callback methods you should also use to handle various stages of the
-fragment lifecycle. All the lifecycle callback methods are discussed more later, in the section
+fragment lifecycle. All the lifecycle callback methods are discussed in more detail in the section
 about <a href="#Lifecycle">Handling the Fragment Lifecycle</a>.</p>
 
 
diff --git a/docs/html/guide/components/fundamentals.jd b/docs/html/guide/components/fundamentals.jd
index 2c33a26..ce50022 100644
--- a/docs/html/guide/components/fundamentals.jd
+++ b/docs/html/guide/components/fundamentals.jd
@@ -345,7 +345,7 @@
 {@link android.content.BroadcastReceiver} objects) and registered with the system by calling
 {@link android.content.Context#registerReceiver registerReceiver()}.</p>
 
-<p>For more about how to structure the manifest file for your application, see the <a
+<p>For more about how to structure the manifest file for your application, see <a
 href="{@docRoot}guide/topics/manifest/manifest-intro.html">The AndroidManifest.xml File</a>
 documentation. </p>
 
diff --git a/docs/html/guide/components/processes-and-threads.jd b/docs/html/guide/components/processes-and-threads.jd
index 07a2667..1fed712c 100644
--- a/docs/html/guide/components/processes-and-threads.jd
+++ b/docs/html/guide/components/processes-and-threads.jd
@@ -1,4 +1,6 @@
 page.title=Processes and Threads
+page.tags="lifecycle","background"
+
 @jd:body
 
 <div id="qv-wrapper">
diff --git a/docs/html/guide/components/tasks-and-back-stack.jd b/docs/html/guide/components/tasks-and-back-stack.jd
index ecaba8d..a21bf34 100644
--- a/docs/html/guide/components/tasks-and-back-stack.jd
+++ b/docs/html/guide/components/tasks-and-back-stack.jd
@@ -231,7 +231,7 @@
 &lt;activity&gt;}</a> manifest element and with flags in the intent that you pass to {@link
 android.app.Activity#startActivity startActivity()}.</p>
 
-<p>In this regard, the the principal <a
+<p>In this regard, the principal <a
 href="{@docRoot}guide/topics/manifest/activity-element.html">{@code &lt;activity&gt;}</a>
 attributes you can use are:</p>
 
@@ -319,7 +319,7 @@
 routes the intent to that instance through a call to its {@link
 android.app.Activity#onNewIntent onNewIntent()} method, rather than creating a new instance of the
 activity. The activity can be instantiated multiple times, each instance can
-belong to different tasks, and one task can have multiple instances (but only if the the
+belong to different tasks, and one task can have multiple instances (but only if the
 activity at the top of the back stack is <em>not</em> an existing instance of the activity).
   <p>For example, suppose a task's back stack consists of root activity A with activities B, C,
 and D on top (the stack is A-B-C-D; D is on top). An intent arrives for an activity of type D.
diff --git a/docs/html/guide/practices/compatibility.jd b/docs/html/guide/practices/compatibility.jd
index bc58403..9e3d461 100644
--- a/docs/html/guide/practices/compatibility.jd
+++ b/docs/html/guide/practices/compatibility.jd
@@ -1,4 +1,5 @@
 page.title=Android Compatibility
+excludeFromSuggestions=true
 @jd:body
 
 <div id="qv-wrapper">
diff --git a/docs/html/guide/practices/index.jd b/docs/html/guide/practices/index.jd
index 04a43c5..b61272b 100644
--- a/docs/html/guide/practices/index.jd
+++ b/docs/html/guide/practices/index.jd
@@ -1,4 +1,5 @@
 page.title=Best Practices
+excludeFromSuggestions=true
 page.landing=true
 page.landing.intro=Design and build apps the right way. Learn how to create apps that look great and perform well on as many devices as possible, from phones to tablets and more.  
 page.landing.image=
@@ -19,7 +20,7 @@
     
     <a href="http://android-developers.blogspot.com/2012/01/say-goodbye-to-menu-button.html">
       <h4>Say Goodbye to the Menu Button</h4>
-      <p>As Ice Cream Sandwich rolls out to more devices, it?s important that you begin to migrate
+      <p>As Ice Cream Sandwich rolls out to more devices, it's important that you begin to migrate
 your designs to the action bar in order to promote a consistent Android user experience.</p>
     </a>
     
@@ -49,4 +50,4 @@
   </div>
 
 
-</div>
\ No newline at end of file
+</div>
diff --git a/docs/html/guide/practices/optimizing-for-3.0.jd b/docs/html/guide/practices/optimizing-for-3.0.jd
index 0dd92d9..465a847 100644
--- a/docs/html/guide/practices/optimizing-for-3.0.jd
+++ b/docs/html/guide/practices/optimizing-for-3.0.jd
@@ -1,4 +1,5 @@
 page.title=Optimizing Apps for Android 3.0
+excludeFromSuggestions=true
 @jd:body
 
 
diff --git a/docs/html/guide/practices/screen-compat-mode.jd b/docs/html/guide/practices/screen-compat-mode.jd
index 7f10914..e3160c39 100644
--- a/docs/html/guide/practices/screen-compat-mode.jd
+++ b/docs/html/guide/practices/screen-compat-mode.jd
@@ -1,4 +1,5 @@
 page.title=Screen Compatibility Mode
+excludeFromSuggestions=true
 parent.title=Supporting Multiple Screens
 parent.link=screens_support.html
 
diff --git a/docs/html/guide/practices/screens-distribution.jd b/docs/html/guide/practices/screens-distribution.jd
index 29d2a8c..99eb04e 100644
--- a/docs/html/guide/practices/screens-distribution.jd
+++ b/docs/html/guide/practices/screens-distribution.jd
@@ -1,4 +1,5 @@
 page.title=Distributing to Specific Screens
+excludeFromSuggestions=true
 parent.title=Supporting Multiple Screens
 parent.link=screens_support.html
 
diff --git a/docs/html/guide/practices/screens-support-1.5.jd b/docs/html/guide/practices/screens-support-1.5.jd
index 15f0695..ad680d9 100644
--- a/docs/html/guide/practices/screens-support-1.5.jd
+++ b/docs/html/guide/practices/screens-support-1.5.jd
@@ -1,4 +1,5 @@
 page.title=Strategies for Android 1.5
+excludeFromSuggestions=true
 parent.title=Supporting Multiple Screens
 parent.link=screens_support.html
 
diff --git a/docs/html/guide/practices/seamlessness.jd b/docs/html/guide/practices/seamlessness.jd
index ec6b7fd..9679e2a 100644
--- a/docs/html/guide/practices/seamlessness.jd
+++ b/docs/html/guide/practices/seamlessness.jd
@@ -1,4 +1,5 @@
 page.title=Designing for Seamlessness
+excludeFromSuggestions=true
 @jd:body
 
 <div id="qv-wrapper">
diff --git a/docs/html/guide/practices/ui_guidelines/activity_task_design.jd b/docs/html/guide/practices/ui_guidelines/activity_task_design.jd
index cb2bc37..f6669e4 100644
--- a/docs/html/guide/practices/ui_guidelines/activity_task_design.jd
+++ b/docs/html/guide/practices/ui_guidelines/activity_task_design.jd
@@ -1,4 +1,5 @@
 page.title=Activity and Task Design Guidelines
+excludeFromSuggestions=true
 parent.title=UI Guidelines
 parent.link=index.html
 @jd:body
diff --git a/docs/html/guide/practices/ui_guidelines/icon_design.jd b/docs/html/guide/practices/ui_guidelines/icon_design.jd
index 70ae862..0726660 100644
--- a/docs/html/guide/practices/ui_guidelines/icon_design.jd
+++ b/docs/html/guide/practices/ui_guidelines/icon_design.jd
@@ -1,4 +1,5 @@
 page.title=Icon Design Guidelines
+excludeFromSuggestions=true
 parent.title=UI Guidelines
 parent.link=index.html
 @jd:body
diff --git a/docs/html/guide/practices/ui_guidelines/icon_design_action_bar.jd b/docs/html/guide/practices/ui_guidelines/icon_design_action_bar.jd
index 9f835a7..831de45 100644
--- a/docs/html/guide/practices/ui_guidelines/icon_design_action_bar.jd
+++ b/docs/html/guide/practices/ui_guidelines/icon_design_action_bar.jd
@@ -1,4 +1,5 @@
 page.title=Action Bar Icons
+excludeFromSuggestions=true
 parent.title=Icon Design Guidelines
 parent.link=icon_design.html
 @jd:body
diff --git a/docs/html/guide/practices/ui_guidelines/icon_design_dialog.jd b/docs/html/guide/practices/ui_guidelines/icon_design_dialog.jd
index a2c1459..c958ed9 100644
--- a/docs/html/guide/practices/ui_guidelines/icon_design_dialog.jd
+++ b/docs/html/guide/practices/ui_guidelines/icon_design_dialog.jd
@@ -1,4 +1,5 @@
 page.title=Dialog Icons
+excludeFromSuggestions=true
 parent.title=Icon Design Guidelines
 parent.link=icon_design.html
 @jd:body
diff --git a/docs/html/guide/practices/ui_guidelines/icon_design_launcher.jd b/docs/html/guide/practices/ui_guidelines/icon_design_launcher.jd
index 4ec56b1..f47e186 100644
--- a/docs/html/guide/practices/ui_guidelines/icon_design_launcher.jd
+++ b/docs/html/guide/practices/ui_guidelines/icon_design_launcher.jd
@@ -1,4 +1,5 @@
 page.title=Launcher Icons
+excludeFromSuggestions=true
 parent.title=Icon Design Guidelines
 parent.link=icon_design.html
 @jd:body
diff --git a/docs/html/guide/practices/ui_guidelines/icon_design_launcher_archive.jd b/docs/html/guide/practices/ui_guidelines/icon_design_launcher_archive.jd
index 4529797..2df3a22 100644
--- a/docs/html/guide/practices/ui_guidelines/icon_design_launcher_archive.jd
+++ b/docs/html/guide/practices/ui_guidelines/icon_design_launcher_archive.jd
@@ -1,4 +1,5 @@
 page.title=Launcher Icons (Archive)
+excludeFromSuggestions=true
 parent.title=Icon Design Guidelines
 parent.link=icon_design.html
 @jd:body
diff --git a/docs/html/guide/practices/ui_guidelines/icon_design_list.jd b/docs/html/guide/practices/ui_guidelines/icon_design_list.jd
index 38ceb85..29e1a93 100644
--- a/docs/html/guide/practices/ui_guidelines/icon_design_list.jd
+++ b/docs/html/guide/practices/ui_guidelines/icon_design_list.jd
@@ -1,4 +1,5 @@
 page.title=List View Icons
+excludeFromSuggestions=true
 parent.title=Icon Design Guidelines
 parent.link=icon_design.html
 @jd:body
diff --git a/docs/html/guide/practices/ui_guidelines/icon_design_menu.jd b/docs/html/guide/practices/ui_guidelines/icon_design_menu.jd
index 24bce51..a5b3597 100644
--- a/docs/html/guide/practices/ui_guidelines/icon_design_menu.jd
+++ b/docs/html/guide/practices/ui_guidelines/icon_design_menu.jd
@@ -1,4 +1,5 @@
 page.title=Menu Icons
+excludeFromSuggestions=true
 parent.title=Icon Design Guidelines
 parent.link=icon_design.html
 @jd:body
diff --git a/docs/html/guide/practices/ui_guidelines/icon_design_status_bar.jd b/docs/html/guide/practices/ui_guidelines/icon_design_status_bar.jd
index 4cd4db3..4993adb 100644
--- a/docs/html/guide/practices/ui_guidelines/icon_design_status_bar.jd
+++ b/docs/html/guide/practices/ui_guidelines/icon_design_status_bar.jd
@@ -1,4 +1,5 @@
 page.title=Status Bar Icons
+excludeFromSuggestions=true
 parent.title=Icon Design Guidelines
 parent.link=icon_design.html
 @jd:body
diff --git a/docs/html/guide/practices/ui_guidelines/icon_design_tab.jd b/docs/html/guide/practices/ui_guidelines/icon_design_tab.jd
index 5338a4d..cbe6706 100644
--- a/docs/html/guide/practices/ui_guidelines/icon_design_tab.jd
+++ b/docs/html/guide/practices/ui_guidelines/icon_design_tab.jd
@@ -1,4 +1,5 @@
 page.title=Tab Icons
+excludeFromSuggestions=true
 parent.title=Icon Design Guidelines
 parent.link=icon_design.html
 @jd:body
diff --git a/docs/html/guide/practices/ui_guidelines/index.jd b/docs/html/guide/practices/ui_guidelines/index.jd
index 7603f6b..91a0725 100644
--- a/docs/html/guide/practices/ui_guidelines/index.jd
+++ b/docs/html/guide/practices/ui_guidelines/index.jd
@@ -1,4 +1,5 @@
 page.title=User Interface Guidelines
+excludeFromSuggestions=true
 @jd:body
 
 
diff --git a/docs/html/guide/practices/ui_guidelines/menu_design.jd b/docs/html/guide/practices/ui_guidelines/menu_design.jd
index b4e2ea7..bf87bdd 100644
--- a/docs/html/guide/practices/ui_guidelines/menu_design.jd
+++ b/docs/html/guide/practices/ui_guidelines/menu_design.jd
@@ -1,4 +1,5 @@
 page.title=Menu Design Guidelines
+excludeFromSuggestions=true
 parent.title=UI Guidelines
 parent.link=index.html
 @jd:body
diff --git a/docs/html/guide/practices/ui_guidelines/widget_design.jd b/docs/html/guide/practices/ui_guidelines/widget_design.jd
index a48d17d..cf2cd64 100644
--- a/docs/html/guide/practices/ui_guidelines/widget_design.jd
+++ b/docs/html/guide/practices/ui_guidelines/widget_design.jd
@@ -1,4 +1,5 @@
 page.title=App Widget Design Guidelines
+excludeFromSuggestions=true
 parent.title=UI Guidelines
 parent.link=index.html
 @jd:body
diff --git a/docs/html/guide/topics/admin/device-admin.jd b/docs/html/guide/topics/admin/device-admin.jd
index 4a325db..a474498 100644
--- a/docs/html/guide/topics/admin/device-admin.jd
+++ b/docs/html/guide/topics/admin/device-admin.jd
@@ -1,4 +1,5 @@
 page.title=Device Administration
+page.tags="devicepolicymanager","policy","security"
 @jd:body
 
 <div id="qv-wrapper">
@@ -339,7 +340,7 @@
 </code> is a permission that a {@link android.app.admin.DeviceAdminReceiver} subclass must
 have, to ensure that only the system can interact with the receiver (no application can be granted this permission). This
 prevents other applications from abusing your device admin app.</li>
-<li><code>android.app.action.DEVICE_ADMIN_ENABLED</code> is the  the primary
+<li><code>android.app.action.DEVICE_ADMIN_ENABLED</code> is the primary
 action that a {@link android.app.admin.DeviceAdminReceiver} subclass must handle to be
 allowed to manage a device. This is set to the receiver when the user enables
 the device admin app. Your code typically handles this in
diff --git a/docs/html/guide/topics/admin/keychain.jd b/docs/html/guide/topics/admin/keychain.jd
deleted file mode 100644
index 2ea2408..0000000
--- a/docs/html/guide/topics/admin/keychain.jd
+++ /dev/null
@@ -1,4 +0,0 @@
-page.title=Text and Input
-@jd:body
-
-<p>Add contnet here</p>
diff --git a/docs/html/guide/topics/appwidgets/index.jd b/docs/html/guide/topics/appwidgets/index.jd
index 6e6fa28..cdbf827 100644
--- a/docs/html/guide/topics/appwidgets/index.jd
+++ b/docs/html/guide/topics/appwidgets/index.jd
@@ -1,4 +1,5 @@
 page.title=App Widgets
+page.tags="home"
 @jd:body
 
 <div id="qv-wrapper">
@@ -1119,7 +1120,7 @@
 active, the system accesses these objects using their index position in the
 array and the text they contain is displayed  </p>
 
-<p>Here is an excerpt from the the <a
+<p>Here is an excerpt from the <a
 href="{@docRoot}resources/samples/StackWidget/index.html">StackView Widget</a>
 sample's 
 {@link android.widget.RemoteViewsService.RemoteViewsFactory
diff --git a/docs/html/guide/topics/connectivity/bluetooth.jd b/docs/html/guide/topics/connectivity/bluetooth.jd
index 832b850..1c55d8b 100644
--- a/docs/html/guide/topics/connectivity/bluetooth.jd
+++ b/docs/html/guide/topics/connectivity/bluetooth.jd
@@ -1,4 +1,5 @@
 page.title=Bluetooth
+page.tags="wireless","bluetoothadapter","bluetoothdevice"
 @jd:body
 
 <div id="qv-wrapper"> 
diff --git a/docs/html/guide/topics/connectivity/sip.jd b/docs/html/guide/topics/connectivity/sip.jd
index a5f0e2e..526eb83 100644
--- a/docs/html/guide/topics/connectivity/sip.jd
+++ b/docs/html/guide/topics/connectivity/sip.jd
@@ -1,4 +1,5 @@
 page.title=Session Initiation Protocol
+page.tags="sipmanager","sipprofile","sipaudiocall","telephony"
 @jd:body
 <div id="qv-wrapper">
 <div id="qv">
diff --git a/docs/html/guide/topics/connectivity/wifip2p.jd b/docs/html/guide/topics/connectivity/wifip2p.jd
index bbf30fd..2167a0f 100644
--- a/docs/html/guide/topics/connectivity/wifip2p.jd
+++ b/docs/html/guide/topics/connectivity/wifip2p.jd
@@ -1,4 +1,5 @@
 page.title=Wi-Fi Direct
+page.tags="wireless","WifiP2pManager"
 
 @jd:body
 
@@ -433,7 +434,7 @@
 
   <p>The {@link android.net.wifi.p2p.WifiP2pManager#requestPeers requestPeers()} method is also
   asynchronous and can notify your activity when a list of peers is available with {@link
-  android.net.wifi.p2p.WifiP2pManager.PeerListListener#onPeersAvailable onPeersAvailable()}, which is defined in the
+  android.net.wifi.p2p.WifiP2pManager.PeerListListener#onPeersAvailable onPeersAvailable()}, which is defined in
   the {@link android.net.wifi.p2p.WifiP2pManager.PeerListListener} interface. The {@link
   android.net.wifi.p2p.WifiP2pManager.PeerListListener#onPeersAvailable onPeersAvailable()} method
   provides you with an {@link android.net.wifi.p2p.WifiP2pDeviceList}, which you can iterate
diff --git a/docs/html/guide/topics/data/data-storage.jd b/docs/html/guide/topics/data/data-storage.jd
index 2603a06..385c116 100644
--- a/docs/html/guide/topics/data/data-storage.jd
+++ b/docs/html/guide/topics/data/data-storage.jd
@@ -1,4 +1,5 @@
 page.title=Storage Options
+page.tags="database","sharedpreferences","sdcard"
 @jd:body
 
 
diff --git a/docs/html/guide/topics/data/install-location.jd b/docs/html/guide/topics/data/install-location.jd
index 757cd19..2ec0d5a 100644
--- a/docs/html/guide/topics/data/install-location.jd
+++ b/docs/html/guide/topics/data/install-location.jd
@@ -1,4 +1,5 @@
 page.title=App Install Location
+page.tags="sdcard","external"
 @jd:body
 
 
diff --git a/docs/html/guide/topics/graphics/opengl.jd b/docs/html/guide/topics/graphics/opengl.jd
index 6114a4a..469eae2 100644
--- a/docs/html/guide/topics/graphics/opengl.jd
+++ b/docs/html/guide/topics/graphics/opengl.jd
@@ -1,6 +1,5 @@
 page.title=OpenGL
-parent.title=Graphics
-parent.link=index.html
+page.tags="games"
 @jd:body
 
 <div id="qv-wrapper">
@@ -138,7 +137,7 @@
             <li>{@link android.opengl.GLES10}</li>
             <li>{@link android.opengl.GLES10Ext}</li>
             <li>{@link android.opengl.GLES11}</li>
-            <li>{@link android.opengl.GLES10Ext}</li>
+            <li>{@link android.opengl.GLES11Ext}</li>
           </ul>
         </li>
       <li>{@link javax.microedition.khronos.opengles} - This package provides the standard
@@ -289,13 +288,14 @@
     private final String vertexShaderCode =
 
         // This matrix member variable provides a hook to manipulate
-        // the coordinates of objects that use this vertex shader
+        // the coordinates of objects that use this vertex shader.
         "uniform mat4 uMVPMatrix;   \n" +
 
         "attribute vec4 vPosition;  \n" +
         "void main(){               \n" +
-
-        // the matrix must be included as part of gl_Position
+        // The matrix must be included as part of gl_Position
+        // Note that the uMVPMatrix factor *must be first* in order
+        // for the matrix multiplication product to be correct.
         " gl_Position = uMVPMatrix * vPosition; \n" +
 
         "}  \n";
@@ -444,7 +444,7 @@
 
 <p>Beyond the ETC1 format, Android devices have varied support for texture compression based on
 their GPU chipsets and OpenGL implementations. You should investigate texture compression support on
-the the devices you are are targeting to determine what compression types your application should
+the devices you are are targeting to determine what compression types your application should
 support. In order to determine what texture formats are supported on a given device, you must <a
 href="#gl-extension-query">query the device</a> and review the <em>OpenGL extension names</em>,
 which identify what texture compression formats (and other OpenGL features) are supported by the
diff --git a/docs/html/guide/topics/graphics/prop-animation.jd b/docs/html/guide/topics/graphics/prop-animation.jd
index b733624..22bf7696 100644
--- a/docs/html/guide/topics/graphics/prop-animation.jd
+++ b/docs/html/guide/topics/graphics/prop-animation.jd
@@ -1,6 +1,5 @@
 page.title=Property Animation
-parent.title=Animation
-parent.link=animation.html
+page.tags="valueanimator","objectanimator","layouttransition","ViewPropertyAnimator"
 @jd:body
 
   <div id="qv-wrapper">
@@ -479,7 +478,7 @@
     </li>
 
     <li>Depending on what property or object you are animating, you might need to call the {@link
-    android.view.View#invalidate invalidate()} method on a View force the screen to redraw itself with the
+    android.view.View#invalidate invalidate()} method on a View to force the screen to redraw itself with the
     updated animated values. You do this in the
     {@link android.animation.ValueAnimator.AnimatorUpdateListener#onAnimationUpdate onAnimationUpdate()}
     callback. For example, animating the color property of a Drawable object only cause updates to the
@@ -825,7 +824,7 @@
 
   <h2 id="views">Animating Views</h2>
 
-  <p>The property animation system allow streamlined animation of View objects and offerse
+  <p>The property animation system allow streamlined animation of View objects and offers
   a few advantages over the view animation system. The view
   animation system transformed View objects by changing the way that they were drawn. This was
   handled in the container of each View, because the View itself had no properties to manipulate.
diff --git a/docs/html/guide/topics/location/index.jd b/docs/html/guide/topics/location/index.jd
index 3217196..c4e8829 100644
--- a/docs/html/guide/topics/location/index.jd
+++ b/docs/html/guide/topics/location/index.jd
@@ -59,7 +59,9 @@
 
 <h2 id="maps">Google Maps Android API</h2>
 
-<p>With the Google Maps Android API, you can add maps to your app that are based on Google
+<p>With the 
+<a href="http://developers.google.com/maps/documentation/android/">Google Maps Android API</a>,
+you can add maps to your app that are based on Google
 Maps data. The API automatically handles access to Google Maps servers, data downloading,
 map display, and touch gestures on the map. You can also use API calls to add markers,
 polygons and overlays, and to change the user's view of a particular map area.</p>
@@ -85,6 +87,6 @@
 
 <p>To integrate Google Maps into your app, you need to install the Google Play services
 libraries for your Android SDK. For more details, read about <a
-href="{@docRoot}google/play-services/index.html">Google Play services</a>.</p>
+href="{@docRoot}google/play-services/maps.html">Google Play services</a>.</p>
 
 
diff --git a/docs/html/guide/topics/location/strategies.jd b/docs/html/guide/topics/location/strategies.jd
index 6cc8f1a..2f7e6c3 100644
--- a/docs/html/guide/topics/location/strategies.jd
+++ b/docs/html/guide/topics/location/strategies.jd
@@ -1,6 +1,5 @@
 page.title=Location Strategies
-parent.title=Location and Maps
-parent.link=index.html
+page.tags="geolocation","maps","mapview"
 @jd:body
 
 <div id="qv-wrapper">
diff --git a/docs/html/guide/topics/manifest/activity-alias-element.jd b/docs/html/guide/topics/manifest/activity-alias-element.jd
index ba2c154..d3df08b 100644
--- a/docs/html/guide/topics/manifest/activity-alias-element.jd
+++ b/docs/html/guide/topics/manifest/activity-alias-element.jd
@@ -89,7 +89,7 @@
 
 <dt><a name="label"></a>{@code android:label}</dt>
 <dd>A user-readable label for the alias when presented to users through the alias.
-See the the <code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code> element's 
+See the <code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code> element's
 <code><a href="{@docRoot}guide/topics/manifest/activity-element.html#label">label</a></code> attribute for more information.
 </p></dd>
 
@@ -132,4 +132,4 @@
 <dt>see also:</dt>
 <dd><code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code></dd>
 
-</dl>
\ No newline at end of file
+</dl>
diff --git a/docs/html/guide/topics/manifest/activity-element.jd b/docs/html/guide/topics/manifest/activity-element.jd
index 2aedaec..c9f505f 100644
--- a/docs/html/guide/topics/manifest/activity-element.jd
+++ b/docs/html/guide/topics/manifest/activity-element.jd
@@ -217,7 +217,7 @@
   </tr><tr>
   <td>"{@code uiMode}"</td>
    <td>The user interface mode has changed &mdash; this can be caused when the user places the
-device into a desk/car dock or when the the night mode changes. See {@link
+device into a desk/car dock or when the night mode changes. See {@link
 android.app.UiModeManager}. 
     <em>Added in API level 8</em>.</td>
   </tr><tr>
diff --git a/docs/html/guide/topics/manifest/data-element.jd b/docs/html/guide/topics/manifest/data-element.jd
index 8fd91de..766d2d7 100644
--- a/docs/html/guide/topics/manifest/data-element.jd
+++ b/docs/html/guide/topics/manifest/data-element.jd
@@ -85,6 +85,9 @@
 The subtype can be the asterisk wildcard ({@code *}) to indicate that any 
 subtype matches.
 
+<p>It's common for an intent filter to declare a {@code &lt;data>} that includes
+only the {@code android:mimeType} attribute.</p>
+
 <p class="note">Note: MIME type matching in the Android framework is
 case-sensitive, unlike formal RFC MIME types.  As a result, you should always
 specify MIME types using lowercase letters.</p>
diff --git a/docs/html/guide/topics/manifest/intent-filter-element.jd b/docs/html/guide/topics/manifest/intent-filter-element.jd
index f90541c..68da981 100644
--- a/docs/html/guide/topics/manifest/intent-filter-element.jd
+++ b/docs/html/guide/topics/manifest/intent-filter-element.jd
@@ -119,7 +119,11 @@
 
 <p>
 The value must be an integer, such as "{@code 100}".  Higher numbers have a
-higher priority.
+higher priority. The default value is 0.
+The value must be greater than -1000 and less than 1000.</p>
+
+<p>Also see {@link android.content.IntentFilter#setPriority
+setPriority()}.
 </p></dd>
 
 </dl></dd>
diff --git a/docs/html/guide/topics/manifest/meta-data-element.jd b/docs/html/guide/topics/manifest/meta-data-element.jd
index 85a871d..56a214c 100644
--- a/docs/html/guide/topics/manifest/meta-data-element.jd
+++ b/docs/html/guide/topics/manifest/meta-data-element.jd
@@ -80,7 +80,7 @@
 </tr><tr>
   <td>Color value, in the form "{@code #rgb}", "{@code #argb}", 
       "{@code #rrggbb}", or "{@code #aarrggbb}"</td>
-  <td>{@link android.os.Bundle#getString(String) getString()}</td>
+  <td>{@link android.os.Bundle#getInt(String) getInt()}</td>
 </tr><tr>
   <td>Float value, such as "{@code 1.23}"</td>
   <td>{@link android.os.Bundle#getFloat(String) getFloat()}</td>
diff --git a/docs/html/guide/topics/manifest/uses-sdk-element.jd b/docs/html/guide/topics/manifest/uses-sdk-element.jd
index f9e2785..3b3bb8f 100644
--- a/docs/html/guide/topics/manifest/uses-sdk-element.jd
+++ b/docs/html/guide/topics/manifest/uses-sdk-element.jd
@@ -26,14 +26,14 @@
 </div>
 </div>
 
-<div class="sidebox-wrapper"> 
+<div class="sidebox-wrapper">
 <div class="sidebox">
-    <img src="{@docRoot}assets/images/icon_play.png" style="float:left;margin:0;padding:0;"> 
-    <p style="color:#669999;padding-top:1em;">Google Play Filtering</p> 
+    <img src="{@docRoot}assets/images/icon_play.png" style="float:left;margin:0;padding:0;">
+    <p style="color:#669999;padding-top:1em;">Google Play Filtering</p>
     <p style="padding-top:1em;">Google Play uses the <code>&lt;uses-sdk&gt;</code>
-    attributes declared in your app manifest to filter your app from devices 
+    attributes declared in your app manifest to filter your app from devices
     that do not meet it's platform version requirements. Before setting these
-    attributes, make sure that you understand 
+    attributes, make sure that you understand
     <a href="{@docRoot}google/play/filters.html">Google Play filters</a>. </p>
   </div>
 </div>
@@ -41,7 +41,7 @@
 <dl class="xml">
 <dt>syntax:</dt>
 <dd><pre>
-&lt;uses-sdk android:<a href="#min">minSdkVersion</a>="<i>integer</i>" 
+&lt;uses-sdk android:<a href="#min">minSdkVersion</a>="<i>integer</i>"
           android:<a href="#target">targetSdkVersion</a>="<i>integer</i>"
           android:<a href="#max">maxSdkVersion</a>="<i>integer</i>" /&gt;</pre></dd>
 
@@ -55,14 +55,14 @@
 </p>
 
 <p>Despite its name, this element is used to specify the API Level, <em>not</em>
-the version number of the SDK (software development kit) or Android platform. 
+the version number of the SDK (software development kit) or Android platform.
 The API Level is always a single integer. You cannot derive the API Level from
 its associated Android version number (for example, it is not the same as the
 major version or the sum of the major and minor versions).</p>
 
 <p>Also read the document about
 <a href="{@docRoot}tools/publishing/versioning.html">Versioning Your Applications</a>.
-</p></dd> 
+</p></dd>
 
 <dt>attributes:</dt>
 
@@ -117,8 +117,8 @@
   </dd>
 
   <dt><a name="max"></a>{@code android:maxSdkVersion}</dt>
-  <dd>An integer designating the maximum API Level on which the application is 
-  designed to run. 
+  <dd>An integer designating the maximum API Level on which the application is
+  designed to run.
 
   <p>In Android 1.5, 1.6, 2.0, and 2.0.1, the system checks the value of this
   attribute when installing an application and when re-validating the application
@@ -165,7 +165,7 @@
 as a filter, however, when presenting users with applications available for
 download. </div>
   </dd>
-  
+
 
 </dl></dd>
 
@@ -217,7 +217,7 @@
 <p>The framework API that an Android platform delivers is specified using an
 integer identifier called "API Level". Each Android platform version supports
 exactly one API Level, although support is implicit for all earlier API Levels
-(down to API Level 1). The initial release of the Android platform provided 
+(down to API Level 1). The initial release of the Android platform provided
 API Level 1 and subsequent releases have incremented the API Level.</p>
 
 <p>The table below specifies the API Level supported by each version of the
@@ -227,8 +227,8 @@
 
 <table>
   <tr><th>Platform Version</th><th>API Level</th><th>VERSION_CODE</th><th>Notes</th></tr>
- 
-    <tr><td><a href="{@docRoot}about/versions/android-4.2.html">Android 4.2</a></td>
+
+    <tr><td><a href="{@docRoot}about/versions/android-4.2.html">Android 4.2, 4.2.2</a></td>
     <td><a href="{@docRoot}sdk/api_diff/17/changes.html" title="Diff Report">17</a></td>
     <td>{@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}</td>
     <td><a href="{@docRoot}about/versions/jelly-bean.html">Platform
@@ -250,70 +250,70 @@
     <td><a href="{@docRoot}sdk/api_diff/14/changes.html" title="Diff Report">14</a></td>
     <td>{@link android.os.Build.VERSION_CODES#ICE_CREAM_SANDWICH}</td>
     </tr>
-  
+
     <tr><td><a href="{@docRoot}about/versions/android-3.2.html">Android 3.2</a></td>
     <td><a href="{@docRoot}sdk/api_diff/13/changes.html" title="Diff Report">13</a></td>
     <td>{@link android.os.Build.VERSION_CODES#HONEYCOMB_MR2}</td>
     <td><!-- <a href="{@docRoot}about/versions/android-3.2-highlights.html">Platform
 Highlights</a>--></td></tr>
-  
+
   <tr><td><a href="{@docRoot}about/versions/android-3.1.html">Android 3.1.x</a></td>
     <td><a href="{@docRoot}sdk/api_diff/12/changes.html" title="Diff Report">12</a></td>
     <td>{@link android.os.Build.VERSION_CODES#HONEYCOMB_MR1}</td>
     <td><a href="{@docRoot}about/versions/android-3.1-highlights.html">Platform Highlights</a></td></tr>
-    
+
   <tr><td><a href="{@docRoot}about/versions/android-3.0.html">Android 3.0.x</td>
     <td><a href="{@docRoot}sdk/api_diff/11/changes.html" title="Diff Report">11</a></td>
     <td>{@link android.os.Build.VERSION_CODES#HONEYCOMB}</td>
     <td><a href="{@docRoot}about/versions/android-3.0-highlights.html">Platform Highlights</a></td></tr>
-    
+
   <tr><td><a href="{@docRoot}about/versions/android-2.3.3.html">Android 2.3.4<br>Android 2.3.3</td>
     <td><a href="{@docRoot}sdk/api_diff/10/changes.html" title="Diff Report">10</a></td>
     <td>{@link android.os.Build.VERSION_CODES#GINGERBREAD_MR1}</td>
     <td rowspan="2"><a href="{@docRoot}about/versions/android-2.3-highlights.html">Platform
 Highlights</a></td></tr>
-  
+
   <tr><td><a href="{@docRoot}about/versions/android-2.3.html">Android 2.3.2<br>Android 2.3.1<br>Android
 2.3</td>
     <td><a href="{@docRoot}sdk/api_diff/9/changes.html" title="Diff Report">9</a></td>
     <td>{@link android.os.Build.VERSION_CODES#GINGERBREAD}</td>
     </tr>
-  
+
   <tr><td><a href="{@docRoot}about/versions/android-2.2.html">Android 2.2.x</td>
     <td ><a href="{@docRoot}sdk/api_diff/8/changes.html" title="Diff Report">8</a></td>
     <td>{@link android.os.Build.VERSION_CODES#FROYO}</td>
     <td><a href="{@docRoot}about/versions/android-2.2-highlights.html">Platform Highlights</a></td></tr>
-  
+
   <tr><td><a href="{@docRoot}about/versions/android-2.1.html">Android 2.1.x</td>
     <td><a href="{@docRoot}sdk/api_diff/7/changes.html" title="Diff Report">7</a></td>
     <td>{@link android.os.Build.VERSION_CODES#ECLAIR_MR1}</td>
     <td rowspan="3" ><a href="{@docRoot}about/versions/android-2.0-highlights.html">Platform
 Highlights</a></td></tr>
-    
+
   <tr><td><a href="{@docRoot}about/versions/android-2.0.1.html">Android 2.0.1</td>
     <td><a href="{@docRoot}sdk/api_diff/6/changes.html" title="Diff Report">6</a></td>
     <td>{@link android.os.Build.VERSION_CODES#ECLAIR_0_1}</td>
     </tr>
-    
+
   <tr><td><a href="{@docRoot}about/versions/android-2.0.html">Android 2.0</td>
     <td><a href="{@docRoot}sdk/api_diff/5/changes.html" title="Diff Report">5</a></td>
     <td>{@link android.os.Build.VERSION_CODES#ECLAIR}</td>
     </tr>
-    
+
   <tr><td><a href="{@docRoot}about/versions/android-1.6.html">Android 1.6</td>
     <td><a href="{@docRoot}sdk/api_diff/4/changes.html" title="Diff Report">4</a></td>
     <td>{@link android.os.Build.VERSION_CODES#DONUT}</td>
     <td><a href="{@docRoot}about/versions/android-1.6-highlights.html">Platform Highlights</a></td></tr>
-    
+
   <tr><td><a href="{@docRoot}about/versions/android-1.5.html">Android 1.5</td>
     <td><a href="{@docRoot}sdk/api_diff/3/changes.html" title="Diff Report">3</a></td>
     <td>{@link android.os.Build.VERSION_CODES#CUPCAKE}</td>
     <td><a href="{@docRoot}about/versions/android-1.5-highlights.html">Platform Highlights</a></td></tr>
-    
+
   <tr><td><a href="{@docRoot}about/versions/android-1.1.html">Android 1.1</td>
     <td>2</td>
     <td>{@link android.os.Build.VERSION_CODES#BASE_1_1}</td><td></td></tr>
-    
+
   <tr><td>Android 1.0</td>
     <td>1</td>
     <td>{@link android.os.Build.VERSION_CODES#BASE}</td>
@@ -324,10 +324,10 @@
 <h2 id="uses">Uses of API Level in Android</h2>
 
 <p>The API Level identifier serves a key role in ensuring the best possible
-experience for users and application developers: 
+experience for users and application developers:
 
 <ul>
-<li>It lets the Android platform describe the maximum framework API revision 
+<li>It lets the Android platform describe the maximum framework API revision
 that it supports</li>
 <li>It lets applications describe the framework API revision that they
 require</li>
@@ -349,7 +349,7 @@
 <li><code>android:targetSdkVersion</code> &mdash; Specifies the API Level
 on which the application is designed to run. In some cases, this allows the
 application to use manifest elements or behaviors defined in the target
-API Level, rather than being restricted to using only those defined 
+API Level, rather than being restricted to using only those defined
 for the minimum API Level.</li>
 <li><code>android:maxSdkVersion</code> &mdash; Specifies the maximum API Level
 on which the application is able to run. <strong>Important:</strong> Please read the <a
@@ -375,7 +375,7 @@
 must be less than or equal to the system's API Level integer. If not declared,
 the system assumes that the application requires API Level 1. </li>
 <li>If a <code>android:maxSdkVersion</code> attribute is declared, its value
-must be equal to or greater than the system's API Level integer. 
+must be equal to or greater than the system's API Level integer.
 If not declared, the system assumes that the application
 has no maximum API Level. Please read the <a
 href="{@docRoot}guide/topics/manifest/uses-sdk-element.html"><code>&lt;uses-sdk&gt;</code></a>
@@ -470,7 +470,7 @@
 <p>When you are developing your application, you will need to choose
 the platform version against which you will compile the application. In
 general, you should compile your application against the lowest possible
-version of the platform that your application can support. 
+version of the platform that your application can support.
 
 <p>You can determine the lowest possible platform version by compiling the
 application against successively lower build targets. After you determine the
@@ -513,7 +513,7 @@
 located in the &lt;sdk&gt;/tools directory. You can launch the SDK updater by
 executing <code>android sdk</code>. You can
 also simply double-click the android.bat (Windows) or android (OS X/Linux) file.
-In ADT, you can also access the updater by selecting 
+In ADT, you can also access the updater by selecting
 <strong>Window</strong>&nbsp;>&nbsp;<strong>Android SDK
 Manager</strong>.</p>
 
@@ -552,9 +552,9 @@
 <h2 id="filtering">Filtering the Reference Documentation by API Level</h2>
 
 <p>Reference documentation pages on the Android Developers site offer a "Filter
-by API Level" control in the top-right area of each page. You can use the 
-control to show documentation only for parts of the API that are actually 
-accessible to your application, based on the API Level that it specifies in 
+by API Level" control in the top-right area of each page. You can use the
+control to show documentation only for parts of the API that are actually
+accessible to your application, based on the API Level that it specifies in
 the <code>android:minSdkVersion</code> attribute of its manifest file. </p>
 
 <p>To use filtering, select the checkbox to enable filtering, just below the
@@ -574,10 +574,10 @@
 </p>
 
 <p>Also note that the reference documentation for individual API elements
-specifies the API Level at which each element was introduced. The API Level 
-for packages and classes is specified as "Since &lt;api level&gt;" at the 
-top-right corner of the content area on each documentation page. The API Level 
-for class members is specified in their detailed description headers, 
+specifies the API Level at which each element was introduced. The API Level
+for packages and classes is specified as "Since &lt;api level&gt;" at the
+top-right corner of the content area on each documentation page. The API Level
+for class members is specified in their detailed description headers,
 at the right margin. </p>
 
 
diff --git a/docs/html/guide/topics/media/audio-capture.jd b/docs/html/guide/topics/media/audio-capture.jd
index 75d294b..44c618f 100644
--- a/docs/html/guide/topics/media/audio-capture.jd
+++ b/docs/html/guide/topics/media/audio-capture.jd
@@ -1,6 +1,5 @@
 page.title=Audio Capture
-parent.title=Multimedia and Camera 
-parent.link=index.html
+page.tags="mediarecorder"
 @jd:body
 
     <div id="qv-wrapper">
diff --git a/docs/html/guide/topics/media/camera.jd b/docs/html/guide/topics/media/camera.jd
index 3fe23f8..8ebb349 100644
--- a/docs/html/guide/topics/media/camera.jd
+++ b/docs/html/guide/topics/media/camera.jd
@@ -1,6 +1,5 @@
 page.title=Camera
-parent.title=Multimedia and Camera
-parent.link=index.html
+page.tags="mediarecorder"
 @jd:body
 
 <div id="qv-wrapper">
diff --git a/docs/html/guide/topics/media/mediaplayer.jd b/docs/html/guide/topics/media/mediaplayer.jd
index 45a58a7..fb272d2 100644
--- a/docs/html/guide/topics/media/mediaplayer.jd
+++ b/docs/html/guide/topics/media/mediaplayer.jd
@@ -1,6 +1,5 @@
 page.title=Media Playback
-parent.title=Multimedia and Camera 
-parent.link=index.html
+page.tags="mediaplayer","soundpool","audiomanager"
 @jd:body
 
     <div id="qv-wrapper">
diff --git a/docs/html/guide/topics/providers/calendar-provider.jd b/docs/html/guide/topics/providers/calendar-provider.jd
index f53b062..3cd4511 100644
--- a/docs/html/guide/topics/providers/calendar-provider.jd
+++ b/docs/html/guide/topics/providers/calendar-provider.jd
@@ -605,7 +605,7 @@
 Uri updateUri = null;
 // The new title for the event
 values.put(Events.TITLE, &quot;Kickboxing&quot;); 
-myUri = ContentUris.withAppendedId(Events.CONTENT_URI, eventID);
+updateUri = ContentUris.withAppendedId(Events.CONTENT_URI, eventID);
 int rows = getContentResolver().update(updateUri, values, null, null);
 Log.i(DEBUG_TAG, &quot;Rows updated: &quot; + rows);  </pre>
 
@@ -816,7 +816,7 @@
   <tr>
     <td>{@link android.provider.CalendarContract.Instances#END_MINUTE}</td>
     
-    <td>The end minute of the instance measured from midnight in the the
+    <td>The end minute of the instance measured from midnight in the
 Calendar's time zone.</td>
     
   </tr>
diff --git a/docs/html/guide/topics/resources/accessing-resources.jd b/docs/html/guide/topics/resources/accessing-resources.jd
index 0673b6f..8f99653 100644
--- a/docs/html/guide/topics/resources/accessing-resources.jd
+++ b/docs/html/guide/topics/resources/accessing-resources.jd
@@ -50,7 +50,7 @@
 <p>When your application is compiled, {@code aapt} generates the {@code R} class, which contains
 resource IDs for all the resources in your {@code
 res/} directory. For each type of resource, there is an {@code R} subclass (for example,
-{@code R.drawable} for all drawable resources) and for each resource of that type, there is a static
+{@code R.drawable} for all drawable resources), and for each resource of that type, there is a static
 integer (for example, {@code R.drawable.icon}). This integer is the resource ID that you can use
 to retrieve your resource.</p>
 
@@ -68,7 +68,7 @@
 
 <p>There are two ways you can access a resource:</p>
 <ul>
-  <li><strong>In code:</strong> Using an static integer from a sub-class of your {@code R}
+  <li><strong>In code:</strong> Using a static integer from a sub-class of your {@code R}
 class, such as:
     <pre class="classic no-pretty-print">R.string.hello</pre>
     <p>{@code string} is the resource type and {@code hello} is the resource name. There are many
@@ -264,11 +264,13 @@
     android:text=&quot;&#64;string/hello&quot; /&gt;
 </pre>
 
-<p class="note"><strong>Note:</strong> You should use string resources at all times, so that your
-application can be localized for other languages. For information about creating alternative
+<p class="note"><strong>Note:</strong> You should use string resources at 
+all times, so that your application can be localized for other languages. 
+For information about creating alternative
 resources (such as localized strings), see <a
 href="providing-resources.html#AlternativeResources">Providing Alternative
-Resources</a>.</p>
+Resources</a>. For a complete guide to localizing your application for other languages,
+see <a href="localization.html">Localization</a>.</p>
 
 <p>You can even use resources in XML to create aliases. For example, you can create a
 drawable resource that is an alias for another drawable resource:</p>
diff --git a/docs/html/guide/topics/resources/animation-resource.jd b/docs/html/guide/topics/resources/animation-resource.jd
index 3af52aa..e5cac88 100644
--- a/docs/html/guide/topics/resources/animation-resource.jd
+++ b/docs/html/guide/topics/resources/animation-resource.jd
@@ -217,7 +217,7 @@
     </dd>
 
 <dt id="val-animator-element"><code>&lt;animator&gt;</code></dt>
-    <dd>Animates a over a specified amount of time.
+    <dd>Performs an animation over a specified amount of time.
     Represents a {@link android.animation.ValueAnimator}.
 
       <p class="caps">attributes:</p>
@@ -593,7 +593,7 @@
 <p>All interpolators available in Android are subclasses of the {@link
 android.view.animation.Interpolator} class. For each interpolator class, Android
 includes a public resource you can reference in order to apply the interpolator to an animation
-using the the {@code android:interpolator} attribute.
+using the {@code android:interpolator} attribute.
 The following table specifies the resource to use for each interpolator:</p>
 
 <table>
diff --git a/docs/html/guide/topics/resources/layout-resource.jd b/docs/html/guide/topics/resources/layout-resource.jd
index 380ab15..366ddc8 100644
--- a/docs/html/guide/topics/resources/layout-resource.jd
+++ b/docs/html/guide/topics/resources/layout-resource.jd
@@ -135,7 +135,7 @@
     </dd>
   <dt id="requestfocus-element"><code>&lt;requestFocus&gt;</code></dt>
     <dd>Any element representing a {@link android.view.View} object can include this empty element,
-    which gives it's parent initial focus on the screen. You can have only one of these
+    which gives its parent initial focus on the screen. You can have only one of these
     elements per file.</dd>
 
   <dt id="include-element"><code>&lt;include&gt;</code></dt>
diff --git a/docs/html/guide/topics/resources/providing-resources.jd b/docs/html/guide/topics/resources/providing-resources.jd
index b311b7f..5097cc4 100644
--- a/docs/html/guide/topics/resources/providing-resources.jd
+++ b/docs/html/guide/topics/resources/providing-resources.jd
@@ -376,7 +376,7 @@
 screen area. Specifically, the device's smallestWidth is the shortest of the screen's available
 height and width (you may also think of it as the "smallest possible width" for the screen). You can
 use this qualifier to ensure that, regardless of the screen's current orientation, your
-application's has at least {@code &lt;N&gt;} dps of width available for it UI.</p>
+application has at least {@code &lt;N&gt;} dps of width available for its UI.</p>
         <p>For example, if your layout requires that its smallest dimension of screen area be at
 least 600 dp at all times, then you can use this qualifer to create the layout resources, {@code
 res/layout-sw600dp/}. The system will use these resources only when the smallest dimension of
diff --git a/docs/html/guide/topics/resources/runtime-changes.jd b/docs/html/guide/topics/resources/runtime-changes.jd
index 5f39aa5..45a548a 100644
--- a/docs/html/guide/topics/resources/runtime-changes.jd
+++ b/docs/html/guide/topics/resources/runtime-changes.jd
@@ -1,6 +1,5 @@
 page.title=Handling Runtime Changes
-parent.title=Application Resources
-parent.link=index.html
+page.tags="activity","lifecycle"
 @jd:body
 
 <div id="qv-wrapper">
diff --git a/docs/html/guide/topics/search/adding-custom-suggestions.jd b/docs/html/guide/topics/search/adding-custom-suggestions.jd
index 02ee084..47ad2fe 100644
--- a/docs/html/guide/topics/search/adding-custom-suggestions.jd
+++ b/docs/html/guide/topics/search/adding-custom-suggestions.jd
@@ -1,6 +1,5 @@
 page.title=Adding Custom Suggestions
-parent.title=Search
-parent.link=index.html
+page.tags="SearchRecentSuggestionsProvider",
 @jd:body
 
 <div id="qv-wrapper">
diff --git a/docs/html/guide/topics/search/adding-recent-query-suggestions.jd b/docs/html/guide/topics/search/adding-recent-query-suggestions.jd
index 2c9a461..c1d59d4 100644
--- a/docs/html/guide/topics/search/adding-recent-query-suggestions.jd
+++ b/docs/html/guide/topics/search/adding-recent-query-suggestions.jd
@@ -1,6 +1,6 @@
 page.title=Adding Recent Query Suggestions
-parent.title=Search
-parent.link=index.html
+page.tags="SearchRecentSuggestions","SearchRecentSuggestionsProvider"
+
 @jd:body
 
 <div id="qv-wrapper">
diff --git a/docs/html/guide/topics/search/search-dialog.jd b/docs/html/guide/topics/search/search-dialog.jd
index b9a26d6..fc722b2 100644
--- a/docs/html/guide/topics/search/search-dialog.jd
+++ b/docs/html/guide/topics/search/search-dialog.jd
@@ -1,6 +1,5 @@
 page.title=Creating a Search Interface
-parent.title=Search
-parent.link=index.html
+page.tags="searchview"
 @jd:body
 
 <div id="qv-wrapper">
@@ -722,6 +721,7 @@
     // Get the SearchView and set the searchable configuration
     SearchManager searchManager = (SearchManager) {@link android.app.Activity#getSystemService getSystemService}(Context.SEARCH_SERVICE);
     SearchView searchView = (SearchView) menu.findItem(R.id.menu_search).getActionView();
+    // Assumes current activity is the searchable activity
     searchView.setSearchableInfo(searchManager.getSearchableInfo({@link android.app.Activity#getComponentName()}));
     searchView.setIconifiedByDefault(false); // Do not iconify the widget; expand it by default
 
diff --git a/docs/html/guide/topics/search/searchable-config.jd b/docs/html/guide/topics/search/searchable-config.jd
index fb689f9..fc13c04 100644
--- a/docs/html/guide/topics/search/searchable-config.jd
+++ b/docs/html/guide/topics/search/searchable-config.jd
@@ -1,6 +1,5 @@
 page.title=Searchable Configuration
-parent.title=Search
-parent.link=index.html
+
 @jd:body
 
 <div id="qv-wrapper">
diff --git a/docs/html/guide/topics/security/index.jd b/docs/html/guide/topics/security/index.jd
deleted file mode 100644
index 775fc03..0000000
--- a/docs/html/guide/topics/security/index.jd
+++ /dev/null
@@ -1,65 +0,0 @@
-page.title=Security and Permissions
-page.landing=true
-page.landing.intro=Android's security architecture gives the user full control over what resources are accessible to each app, protecting the system itself and all apps in it. Learn how to use system permissions to request access to the resources your app needs and design your app for optimal security. 
-page.landing.image=
-
-@jd:body
-
-<div style="width=100%;padding-left:1em;">
-
-  <div style="float:left;clear:both;padding-top:20px;">
-    <p style="text-transform:uppercase;"><b style="color:#666;font-size:14px;">Blog Articles</b></p>
-
-    <div class="" style="border-top:2px solid #DDD;margin:1em 0;background-color:#F7F7F7;width:336px">
-
-      <div style="float:left;padding:8px;padding-right:16px;">
-        <img src="/assets/images/resource-article.png">
-      </div>
-
-      <div class="caption">
-        <p style="margin:0;padding:0;font-weight:bold;"><a href="">Accessibility: Are You Serving All Your Users?</a></p>
-        <p style="margin:0;padding:0">In the upcoming weeks, some of the older Client Login authentication keys will expire. 
-        If you generated the token you’re currently using to authenticate with the C2DM servers before October 2011, it will stop working.</p>
-
-        <p style="margin:0;padding:0;font-weight:bold;"><a href="">Android C2DM — Client Login key expiration</a></p>
-        <p  style="margin:0;padding:0">Accessibility is about making sure that Android users who have limited vision or other physical impairments can use your application just as well</p>
-
-        <p style="margin:0;padding:0;font-weight:bold;"><a href="">A Faster Emulator with Better Hardware Support</a></p>
-        <p  style="margin:0;padding:0">The Android emulator is a key tool for Android developers in building and testing their apps.
-        As the power and diversity of Android devices has grown quickly, it’s been hard for the emulator keep pace. </p>
-
-        <a href="">More &raquo;</a>
-      </div>
-    </div>
-  </div>
-
-  <div style="float:right;padding-top:20px;">
-    <p style="text-transform:uppercase;"><b style="color:#666;font-size:14px;">Training</b></p>
-
-    <div class="" style="border-top:2px solid #DDD;bordddser-top:2px solid #FF8800;margin:1em 0;background-color:#F7F7F7;width:336px">
-
-      <div style="float:left;padding:8px;padding-right:16px;">
-        <img src="/assets/images/resource-tutorial.png">
-      </div>
-
-      <div class="caption">
-        <p style="margin:0;padding:0;font-weight:bold;"><a href="">Managing the Activity Lifecycle</a></p>
-        <p  style="margin:0;padding:0">This class explains important lifecycle callback methods that each Activity
-        instance receives and how you can use them so your activity does what the user expects and does not consume system
-        resources when your activity doesn't need them.</p>
-
-        <p style="margin:0;padding:0;font-weight:bold;"><a href="">Supporting Different Devices</a></p>
-        <p  style="margin:0;padding:0">This class teaches you how to use basic platform features that leverage alternative
-        resources and other features so your app can provide an optimized user experience on a variety of Android-compatible devices,
-        using a single application package (APK).</p>
-
-        <p style="margin:0;padding:0;font-weight:bold;"><a href="">Sharing Content</a></p>
-        <p  style="margin:0;padding:0">This class covers some common ways you can send and receive content between
-        applications using Intent APIs and the ActionProvider object.</p>
-
-        <a href="">More &raquo;</a>
-      </div>
-    </div>
-</div>
-
-</div>
\ No newline at end of file
diff --git a/docs/html/guide/topics/security/security.jd b/docs/html/guide/topics/security/security.jd
deleted file mode 100644
index 9cdccae..0000000
--- a/docs/html/guide/topics/security/security.jd
+++ /dev/null
@@ -1,767 +0,0 @@
-page.title=Designing for Security
-@jd:body
-
-<div id="qv-wrapper">
-<div id="qv">
-<h2>In this document</h2>
-<ol>
-<li><a href="#Dalvik">Using Davlik Code</a></li>
-<li><a href="#Native">Using Native Code</a></li>
-<li><a href="#Data">Storing Data</a></li>
-<li><a href="#IPC">Using IPC</a></li>
-<li><a href="#Permissions">Using Permissions</a></li>
-<li><a href="#Networking">Using Networking</a></li>
-<li><a href="#DynamicCode">Dynamically Loading Code</a></li>
-<li><a href="#Input">Performing Input Validation</a></li>
-<li><a href="#UserData">Handling User Data</a></li>
-<li><a href="#Crypto">Using Cryptography</a></li>
-</ol>
-<h2>See also</h2>
-<ol>
-<li><a href="http://source.android.com/tech/security/index.html">Android
-Security Overview</a></li>
-<li><a href="{@docRoot}guide/topics/security/security.html">Android Security
-And Permissions</a></li>
-</ol>
-</div></div>
-<p>Android was designed so that most developers will be able to build
-applications using the default settings and not be confronted with difficult
-decisions about security.  Android also has a number of security features built
-into the operating system that significantly reduce the frequency and impact of
-application security issues.</p>
-
-<p>Some of the security features that help developers build secure applications
-include:
-<ul>
-<li>The Android Application Sandbox that isolates data and code execution on a
-per-application basis.</li>
-<li>Android application framework with robust implementations of common
-security functionality such as cryptography, permissions, and secure IPC.</li>
-<li>Technologies like ASLR, NX, ProPolice, safe_iop, OpenBSD dlmalloc, OpenBSD
-calloc, and Linux mmap_min_addr to mitigate risks associated with common memory
-management errors</li>
-<li>An encrypted filesystem that can be enabled to protect data on lost or
-stolen devices.</li>
-</ul></p>
-
-<p>Nevertheless, it is important for developers to be familiar with Android
-security best practices to make sure they take advantage of these capabilities
-and to reduce the likelihood of inadvertently introducing security issues that
-can affect their applications.</p>
-
-<p>This document is organized around common APIs and development techniques
-that can have security implications for your application and its users. As
-these best practices are constantly evolving, we recommend you check back
-occasionally throughout your application development process.</p>
-
-<a name="Dalvik"></a>
-<h2>Using Dalvik Code</h2>
-<p>Writing secure code that runs in virtual machines is a well-studied topic
-and many of the issues are not specific to Android.  Rather than attempting to
-rehash these topics, we’d recommend that you familiarize yourself with the
-existing literature. Two of the more popular resources are:
-<ul>
-<li><a href="http://www.securingjava.com/toc.html">
-http://www.securingjava.com/toc.html</a></li>
-<li><a
-href="https://www.owasp.org/index.php/Java_Security_Resources">
-https://www.owasp.org/index.php/Java_Security_Resources</a></li>
-</ul></p>
-
-<p>This document is focused on the areas which are Android specific and/or
-different from other environments.  For developers experienced with VM
-programming in other environments, there are two broad issues that may be
-different about writing apps for Android:
-<ul>
-<li>Some virtual machines, such as the JVM or .net runtime, act as a security
-boundary, isolating code from the underlying operating system capabilities.  On
-Android, the Dalvik VM is not a security boundary -- the application sandbox is
-implemented at the OS level, so Dalvik can interoperate with native code in the
-same application without any security constraints.</li>
-<li>Given the limited storage on mobile devices, it’s common for developers
-to want to build modular applications and use dynamic class loading.  When
-doing this consider both the source where you retrieve your application logic
-and where you store it locally. Do not use dynamic class loading from sources
-that are not verified, such as unsecured network sources or external storage,
-since that code can be modified to include malicious behavior.</li>
-</ul></p>
-
-<a name="Native"></a>
-<h2>Using Native Code</h2>
-
-<p>In general, we encourage developers to use the Android SDK for most
-application development, rather than using native code.   Applications built
-with native code are more complex, less portable, and more like to include
-common memory corruption errors such as buffer overflows.</p>
-
-<p>Android is built using the Linux kernel and being familiar with Linux
-development security best practices is especially useful if you are going to
-use native code. This document is too short to discuss all of those best
-practices, but one of the most popular resources is  “Secure Programming for
-Linux and Unix HOWTO”, available at <a
-href="http://www.dwheeler.com/secure-programs">
-http://www.dwheeler.com/secure-programs</a>.</p>
-
-<p>An important difference between Android and most Linux environments is the
-Application Sandbox.  On Android, all applications run in the Application
-Sandbox, including those written with native code.  At the most basic level, a
-good way to think about it for developers familiar with Linux is to know that
-every application is given a unique UID with very limited permissions. This is
-discussed in more detail in the <a
-href="http://source.android.com/tech/security/index.html">Android Security
-Overview</a> and you should be familiar with application permissions even if
-you are using native code.</p>
-
-<a name="Data"></a>
-<h2>Storing Data</h2>
-
-<h3>Using internal files</h3>
-
-<p>By default, files created on <a
-href="{@docRoot}guide/topics/data/data-storage.html#filesInternal">internal
-storage</a> are only accessible to the application that created the file. This
-protection is implemented by Android and is sufficient for most
-applications.</p>
-
-<p>Use of <a
-href="{@docRoot}reference/android/content/Context.html#MODE_WORLD_WRITEABLE">
-world writable</a> or <a
-href="{@docRoot}reference/android/content/Context.html#MODE_WORLD_READABLE">world
-readable</a> files for IPC is discouraged because it does not provide
-the ability to limit data access to particular applications, nor does it
-provide any control on data format. As an alternative, you might consider using
-a ContentProvider which provides read and write permissions, and can make
-dynamic permission grants on a case-by-case basis.</p>
-
-<p>To provide additional protection for sensitive data, some applications
-choose to encrypt local files using a key that is not accessible to the
-application. (For example, a key can be placed in a {@link java.security.KeyStore} and
-protected with a user password that is not stored on the device).  While this
-does not protect data from a root compromise that can monitor the user
-inputting the password,  it can provide protection for a lost device without <a
-href="http://source.android.com/tech/encryption/index.html">file system
-encryption</a>.</p>
-
-<h3>Using external storage</h3>
-
-<p>Files created on <a
-href="{@docRoot}guide/topics/data/data-storage.html#filesExternal">external
-storage</a>, such as SD Cards, are globally readable and writable.  Since
-external storage can be removed by the user and also modified by any
-application,  applications should not store sensitive information using
-external storage.</p>
-
-<p>As with data from any untrusted source, applications should perform input
-validation when handling data from external storage (see Input Validation
-section).  We strongly recommend that applications not store executables or
-class files on external storage prior to dynamic loading.  If an application
-does retrieve executable files from external storage they should be signed and
-cryptographically verified prior to dynamic loading.</p>
-
-<h3>Using content providers</h3>
-
-<p>ContentProviders provide a structured storage mechanism that can be limited
-to your own application, or exported to allow access by other applications. By
-default, a <code>
-<a href="{@docRoot}reference/android/content/ContentProvider.html">
-ContentProvider</a></code> is
-<a href="{@docRoot}guide/topics/manifest/provider-element.html#exported">exported
-</a> for use by other applications.  If you do not intend to provide other
-applications with access to your<code>
-<a href="{@docRoot}reference/android/content/ContentProvider.html">
-ContentProvider</a></code>, mark them as <code><a
-href="{@docRoot}guide/topics/manifest/provider-element.html#exported">
-android:exported=false</a></code> in the application manifest.</p>
-
-<p>When creating a <code>
-<a href="{@docRoot}reference/android/content/ContentProvider.html">ContentProvider
-</a></code> that will be exported for use by other applications, you can specify
-a single
-<a href="{@docRoot}guide/topics/manifest/provider-element.html#prmsn">permission
-</a> for reading and writing, or distinct permissions for reading and writing
-within the manifest. We recommend that you limit your permissions to those
-required to accomplish the task at hand. Keep in mind that it’s usually
-easier to add permissions later to expose new functionality than it is to take
-them away and break existing users.</p>
-
-<p>If you are using a <code>
-<a href="{@docRoot}reference/android/content/ContentProvider.html">
-ContentProvider</a></code> for sharing data between applications built by the
-same developer, it is preferable to use
-<a href="{@docRoot}guide/topics/manifest/permission-element.html#plevel">signature
-level permissions</a>.  Signature permissions do not require user confirmation,
-so they provide a better user experience and more controlled access to the
-<code>
-<a href="{@docRoot}reference/android/content/ContentProvider.html">
-ContentProvider</a></code>.</p>
-
-<p>ContentProviders can also provide more granular access by declaring the <a
-href="{@docRoot}guide/topics/manifest/provider-element.html#gprmsn">
-grantUriPermissions</a> element and using the <code><a
-href="{@docRoot}reference/android/content/Intent.html#FLAG_GRANT_READ_URI_PERMISSION">FLAG_GRANT_READ_URI_PERMISSION</a></code>
-and <code><a
-href="{@docRoot}reference/android/content/Intent.html#FLAG_GRANT_WRITE_URI_PERMISSION">FLAG_GRANT_WRITE_URI_PERMISSION</a></code>
-flags in the Intent object
-that activates the component.  The scope of these permissions can be further
-limited by the <code><a
-href="{@docRoot}guide/topics/manifest/grant-uri-permission-element.html">
-grant-uri-permission element</a></code>.</p>
-
-<p>When accessing a <code>
-<a href="{@docRoot}reference/android/content/ContentProvider.html">
-ContentProvider</a></code>, use parameterized query methods such as <code>
-<a href="{@docRoot}reference/android/content/ContentProvider.html#query(android.net.Uri,%20java.lang.String[],%20java.lang.String,%20java.lang.String[],%20java.lang.String)">query()</a></code>, <code><a
-href="{@docRoot}reference/android/content/ContentProvider.html#update(android.net.Uri,%20android.content.ContentValues,%20java.lang.String,%20java.lang.String[])">update()</a></code>, and <code><a
-href="{@docRoot}reference/android/content/ContentProvider.html#delete(android.net.Uri,%20java.lang.String,%20java.lang.String[])">delete()</a></code> to avoid
-potential <a href="http://en.wikipedia.org/wiki/SQL_injection">SQL
-Injection</a> from untrusted data. Note that using parameterized methods is not
-sufficient if the <code>selection</code> is built by concatenating user data
-prior to submitting it to the method.</p>
-
-<p>Do not have a false sense of security about the write permission.  Consider
-that the write permission allows SQL statements which make it possible for some
-data to be confirmed using creative <code>WHERE</code> clauses and parsing the
-results. For example, an attacker might probe for presence of a specific phone
-number in a call-log by modifying a row only if that phone number already
-exists. If the content provider data has predictable structure, the write
-permission may be equivalent to providing both reading and writing.</p>
-
-<a name="IPC"></a>
-<h2>Using Interprocess Communication (IPC)</h2>
-
-<p>Some Android applications attempt to implement IPC using traditional Linux
-techniques such as network sockets and shared files.  We strongly encourage the
-use of Android system functionality for IPC such as Intents, Binders, Services,
-and Receivers.  The Android IPC mechanisms allow you to verify the identity of
-the application connecting to your IPC and set security policy for each IPC
-mechanism.</p>
-
-<p>Many of the security elements are shared across IPC mechanisms. <a
-href="{@docRoot}reference/android/content/BroadcastReceiver.html">
-Broadcast Receivers</a>, <a
-href="{@docRoot}reference/android/R.styleable.html#AndroidManifestActivity">
-Activities</a>, and <a
-href="{@docRoot}reference/android/R.styleable.html#AndroidManifestService">
-Services</a> are all declared in the application manifest.  If your IPC mechanism is
-not intended for use by other applications, set the <a
-href="{@docRoot}guide/topics/manifest/service-element.html#exported">{@code android:exported}</a>
-property to false.  This is useful for applications that consist of multiple processes
-within the same UID, or if you decide late in development that you do not
-actually want to expose functionality as IPC but you don’t want to rewrite
-the code.</p>
-
-<p>If your IPC is intended to be accessible to other applications, you can
-apply a security policy by using the <a
-href="{@docRoot}reference/android/R.styleable.html#AndroidManifestPermission">
-Permission</a> tag. If IPC is between applications built by the same developer,
-it is preferable to use <a
-href="{@docRoot}guide/topics/manifest/permission-element.html#plevel">signature
-level permissions</a>.  Signature permissions do not require user confirmation,
-so they provide a better user experience and more controlled access to the IPC
-mechanism.</p>
-
-<p>One area that can introduce confusion is the use of intent filters. Note
-that Intent filters should not be considered a security feature -- components
-can be invoked directly and may not have data that would conform to the intent
-filter. You should perform input validation within your intent receiver to
-confirm that it is properly formatted for the invoked receiver, service, or
-activity.</p>
-
-<h3>Using intents</h3>
-
-<p>Intents are the preferred mechanism for asynchronous IPC in Android.
-Depending on your application requirements, you might use <code><a
-href="{@docRoot}reference/android/content/Context.html#sendBroadcast(android.content.Intent)">sendBroadcast()</a></code>, 
-<code><a
-href="{@docRoot}reference/android/content/Context.html#sendOrderedBroadcast(android.content.Intent,%20java.lang.String)">sendOrderedBroadcast()</a></code>,
-or direct an intent to a specific application component.</p>
-
-<p>Note that ordered broadcasts can be “consumed” by a recipient, so they
-may not be delivered to all applications.  If you are sending an Intent where
-delivery to a specific receiver is required, the intent must be delivered
-directly to the receiver.</p>
-
-<p>Senders of an intent can verify that the recipient has a permission
-specifying a non-Null Permission upon sending.  Only applications with that
-Permission will receive the intent.  If data within a broadcast intent may be
-sensitive, you should consider applying a permission to make sure that
-malicious applications cannot register to receive those messages without
-appropriate permissions.  In those circumstances, you may also consider
-invoking the receiver directly, rather than raising a broadcast.</p>
-
-<h3>Using binder and AIDL interfaces</h3>
-
-<p><a href="{@docRoot}reference/android/os/Binder.html">Binders</a> are the
-preferred mechanism for RPC-style IPC in Android. They provide a well-defined
-interface that enables mutual authentication of the endpoints, if required.</p>
-
-<p>We strongly encourage designing interfaces in a manner that does not require
-interface specific permission checks. Binders are not declared within the
-application manifest, and therefore you cannot apply declarative permissions
-directly to a Binder.  Binders generally inherit permissions declared in the
-application manifest for the Service or Activity within which they are
-implemented.  If you are creating an interface that requires authentication
-and/or access controls on a specific binder interface, those controls must be
-explicitly added as code in the interface.</p>
-
-<p>If providing an interface that does require access controls, use <code><a
-href="{@docRoot}reference/android/content/Context.html#checkCallingPermission(java.lang.String)">checkCallingPermission()</a></code>
-to verify whether the
-caller of the Binder has a required permission. This is especially important
-before accessing a Service on behalf of the caller, as the identify of your
-application is passed to other interfaces.  If invoking an interface provided
-by a Service, the <code><a
-href="{@docRoot}reference/android/content/Context.html#bindService(android.content.Intent,%20android.content.ServiceConnection,%20int)">bindService()</a></code>
- invocation may fail if you do not have permission to access the given Service.
- If calling an interface provided locally by your own application, it may be
-useful to use the <code><a
-href="{@docRoot}reference/android/os/Binder.html#clearCallingIdentity()">
-clearCallingIdentity()</a></code> to satisfy internal security checks.</p>
-
-<h3>Using broadcast receivers</h3>
-
-<p>Broadcast receivers are used to handle asynchronous requests initiated via
-an intent.</p>
-
-<p>By default, receivers are exported and can be invoked by any other
-application. If your <code><a
-href="{@docRoot}reference/android/content/BroadcastReceiver.html">
-BroadcastReceivers</a></code> is intended for use by other applications, you
-may want to apply security permissions to receivers using the <code><a
-href="{@docRoot}guide/topics/manifest/receiver-element.html">
-&lt;receiver&gt;</a></code> element within the application manifest.  This will
-prevent applications without appropriate permissions from sending an intent to
-the <code><a
-href="{@docRoot}reference/android/content/BroadcastReceiver.html">
-BroadcastReceivers</a></code>.</p>
-
-<h3>Using Services</h3>
-
-<p>Services are often used to supply functionality for other applications to
-use. Each service class must have a corresponding <service> declaration in its
-package's AndroidManifest.xml.</p>
-
-<p>By default, Services are exported and can be invoked by any other
-application.  Services can be protected using the <a
-href="{@docRoot}guide/topics/manifest/service-element.html#prmsn">{@code android:permission}</a>
-attribute
-within the manifest’s <code><a
-href="{@docRoot}guide/topics/manifest/service-element.html">
-&lt;service&gt;</a></code> tag. By doing so, other applications will need to declare
-a corresponding <code><a
-href="{@docRoot}guide/topics/manifest/uses-permission-element.html">&lt;uses-permission&gt;</a>
-</code> element in their own manifest to be
-able to start, stop, or bind to the service.</p>
-
-<p>A Service can protect individual IPC calls into it with permissions, by
-calling <code><a
-href="{@docRoot}reference/android/content/Context.html#checkCallingPermission(java.lang.String)">checkCallingPermission()</a></code>
-before executing
-the implementation of that call.  We generally recommend using the
-declarative permissions in the manifest, since those are less prone to
-oversight.</p>
-
-<h3>Using Activities</h3>
-
-<p>Activities are most often used for providing the core user-facing
-functionality of an application. By default, Activities are exported and
-invokable by other applications only if they have an intent filter or binder
-declared.  In general, we recommend that you specifically declare a Receiver or
-Service to handle IPC, since this modular approach reduces the risk of exposing
-functionality that is not intended for use by other applications.</p>
-
-<p>If you do expose an Activity for purposes of IPC, the  <code><a
-href="{@docRoot}guide/topics/manifest/activity-element.html#prmsn">android:permission</a></code>
-attribute in the  <code><a
-href="{@docRoot}guide/topics/manifest/activity-element.html">
-&lt;activity&gt;</a></code> declaration in the application manifest can be used to
-restrict access to only those applications which have the stated
-permissions.</p>
-
-<a name="Permissions"></a>
-<h2>Using Permissions</h2>
-
-<h3>Requesting Permissions</h3>
-
-<p>We recommend minimizing the number of permissions requested by an
-application. Not having access to sensitive permissions reduces the risk of
-inadvertently misusing those permissions, can improve user adoption, and makes
-applications less attractive targets for attackers.</p>
-
-<p>If it is possible to design your application in a way that does not require
-a permission, that is preferable.  For example, rather than requesting access
-to device information to create an identifier, create a <a
-href="{@docRoot}reference/java/util/UUID.html">GUID</a> for your application.
-(This specific example is also discussed in Handling User Data) Or, rather than
-using external storage, store data in your application directory.</p>
-
-<p>If a permission is not required, do not request it.  This sounds simple, but
-there has been quite a bit of research into the frequency of over-requesting
-permissions. If you’re interested in the subject you might start with this
-research paper published by U.C. Berkeley: <a
-href="http://www.eecs.berkeley.edu/Pubs/TechRpts/2011/EECS-2011-48.pdf">
-http://www.eecs.berkeley.edu/Pubs/TechRpts/2011/EECS-2011-48.pdf</a></p>
-
-<p>In addition to requesting permissions, your application can use <a
-href="{@docRoot}guide/topics/manifest/permission-element.html">permissions</a>
-to protect IPC that is security sensitive and will be exposed to other
-applications -- such as a <code><a
-href="{@docRoot}reference/android/content/ContentProvider.html">
-ContentProvider</a></code>.  In general, we recommend using access controls
-other than user confirmed permissions where possible since permissions can
-be confusing for users. For example, consider using the <a
-href="{@docRoot}guide/topics/manifest/permission-element.html#plevel">signature
-protection level</a> on permissions for IPC communication between applications
-provided by a single developer.</p>
-
-<p>Do not cause permission re-delegation.  This occurs when an app exposes data
-over IPC that is only available because it has a specific permission, but does
-not require that permission of any clients of it’s IPC interface. More
-details on the potential impacts, and frequency of this type of problem is
-provided in this research paper published at USENIX: <a
-href="http://www.cs.berkeley.edu/~afelt/felt_usenixsec2011.pdf">http://www.cs.be
-rkeley.edu/~afelt/felt_usenixsec2011.pdf</a></p>
-
-<h3>Creating Permissions</h3>
-
-<p>Generally, you should strive to create as few permissions as possible while
-satisfying your security requirements.  Creating a new permission is relatively
-uncommon for most applications, since <a
-href="{@docRoot}reference/android/Manifest.permission.html">system-defined
-permissions</a> cover many situations.  Where appropriate,
-perform access checks using existing permissions.</p>
-
-<p>If you must create a new permission, consider whether you can accomplish
-your task with a Signature permission.  Signature permissions are transparent
-to the user and only allow access by applications signed by the same developer
-as application performing the permission check.  If you create a Dangerous
-permission, then the user needs to decide whether to install the application.
-This can be confusing for other developers, as well as for users.</p>
-
-<p>If you create a Dangerous permission, there are a number of complexities
-that you need to consider.
-<ul>
-<li>The permission must have a string that concisely expresses to a user the
-security decision they will be required to make.</li>
-<li>The permission string must be localized to many different languages.</li>
-<li>Uses may choose not to install an application because a permission is
-confusing or perceived as risky.</li>
-<li>Applications may request the permission when the creator of the permission
-has not been installed.</li>
-</ul></p>
-
-<p>Each of these poses a significant non-technical challenge for an application
-developer, which is why we discourage the use of Dangerous permission.</p>
-
-<a name="Networking"></a>
-<h2>Using Networking</h2>
-
-<h3>Using IP Networking</h3>
-
-<p>Networking on Android is not significantly different from Linux
-environments.  The key consideration is making sure that appropriate protocols
-are used for sensitive data, such as <a
-href="{@docRoot}reference/javax/net/ssl/HttpsURLConnection.html">HTTPS</a> for
-web traffic.   We prefer use of HTTPS over HTTP anywhere that HTTPS is
-supported on the server, since mobile devices frequently connect on networks
-that are not secured, such as public WiFi hotspots.</p>
-
-<p>Authenticated, encrypted socket-level communication can be easily
-implemented using the <code><a
-href="{@docRoot}reference/javax/net/ssl/SSLSocket.html">SSLSocket</a></code>
-class.  Given the frequency with which Android devices connect to unsecured
-wireless networks using WiFi, the use of secure networking is strongly
-encouraged for all applications.</p>
-
-<p>We have seen some applications use <a
-href="http://en.wikipedia.org/wiki/Localhost">localhost</a> network ports for
-handling sensitive IPC.  We discourage this approach since these interfaces are
-accessible by other applications on the device.  Instead, use an Android IPC
-mechanism where authentication is possible such as a Service and Binder.  (Even
-worse than using loopback is to bind to INADDR_ANY since then your application
-may receive requests from anywhere.  We’ve seen that, too.)</p>
-
-<p>Also, one common issue that warrants repeating is to make sure that you do
-not trust data downloaded from HTTP or other insecure protocols.  This includes
-validation of input in <code><a
-href="{@docRoot}reference/android/webkit/WebView.html">WebView</a></code> and
-any responses to intents issued against HTTP.</p>
-
-<h3>Using Telephony Networking</h3>
-
-<p>SMS is the telephony protocol most frequently used by Android developers.
-Developers should keep in mind that this protocol was primarily designed for
-user-to-user communication and is not well-suited for some application
-purposes. Due to the limitations of SMS, we strongly recommend the use of <a
-href="http://code.google.com/android/c2dm/">C2DM</a> and IP networking for
-sending data messages to devices.</p>
-
-<p>Many developers do not realize that SMS is not encrypted or strongly
-authenticated on the network or on the device.  In particular, any SMS receiver
-should expect that a malicious user may have sent the SMS to your application
--- do not rely on unauthenticated SMS data to perform sensitive commands.
-Also, you should be aware that SMS may be subject to spoofing and/or
-interception on the network.  On the Android-powered device itself, SMS
-messages are transmitted as Broadcast intents, so they may be read or captured
-by other applications that have the READ_SMS permission.</p>
-
-<a name="DynamicCode"></a>
-<h2>Dynamically Loading Code</h2>
-
-<p>We strongly discourage loading code from outside of the application APK.
-Doing so significantly increases the likelihood of application compromise due
-to code injection or code tampering.  It also adds complexity around version
-management and application testing.  Finally, it can make it impossible to
-verify the behavior of an application, so it may be prohibited in some
-environments.</p>
-
-<p>If your application does dynamically load code, the most important thing to
-keep in mind about dynamically loaded code is that it runs with the same
-security permissions as the application APK.  The user made a decision to
-install your application based on your identity, and they are expecting that
-you provide any code run within the application, including code that is
-dynamically loaded.</p>
-
-<p>The major security risk associated with dynamically loading code is that the
-code needs to come from a verifiable source. If the modules are included
-directly within your APK, then they cannot be modified by other applications.
-This is true whether the code is a native library or a class being loaded using
-<a href="{@docRoot}reference/dalvik/system/DexClassLoader.html">
-<code>DexClassLoader</code></a>.  We have seen many instances of applications
-attempting to load code from insecure locations, such as downloaded from the
-network over unencrypted protocols or from world writable locations such as
-external storage. These locations could allow someone on the network to modify
-the content in transit, or another application on a users device to modify the
-content, respectively.</p>
-
-
-<h3>Using WebView</h3>
-
-<p>Since WebView consumes web content that can include HTML and JavaScript,
-improper use can introduce common web security issues such as <a
-href="http://en.wikipedia.org/wiki/Cross_site_scripting">cross-site-scripting</a
-> (JavaScript injection).  Android includes a number of mechanisms to reduce
-the scope of these potential issues by limiting the capability of WebView to
-the minimum functionality required by your application.</p>
-
-<p>If your application does not directly use JavaScript within a <code><a
-href="{@docRoot}reference/android/webkit/WebView.html">WebView</a></code>, do
-not call
-<a href="{@docRoot}reference/android/webkit/WebSettings.html#setJavaScriptEnabled(boolean)">
-<code>setJavaScriptEnabled()</code></a>. We have seen this method invoked
-in sample code that might be repurposed in production application -- so
-remove it if necessary. By default, <code><a
-href="{@docRoot}reference/android/webkit/WebView.html">WebView</a></code> does
-not execute JavaScript so cross-site-scripting is not possible.</p>
-
-<p>Use <code><a
-href="{@docRoot}reference/android/webkit/WebView.html#addJavascriptInterface(java.lang.Object,%20java.lang.String)">addJavaScriptInterface()</a></code> with
-particular care because it allows JavaScript to invoke operations that are
-normally reserved for Android applications.  Only expose <code><a
-href="{@docRoot}reference/android/webkit/WebView.html#addJavascriptInterface(java.lang.Object,%20java.lang.String)">addJavaScriptInterface()</a></code> to
-sources from which all input is trustworthy.  If untrusted input is allowed,
-untrusted JavaScript may be able to invoke Android methods.  In general, we
-recommend only exposing <code><a
-href="{@docRoot}reference/android/webkit/WebView.html#addJavascriptInterface(java.lang.Object,%20java.lang.String)">addJavaScriptInterface()</a></code> to
-JavaScript that is contained within your application APK.</p>
-
-<p>Do not trust information downloaded over HTTP, use HTTPS instead.  Even if
-you are connecting only to a single website that you trust or control, HTTP is
-subject to <a
-href="http://en.wikipedia.org/wiki/Man-in-the-middle_attack">MiTM</a> attacks
-and interception of data.  Sensitive capabilities using <code><a
-href="{@docRoot}reference/android/webkit/WebView.html#addJavascriptInterface(java.lang.Object,%20java.lang.String)">addJavaScriptInterface()</a></code> should
-not ever be exposed to unverified script downloaded over HTTP. Note that even
-with the use of HTTPS,
-<code><a
-href="{@docRoot}reference/android/webkit/WebView.html#addJavascriptInterface(java.lang.Object,%20java.lang.String)">addJavaScriptInterface()</a></code>
-increases the attack surface of your application to include the server
-infrastructure and all CAs trusted by the Android-powered device.</p>
-
-<p>If your application accesses sensitive data with a <code><a
-href="{@docRoot}reference/android/webkit/WebView.html">WebView</a></code>, you
-may want to use the <code><a
-href="{@docRoot}reference/android/webkit/WebView.html#clearCache(boolean)">
-clearCache()</a></code> method to delete any files stored locally. Server side
-headers like no-cache can also be used to indicate that an application should
-not cache particular content.</p>
-
-<a name="Input"></a>
-<h2>Performing Input Validation</h2>
-
-<p>Insufficient input validation is one of the most common security problems
-affecting applications, regardless of what platform they run on. Android does
-have platform-level countermeasures that reduce the exposure of applications to
-input validation issues, you should use those features where possible. Also
-note that selection of type-safe languages tends to reduce the likelihood of
-input validation issues.  We strongly recommend building your applications with
-the Android SDK.</p>
-
-<p>If you are using native code, then any data read from files, received over
-the network, or received from an IPC has the potential to introduce a security
-issue.  The most common problems are <a
-href="http://en.wikipedia.org/wiki/Buffer_overflow">buffer overflows</a>, <a
-href="http://en.wikipedia.org/wiki/Double_free#Use_after_free">use after
-free</a>, and <a
-href="http://en.wikipedia.org/wiki/Off-by-one_error">off-by-one errors</a>.
-Android provides a number of technologies like ASLR and DEP that reduce the
-exploitability of these errors, but they do not solve the underlying problem.
-These can be prevented by careful handling of pointers and managing of
-buffers.</p>
-
-<p>Dynamic, string based languages such as JavaScript and SQL are also subject
-to input validation problems due to escape characters and <a
-href="http://en.wikipedia.org/wiki/Code_injection">script injection</a>.</p>
-
-<p>If you are using data within queries that are submitted to SQL Database or a
-Content Provider, SQL Injection may be an issue.  The best defense is to use
-parameterized queries, as is discussed in the ContentProviders section.
-Limiting permissions to read-only or write-only can also reduce the potential
-for harm related to SQL Injection.</p>
-
-<p>If you are using <code><a
-href="{@docRoot}reference/android/webkit/WebView.html">WebView</a></code>, then
-you must consider the possibility of XSS.  If your application does not
-directly use JavaScript within a <code><a
-href="{@docRoot}reference/android/webkit/WebView.html">WebView</a></code>, do
-not call setJavaScriptEnabled() and XSS is no longer possible. If you must
-enable JavaScript then the WebView section provides other security best
-practices.</p>
-
-<p>If you cannot use the security features above, we strongly recommend the use
-of well-structured data formats and verifying that the data conforms to the
-expected format. While blacklisting of characters or character-replacement can
-be an effective strategy, these techniques are error-prone in practice and
-should be avoided when possible.</p>
-
-<a name="UserData"></a>
-<h2>Handling User Data</h2>
-
-<p>In general, the best approach is to minimize use of APIs that access
-sensitive or personal user data. If you have access to data and can avoid
-storing or transmitting the information, do not store or transmit the data.
-Finally, consider if there is a way that your application logic can be
-implemented using a hash or non-reversible form of the data.  For example, your
-application might use the hash of an an email address as a primary key, to
-avoid transmitting or storing the email address.  This reduces the chances of
-inadvertently exposing data, and it also reduces the chance of attackers
-attempting to exploit your application.</p>
-
-<p>If your application accesses personal information such as passwords or
-usernames, keep in mind that some jurisdictions may require you to provide a
-privacy policy explaining your use and storage of that data.  So following the
-security best practice of minimizing access to user data may also simplify
-compliance.</p>
-
-<p>You should also consider whether your application might be inadvertently
-exposing personal information to other parties such as third-party components
-for advertising or third-party services used by your application. If you don't
-know why a component or service requires a personal information, don’t
-provide it.  In general, reducing the access to personal information by your
-application will reduce the potential for problems in this area.</p>
-
-<p>If access to sensitive data is required, evaluate whether that information
-must be transmitted to a server, or whether the operation can be performed on
-the client.  Consider running any code using sensitive data on the client to
-avoid transmitting user data.</p>
-
-<p>Also, make sure that you do not inadvertently expose user data to other
-application on the device through overly permissive IPC, world writable files,
-or network sockets. This is a special case of permission redelegation,
-discussed in the Requesting Permissions section.</p>
-
-<p>If a GUID is required, create a large, unique number and store it.  Do not
-use phone identifiers such as the phone number or IMEI which may be associated
-with personal information.  This topic is discussed in more detail in the <a
-href="http://android-developers.blogspot.com/2011/03/identifying-app-installations.html">Android Developer Blog</a>.</p>
-
-<p>Application developers should be careful writing to on-device logs.
-In Android, logs are a shared resource, and are available
-to an application with the
-<a href="{@docRoot}reference/android/Manifest.permission.html#READ_LOGS">
-<code>READ_LOGS</code></a> permission. Even though the phone log data
-is temporary and erased on reboot, inappropriate logging of user information
-could inadvertently leak user data to other applications.</p>
-
-
-<h3>Handling Credentials</h3>
-
-<p>In general, we recommend minimizing the frequency of asking for user
-credentials -- to make phishing attacks more conspicuous, and less likely to be
-successful.  Instead use an authorization token and refresh it.</p>
-
-<p>Where possible, username and password should not be stored on the device.
-Instead, perform initial authentication using the username and password
-supplied by the user, and then use a short-lived, service-specific
-authorization token.</p>
-
-<p>Services that will be accessible to multiple applications should be accessed
-using <code>
-<a href="{@docRoot}reference/android/accounts/AccountManager.html">
-AccountManager</a></code>. If possible, use the <code><a
-href="{@docRoot}reference/android/accounts/AccountManager.html">
-AccountManager</a></code> class to invoke a cloud-based service and do not store
-passwords on the device.</p>
-
-<p>After using <code><a
-href="{@docRoot}reference/android/accounts/AccountManager.html">
-AccountManager</a></code> to retrieve an Account, check the <code><a
-href="{@docRoot}reference/android/accounts/Account.html#CREATOR">CREATOR</a>
-</code> before passing in any credentials, so that you do not inadvertently pass
-credentials to the wrong application.</p>
-
-<p>If credentials are to be used only by applications that you create, then you
-can verify the application which accesses the <code><a
-href="{@docRoot}reference/android/accounts/AccountManager.html">
-AccountManager</a></code> using <code><a
-href="{@docRoot}reference/android/content/pm/PackageManager.html#checkSignatures(java.lang.String,%20java.lang.String)">checkSignature()</a></code>.
-Alternatively, if only one application will use the credential, you might use a
-{@link java.security.KeyStore} for
-storage.</p>
-
-<a name="Crypto"></a>
-<h2>Using Cryptography</h2>
-
-<p>In addition to providing data isolation, supporting full-filesystem
-encryption, and providing secure communications channels Android provides a
-wide array of algorithms for protecting data using cryptography.</p>
-
-<p>In general, try to use the highest level of pre-existing framework
-implementation that can  support your use case.  If you need to securely
-retrieve a file from a known location, a simple HTTPS URI may be adequate and
-require no knowledge of cryptography on your part.  If you need a secure
-tunnel, consider using
-<a href="{@docRoot}reference/javax/net/ssl/HttpsURLConnection.html">
-<code>HttpsURLConnection</code></a> or <code><a
-href="{@docRoot}reference/javax/net/ssl/SSLSocket.html">SSLSocket</a></code>,
-rather than writing your own protocol.</p>
-
-<p>If you do find yourself needing to implement your own protocol, we strongly
-recommend that you not implement your own cryptographic algorithms. Use
-existing cryptographic algorithms such as those in the implementation of AES or
-RSA provided in the <code><a
-href="{@docRoot}reference/javax/crypto/Cipher.html">Cipher</a></code> class.</p>
-
-<p>Use a secure random number generator (
-<a href="{@docRoot}reference/java/security/SecureRandom.html">
-<code>SecureRandom</code></a>) to initialize any cryptographic keys (<a
-href="{@docRoot}reference/javax/crypto/KeyGenerator.html">
-<code>KeyGenerator</code></a>). Use of a key that is not generated with a secure random
-number generator significantly weakens the strength of the algorithm, and may
-allow offline attacks.</p>
-
-<p>If you need to store a key for repeated use, use a mechanism like {@link java.security.KeyStore} that
-provides a mechanism for long term storage and retrieval of cryptographic
-keys.</p>
-
-<h2>Conclusion</h2>
-
-<p>Android provides developers with the ability to design applications with a
-broad range of security requirements.  These best practices will help you make
-sure that your application takes advantage of the security benefits provided by
-the platform.</p>
-
-<p>You can receive more information on these topics and discuss security best
-practices with other developers in the <a
-href="http://groups.google.com/group/android-security-discuss">Android Security
-Discuss</a> Google Group</p>
diff --git a/docs/html/guide/topics/sensors/sensors_motion.jd b/docs/html/guide/topics/sensors/sensors_motion.jd
index b6c3cb4..289c639 100644
--- a/docs/html/guide/topics/sensors/sensors_motion.jd
+++ b/docs/html/guide/topics/sensors/sensors_motion.jd
@@ -1,6 +1,5 @@
 page.title=Motion Sensors
-parent.title=Sensors
-parent.link=index.html
+page.tags="sensorevent","accelerometer","gyroscope","gravity","rotation"
 @jd:body
 
 <div id="qv-wrapper">
diff --git a/docs/html/guide/topics/sensors/sensors_position.jd b/docs/html/guide/topics/sensors/sensors_position.jd
index 869109b..55b282b 100644
--- a/docs/html/guide/topics/sensors/sensors_position.jd
+++ b/docs/html/guide/topics/sensors/sensors_position.jd
@@ -1,6 +1,5 @@
 page.title=Position Sensors
-parent.title=Sensors
-parent.link=index.html
+page.tags="sensorevent","orientation","proximity"
 @jd:body
 
 <div id="qv-wrapper">
diff --git a/docs/html/guide/topics/text/copy-paste.jd b/docs/html/guide/topics/text/copy-paste.jd
index 6c86f47..b34f0fa 100644
--- a/docs/html/guide/topics/text/copy-paste.jd
+++ b/docs/html/guide/topics/text/copy-paste.jd
@@ -1,4 +1,5 @@
 page.title=Copy and Paste
+page.tags="clipboardmanager","clipdata","input"
 @jd:body
 <div id="qv-wrapper">
     <div id="qv">
diff --git a/docs/html/guide/topics/text/creating-input-method.jd b/docs/html/guide/topics/text/creating-input-method.jd
index 7086824..7254594 100644
--- a/docs/html/guide/topics/text/creating-input-method.jd
+++ b/docs/html/guide/topics/text/creating-input-method.jd
@@ -1,5 +1,5 @@
 page.title=Creating an Input Method
-parent.title=Articles
+page.tags="ime","keyboard","inputmethodservice"
 @jd:body
 
 <div id="qv-wrapper">
diff --git a/docs/html/guide/topics/text/spell-checker-framework.jd b/docs/html/guide/topics/text/spell-checker-framework.jd
index 7f7a0b8..366f9cc 100644
--- a/docs/html/guide/topics/text/spell-checker-framework.jd
+++ b/docs/html/guide/topics/text/spell-checker-framework.jd
@@ -1,5 +1,5 @@
 page.title=Spelling Checker Framework
-parent.title=Articles
+page.tags="input","spellcheckerservice"
 @jd:body
 <div id="qv-wrapper">
 <div id="qv">
diff --git a/docs/html/guide/topics/ui/actionbar.jd b/docs/html/guide/topics/ui/actionbar.jd
index 3115c8f..db09e7d 100644
--- a/docs/html/guide/topics/ui/actionbar.jd
+++ b/docs/html/guide/topics/ui/actionbar.jd
@@ -1,4 +1,5 @@
 page.title=Action Bar
+page.tags="action bar","menu"
 parent.title=User Interface
 parent.link=index.html
 @jd:body
@@ -673,7 +674,7 @@
 view collapsible by adding {@code "collapseActionView"} to the {@code android:showAsAction}
 attribute, as shown in the XML above.</p>
 
-<p>Because the system will expand the action view when the user selects the item, so you
+<p>Because the system will expand the action view when the user selects the item, you
 <em>do not</em> need to respond to the item in the {@link
 android.app.Activity#onOptionsItemSelected onOptionsItemSelected} callback. The system still calls
 {@link android.app.Activity#onOptionsItemSelected onOptionsItemSelected()} when the user selects it,
diff --git a/docs/html/guide/topics/ui/binding.jd b/docs/html/guide/topics/ui/binding.jd
index e8b49d5..a4fd25c 100644
--- a/docs/html/guide/topics/ui/binding.jd
+++ b/docs/html/guide/topics/ui/binding.jd
@@ -10,13 +10,6 @@
     <li><a href="#FillingTheLayout">Filling the Layout with Data</a></li>
     <li><a href="#HandlingUserSelections">Handling User Selections</a></li>
   </ol>
-  
-  <h2>Related tutorials</h2>
-  <ol>
-    <li><a href="{@docRoot}resources/tutorials/views/hello-spinner.html">Spinner</a></li>
-    <li><a href="{@docRoot}resources/tutorials/views/hello-listview.html">List View</a></li>
-    <li><a href="{@docRoot}resources/tutorials/views/hello-gridview.html">Grid View</a></li>
-  </ol>
 </div>
 </div>
 
@@ -81,8 +74,8 @@
 </pre>
 
 <div class="special">
-<p>For more discussion on how to create different AdapterViews, read the following tutorials:
-<a href="{@docRoot}resources/tutorials/views/hello-spinner.html">Hello Spinner</a>,
-<a href="{@docRoot}resources/tutorials/views/hello-listview.html">Hello ListView</a>, and
-<a href="{@docRoot}resources/tutorials/views/hello-gridview.html">Hello GridView</a>.
+<p>For more discussion on how to create different AdapterViews, read the following guides:
+<a href="{@docRoot}guide/topics/ui/controls/spinner.html">Spinner</a>,
+<a href="{@docRoot}guide/topics/ui/layout/listview.html">List View</a>, and
+<a href="{@docRoot}guide/topics/ui/layout/gridview.html">Grid View</a>.
 </div>
diff --git a/docs/html/guide/topics/ui/controls/button.jd b/docs/html/guide/topics/ui/controls/button.jd
index 8d48e9c..41b67b7f 100644
--- a/docs/html/guide/topics/ui/controls/button.jd
+++ b/docs/html/guide/topics/ui/controls/button.jd
@@ -1,6 +1,5 @@
 page.title=Buttons
-parent.title=Input Controls
-parent.link=../controls.html
+page.tags="button","imagebutton"
 @jd:body
 
 <div id="qv-wrapper">
diff --git a/docs/html/guide/topics/ui/controls/checkbox.jd b/docs/html/guide/topics/ui/controls/checkbox.jd
index ea70980..99140b5 100644
--- a/docs/html/guide/topics/ui/controls/checkbox.jd
+++ b/docs/html/guide/topics/ui/controls/checkbox.jd
@@ -1,6 +1,5 @@
 page.title=Checkboxes
-parent.title=Input Controls
-parent.link=../controls.html
+
 @jd:body
 
 <div id="qv-wrapper">
diff --git a/docs/html/guide/topics/ui/controls/pickers.jd b/docs/html/guide/topics/ui/controls/pickers.jd
index cf90f1d..a0e7afb 100644
--- a/docs/html/guide/topics/ui/controls/pickers.jd
+++ b/docs/html/guide/topics/ui/controls/pickers.jd
@@ -1,6 +1,5 @@
-page.title= Pickers
-parent.title=Form Controls
-parent.link=controls-form.html
+page.title=Pickers
+page.tags="datepicker","timepicker"
 @jd:body
 
 <div id="qv-wrapper">
diff --git a/docs/html/guide/topics/ui/controls/radiobutton.jd b/docs/html/guide/topics/ui/controls/radiobutton.jd
index c96e576..d0c48ed 100644
--- a/docs/html/guide/topics/ui/controls/radiobutton.jd
+++ b/docs/html/guide/topics/ui/controls/radiobutton.jd
@@ -1,6 +1,5 @@
 page.title=Radio Buttons
-parent.title=Input Controls
-parent.link=../controls.html
+page.tags="radiobutton","radiogroup"
 @jd:body
 
 <div id="qv-wrapper">
diff --git a/docs/html/guide/topics/ui/controls/spinner.jd b/docs/html/guide/topics/ui/controls/spinner.jd
index deba3e6..85714b6 100644
--- a/docs/html/guide/topics/ui/controls/spinner.jd
+++ b/docs/html/guide/topics/ui/controls/spinner.jd
@@ -1,6 +1,5 @@
-page.title= Spinners
-parent.title=Input Controls
-parent.link=../controls.html
+page.title=Spinners
+page.tags="adapterview","spinneradapter"
 @jd:body
 
 <div id="qv-wrapper">
diff --git a/docs/html/guide/topics/ui/controls/text.jd b/docs/html/guide/topics/ui/controls/text.jd
index 654883d..c0b9873 100644
--- a/docs/html/guide/topics/ui/controls/text.jd
+++ b/docs/html/guide/topics/ui/controls/text.jd
@@ -1,6 +1,5 @@
 page.title=Text Fields
-parent.title=Input Controls
-parent.link=../controls.html
+page.tags="edittext","autocompletetextview"
 @jd:body
 
 <div id="qv-wrapper">
diff --git a/docs/html/guide/topics/ui/controls/togglebutton.jd b/docs/html/guide/topics/ui/controls/togglebutton.jd
index dd7634b..3119cd9 100644
--- a/docs/html/guide/topics/ui/controls/togglebutton.jd
+++ b/docs/html/guide/topics/ui/controls/togglebutton.jd
@@ -1,6 +1,5 @@
 page.title=Toggle Buttons
-parent.title=Input Controls
-parent.link=../controls.html
+page.tags="switch","togglebutton"
 @jd:body
 
 <div id="qv-wrapper">
diff --git a/docs/html/guide/topics/ui/custom-components.jd b/docs/html/guide/topics/ui/custom-components.jd
index be82dbc..703a5ce 100644
--- a/docs/html/guide/topics/ui/custom-components.jd
+++ b/docs/html/guide/topics/ui/custom-components.jd
@@ -1,6 +1,5 @@
 page.title=Custom Components
-parent.title=User Interface
-parent.link=index.html
+page.tags="view","widget"
 @jd:body
 
 <div id="qv-wrapper">
diff --git a/docs/html/guide/topics/ui/declaring-layout.jd b/docs/html/guide/topics/ui/declaring-layout.jd
index e229f23..ab674e6 100644
--- a/docs/html/guide/topics/ui/declaring-layout.jd
+++ b/docs/html/guide/topics/ui/declaring-layout.jd
@@ -1,6 +1,5 @@
 page.title=Layouts
-parent.title=User Interface
-parent.link=index.html
+page.tags="view","viewgroup"
 @jd:body
 
 <div id="qv-wrapper">
diff --git a/docs/html/guide/topics/ui/dialogs.jd b/docs/html/guide/topics/ui/dialogs.jd
index 3cfed13..7f48eac 100644
--- a/docs/html/guide/topics/ui/dialogs.jd
+++ b/docs/html/guide/topics/ui/dialogs.jd
@@ -1,4 +1,6 @@
 page.title=Dialogs
+page.tags="alertdialog","dialogfragment"
+
 @jd:body
 
 
diff --git a/docs/html/guide/topics/ui/drag-drop.jd b/docs/html/guide/topics/ui/drag-drop.jd
index cacdf5c..e989374 100644
--- a/docs/html/guide/topics/ui/drag-drop.jd
+++ b/docs/html/guide/topics/ui/drag-drop.jd
@@ -1,6 +1,5 @@
 page.title=Drag and Drop
-parent.title=User Interface
-parent.link=index.html
+page.tags="clipdata","dragevent","onlongclicklistener"
 @jd:body
 
 <div id="qv-wrapper">
@@ -750,7 +749,7 @@
         A{@link android.view.DragEvent#ACTION_DRAG_EXITED} event, it receives a new
         {@link android.view.DragEvent#ACTION_DRAG_LOCATION} event every time the touch point moves.
         The {@link android.view.DragEvent#getX()} and {@link android.view.DragEvent#getY()} methods
-        return the the X and Y coordinates of the touch point.
+        return the X and Y coordinates of the touch point.
     </li>
     <li>
         {@link android.view.DragEvent#ACTION_DRAG_EXITED}:  This event is sent to a listener that
@@ -995,4 +994,4 @@
         };
     };
 };
-</pre>
\ No newline at end of file
+</pre>
diff --git a/docs/html/guide/topics/ui/layout-objects.jd b/docs/html/guide/topics/ui/layout-objects.jd
deleted file mode 100644
index 1d15ad60..0000000
--- a/docs/html/guide/topics/ui/layout-objects.jd
+++ /dev/null
@@ -1,6 +0,0 @@
-page.title=Layouts
-parent.title=User Interface
-parent.link=index.html
-@jd:body
-
-<p>You should have been redirected to <a href="declaring-layout.html">Layouts</a>.</p>
\ No newline at end of file
diff --git a/docs/html/guide/topics/ui/layout/gridview.jd b/docs/html/guide/topics/ui/layout/gridview.jd
index 84c3dab..bc189c4 100644
--- a/docs/html/guide/topics/ui/layout/gridview.jd
+++ b/docs/html/guide/topics/ui/layout/gridview.jd
@@ -1,6 +1,5 @@
 page.title=Grid View
-parent.title=Layouts
-parent.link=layout-objects.html
+page.tags="gridview"
 @jd:body
 <div id="qv-wrapper">
 <div id="qv">
diff --git a/docs/html/guide/topics/ui/layout/linear.jd b/docs/html/guide/topics/ui/layout/linear.jd
index 8e33706..444dc71 100644
--- a/docs/html/guide/topics/ui/layout/linear.jd
+++ b/docs/html/guide/topics/ui/layout/linear.jd
@@ -1,6 +1,5 @@
 page.title=Linear Layout
-parent.title=Layouts
-parent.link=layout-objects.html
+page.tags="linearlayout"
 @jd:body
 
 <div id="qv-wrapper">
diff --git a/docs/html/guide/topics/ui/layout/listview.jd b/docs/html/guide/topics/ui/layout/listview.jd
index fee5292..6cdd725 100644
--- a/docs/html/guide/topics/ui/layout/listview.jd
+++ b/docs/html/guide/topics/ui/layout/listview.jd
@@ -1,6 +1,5 @@
 page.title=List View
-parent.title=Layouts
-parent.link=declaring-layout.html
+page.tags="listview"
 @jd:body
 <div id="qv-wrapper">
 <div id="qv">
diff --git a/docs/html/guide/topics/ui/layout/relative.jd b/docs/html/guide/topics/ui/layout/relative.jd
index 47f9417..65c5617 100644
--- a/docs/html/guide/topics/ui/layout/relative.jd
+++ b/docs/html/guide/topics/ui/layout/relative.jd
@@ -1,6 +1,5 @@
 page.title=Relative Layout
-parent.title=Layouts
-parent.link=layout-objects.html
+page.tags="relativelayout"
 @jd:body
 
 <div id="qv-wrapper">
diff --git a/docs/html/guide/topics/ui/menus.jd b/docs/html/guide/topics/ui/menus.jd
index 01d373e..dfcea52 100644
--- a/docs/html/guide/topics/ui/menus.jd
+++ b/docs/html/guide/topics/ui/menus.jd
@@ -834,7 +834,7 @@
 </ul>
 
 <p>You can create a group by nesting {@code &lt;item&gt;} elements inside a {@code &lt;group&gt;}
-element in your menu resource or by specifying a group ID with the the {@link
+element in your menu resource or by specifying a group ID with the {@link
 android.view.Menu#add(int,int,int,int) add()} method.</p>
 
 <p>Here's an example menu resource that includes a group:</p>
diff --git a/docs/html/guide/topics/ui/notifiers/index.jd b/docs/html/guide/topics/ui/notifiers/index.jd
deleted file mode 100644
index caf0df7..0000000
--- a/docs/html/guide/topics/ui/notifiers/index.jd
+++ /dev/null
@@ -1,92 +0,0 @@
-page.title=Notifications
-parent.title=User Interface
-parent.link=../index.html
-@jd:body
-
-<p>Several types of situations may arise that require you to notify the user 
-about an event that occurs in your application. Some events require the user to respond
-and others do not. For example:</p>
-<ul>
-  <li>When an event such as saving a file is complete, a small message
-should appear to confirm that the save was successful.</li>
-  <li>If the application is running in the background and needs the user's attention, 
-the application should create a notification that allows the user to respond at 
-his or her convenience.</li>
-  <li>If the application is 
-performing work that the user must wait for (such as loading a file), 
-the application should show a hovering progress wheel or bar.</li>
-</ul>
-
-<p>Each of these notification tasks can be achieved using a different technique:</p>
-<ul>
-  <li>A <a href="#Toast">Toast Notification</a>, for brief messages that come 
-  from the background.</li>
-  <li>A <a href="#StatusBar">Status Notification</a>, for persistent reminders 
-  that come from the background and request the user's response.</li>
-  <li>A <a href="#Dialog">Dialog Notification</a>, for Activity-related notifications.</li>
-</ul>
-
-<p>This document summarizes each of these techniques for notifying the user and includes
-links to full documentation.</p>
-
-
-<h2 id="Toast">Toast Notification</h2>
-
-<img src="{@docRoot}images/toast.png" alt="" style="float:right" />
-
-<p>A toast notification is a message that pops up on the surface of the window.
-It only fills the amount of space required for the message and the user's current
-activity remains visible and interactive. The notification automatically fades in and 
-out, and does not accept interaction events. Because a toast can be created from a background 
-{@link android.app.Service}, it appears even if the application isn't visible.</p>
-
-<p>A toast is best for short text messages, such as "File saved,"
-when you're fairly certain the user is paying attention 
-to the screen. A toast can not accept user interaction events; if you'd like
-the user to respond and take action, consider using a 
-<a href="#StatusBar">Status Notification</a> instead.</p>
-
-<p>For more information, refer to <a href="toasts.html">Toast Notifications</a>.</p>
-
-
-<h2 id="StatusBar">Status Notification</h2>
-
-<img src="{@docRoot}images/notifications_window.png" alt="" style="float:right; clear:right;" />
-
-<p>A status notification adds an icon to the system's status bar 
-(with an optional ticker-text message) and an expanded message in the "Notifications" window.
-When the user selects the expanded message, Android fires an 
-{@link android.content.Intent} that is defined by the notification (usually to launch an 
-{@link android.app.Activity}).
-You can also configure the notification to alert the user with a sound, a vibration, and flashing
-lights on the device.</p>
-
-<p>This kind of notification is ideal when your application is working in
-a background {@link android.app.Service} and needs to 
-notify the user about an event. If you need to alert the user about an event that occurs 
-while your Activity is still in focus, consider using a 
-<a href="#Dialog">Dialog Notification</a> instead.</p>
-
-<p>For more information, refer to 
-<a href="notifications.html">Status Notifications</a>.</p>
-
-
-<h2 id="Dialog">Dialog Notification</h2>
-
-<img src="{@docRoot}images/dialog_progress_spinning.png" alt="" style="float:right" />
-
-<p>A dialog is usually a small window that appears in front of the current Activity.
-The underlying Activity loses focus and the dialog accepts all user interaction. 
-Dialogs are normally used
-for notifications and short activities that directly relate to the application in progress.</p>
-
-<p>You should use a dialog when you need to show a progress bar or a short
-message that requires confirmation from the user (such as an alert with "OK" and "Cancel" buttons). 
-You can use also use dialogs as integral components
-in your application's UI and for other purposes besides notifications.
-For a complete discussion on all the available types of dialogs, 
-including its uses for notifications, refer to 
-<a href="{@docRoot}guide/topics/ui/dialogs.html">Dialogs</a>.</p>
-
-
-
diff --git a/docs/html/guide/topics/ui/settings.jd b/docs/html/guide/topics/ui/settings.jd
index 33e164b..d96447d 100644
--- a/docs/html/guide/topics/ui/settings.jd
+++ b/docs/html/guide/topics/ui/settings.jd
@@ -1,4 +1,6 @@
 page.title=Settings
+page.tags="preference","preferenceactivity","preferencefragment"
+
 @jd:body
 
 
diff --git a/docs/html/guide/topics/ui/ui-events.jd b/docs/html/guide/topics/ui/ui-events.jd
index 707d4b1..6d41b15 100644
--- a/docs/html/guide/topics/ui/ui-events.jd
+++ b/docs/html/guide/topics/ui/ui-events.jd
@@ -13,10 +13,6 @@
     <li><a href="#HandlingFocus">Handling Focus</a></li>
   </ol>
 
-  <h2>Related tutorials</h2>
-  <ol>
-    <li><a href="{@docRoot}resources/tutorials/views/hello-formstuff.html">Form Stuff</a></li>
-  </ol>
 </div>
 </div>
 
diff --git a/docs/html/guide/webapps/webview.jd b/docs/html/guide/webapps/webview.jd
index d2b2532..c87be06 100644
--- a/docs/html/guide/webapps/webview.jd
+++ b/docs/html/guide/webapps/webview.jd
@@ -33,11 +33,6 @@
   <li>{@link android.webkit.WebViewClient}</li>
 </ol>
 
-<h2>Related tutorials</h2>
-<ol>
-  <li><a href="{@docRoot}resources/tutorials/views/hello-webview.html">Web View</a></li>
-</ol>
-
 </div>
 </div>
 
diff --git a/docs/html/images/google/game_services.png b/docs/html/images/google/game_services.png
new file mode 100644
index 0000000..f62d7f0
--- /dev/null
+++ b/docs/html/images/google/game_services.png
Binary files differ
diff --git a/docs/html/images/google/gps-location.png b/docs/html/images/google/gps-location.png
new file mode 100644
index 0000000..c9acda1
--- /dev/null
+++ b/docs/html/images/google/gps-location.png
Binary files differ
diff --git a/docs/html/images/home/io-extended-2013.png b/docs/html/images/home/io-extended-2013.png
new file mode 100644
index 0000000..93989d4
--- /dev/null
+++ b/docs/html/images/home/io-extended-2013.png
Binary files differ
diff --git a/docs/html/images/home/io-logo-2013.png b/docs/html/images/home/io-logo-2013.png
index c95719e..1a200e1 100644
--- a/docs/html/images/home/io-logo-2013.png
+++ b/docs/html/images/home/io-logo-2013.png
Binary files differ
diff --git a/docs/html/index.jd b/docs/html/index.jd
index a0029b5..ce3d9ad 100644
--- a/docs/html/index.jd
+++ b/docs/html/index.jd
@@ -14,17 +14,18 @@
             <ul>
                 <li class="item carousel-home">
                     <div class="content-left col-10">
-                    <img src="{@docRoot}images/home/io-logo-2013.png" style="margin:40px 0 0">
+                    <a href="https://developers.google.com/events/io/io-extended/?utm_source=site&utm_medium=emb&utm_campaign=extended-android-site">
+                      <img src="{@docRoot}images/home/io-extended-2013.png" style="margin:90px 0 0">
+                    </a>
                     </div>
                     <div class="content-right col-5">
-                    <h1>Google I/O 2013</h1>
-                    <p>Android will be at Google I/O on May 15-17, 2013, with sessions covering a variety of topics
-                    such as design, performance, and how to extend your app with the latest Android features.
-                    Registration opens on March 13, 2013 at 7:00 AM PDT (GMT-7).</p>
-                    <p>For more information about event details and planned sessions,
-                    stay tuned to <a
-                    href="http://google.com/+GoogleDevelopers">+Google Developers</a>.</p>
-                    <p><a href="https://developers.google.com/events/io/" class="button">Register here</a></p>
+                    <h1>Google I/O Extended</h1>
+                    <p>Android will be at Google I/O on May 15-17, 2013, with sessions covering topics
+                    such as design, performance, and how to enhance your app with the latest Android features.</p>
+                    <p>Even if you can't make it there, you can experience the excitement and innovation of
+                    Google I/O remotely with Google I/O Extended.</p>
+                    <p><a href="https://developers.google.com/events/io/io-extended/?utm_source=site&utm_medium=emb&utm_campaign=extended-android-site"
+                    >Organize or attend an event near you &raquo;</a></p>
                     </div>
                 </li>
                 <li class="item carousel-home">
diff --git a/docs/html/sdk/1.0_r1/index.jd b/docs/html/sdk/1.0_r1/index.jd
index b380483..dea6620 100644
--- a/docs/html/sdk/1.0_r1/index.jd
+++ b/docs/html/sdk/1.0_r1/index.jd
@@ -1,5 +1,6 @@
 page.title=Android 1.0 SDK, release 1
 sdk.redirect=true
 sdk.redirect.path=index.html
+excludeFromSuggestions=true
 
 @jd:body
diff --git a/docs/html/sdk/1.0_r1/upgrading.jd b/docs/html/sdk/1.0_r1/upgrading.jd
index d6d5dc4..d6a7ed5 100644
--- a/docs/html/sdk/1.0_r1/upgrading.jd
+++ b/docs/html/sdk/1.0_r1/upgrading.jd
@@ -1,5 +1,6 @@
 page.title=Upgrading the SDK
 sdk.version=1.0_r1
+excludeFromSuggestions=true
 @jd:body
 
 <p>For the current SDK release, see the links under <strong>Current SDK Release</strong> in the side navigation.</p>
diff --git a/docs/html/sdk/1.0_r2/index.jd b/docs/html/sdk/1.0_r2/index.jd
index c29c148..8556e3c 100644
--- a/docs/html/sdk/1.0_r2/index.jd
+++ b/docs/html/sdk/1.0_r2/index.jd
@@ -1,5 +1,6 @@
 page.title=Android 1.0 SDK, release 2
 sdk.redirect=true
 sdk.redirect.path=index.html
+excludeFromSuggestions=true
 
 @jd:body
diff --git a/docs/html/sdk/1.0_r2/upgrading.jd b/docs/html/sdk/1.0_r2/upgrading.jd
index 409e30e..243950d 100644
--- a/docs/html/sdk/1.0_r2/upgrading.jd
+++ b/docs/html/sdk/1.0_r2/upgrading.jd
@@ -1,5 +1,6 @@
 page.title=Upgrading the SDK
 sdk.version=1.0_r2
+excludeFromSuggestions=true
 @jd:body
 
 <p>For the current SDK release, see the links under <strong>Current SDK Release</strong> in the side navigation.</p>
diff --git a/docs/html/sdk/1.1_r1/index.jd b/docs/html/sdk/1.1_r1/index.jd
index 63fe51d..44231ee 100644
--- a/docs/html/sdk/1.1_r1/index.jd
+++ b/docs/html/sdk/1.1_r1/index.jd
@@ -1,5 +1,6 @@
 page.title=Android 1.1 SDK, Release 1
 sdk.redirect=true
 sdk.redirect.path=index.html
+excludeFromSuggestions=true
 
 @jd:body
diff --git a/docs/html/sdk/1.1_r1/upgrading.jd b/docs/html/sdk/1.1_r1/upgrading.jd
index bc71149..840ae6b 100644
--- a/docs/html/sdk/1.1_r1/upgrading.jd
+++ b/docs/html/sdk/1.1_r1/upgrading.jd
@@ -1,5 +1,6 @@
 page.title=Upgrading the SDK
 sdk.version=1.1_r1
+excludeFromSuggestions=true
 @jd:body
 
 <!--
diff --git a/docs/html/sdk/1.5_r1/index.jd b/docs/html/sdk/1.5_r1/index.jd
index 60dfc14..7232f57 100644
--- a/docs/html/sdk/1.5_r1/index.jd
+++ b/docs/html/sdk/1.5_r1/index.jd
@@ -1,5 +1,6 @@
 page.title=Android 1.5 SDK, Release 1
 sdk.redirect=true
 sdk.redirect.path=index.html
+excludeFromSuggestions=true
 
 @jd:body
diff --git a/docs/html/sdk/1.5_r1/upgrading.jd b/docs/html/sdk/1.5_r1/upgrading.jd
index 0a12d62..0377069 100644
--- a/docs/html/sdk/1.5_r1/upgrading.jd
+++ b/docs/html/sdk/1.5_r1/upgrading.jd
@@ -1,5 +1,6 @@
 page.title=Upgrading the SDK
 sdk.version=1.5_r1
+excludeFromSuggestions=true
 @jd:body
 
 
diff --git a/docs/html/sdk/1.5_r2/index.jd b/docs/html/sdk/1.5_r2/index.jd
index 4fb99b6..fac4f13 100644
--- a/docs/html/sdk/1.5_r2/index.jd
+++ b/docs/html/sdk/1.5_r2/index.jd
@@ -1,5 +1,6 @@
 page.title=Android 1.5 SDK, Release 2
 sdk.redirect=true
 sdk.redirect.path=index.html
+excludeFromSuggestions=true
 
 @jd:body
diff --git a/docs/html/sdk/1.5_r2/upgrading.jd b/docs/html/sdk/1.5_r2/upgrading.jd
index bb5fc60..31b2358 100644
--- a/docs/html/sdk/1.5_r2/upgrading.jd
+++ b/docs/html/sdk/1.5_r2/upgrading.jd
@@ -1,5 +1,6 @@
 page.title=Upgrading the SDK
 sdk.version=1.5_r2
+excludeFromSuggestions=true
 @jd:body
 
 
diff --git a/docs/html/sdk/1.5_r3/index.jd b/docs/html/sdk/1.5_r3/index.jd
index eb10f5e..e8cfaa1 100644
--- a/docs/html/sdk/1.5_r3/index.jd
+++ b/docs/html/sdk/1.5_r3/index.jd
@@ -1,5 +1,6 @@
 page.title=Android 1.5 SDK, Release 3
 sdk.redirect=true
 sdk.redirect.path=index.html
+excludeFromSuggestions=true
 
 @jd:body
diff --git a/docs/html/sdk/1.5_r3/upgrading.jd b/docs/html/sdk/1.5_r3/upgrading.jd
index 18c1314..62b9a78 100644
--- a/docs/html/sdk/1.5_r3/upgrading.jd
+++ b/docs/html/sdk/1.5_r3/upgrading.jd
@@ -1,6 +1,7 @@
 page.title=Upgrading the SDK
 sdk.version=1.5
 sdk.rel.id=3
+excludeFromSuggestions=true
 
 @jd:body
 
diff --git a/docs/html/sdk/1.6_r1/index.jd b/docs/html/sdk/1.6_r1/index.jd
index e7f9112..671d1cd 100644
--- a/docs/html/sdk/1.6_r1/index.jd
+++ b/docs/html/sdk/1.6_r1/index.jd
@@ -1,5 +1,6 @@
 page.title=Android 1.6 SDK, Release 1
 sdk.redirect=true
 sdk.redirect.path=index.html
+excludeFromSuggestions=true
 
 @jd:body
diff --git a/docs/html/sdk/1.6_r1/upgrading.jd b/docs/html/sdk/1.6_r1/upgrading.jd
index 49535c9..e6dded0 100644
--- a/docs/html/sdk/1.6_r1/upgrading.jd
+++ b/docs/html/sdk/1.6_r1/upgrading.jd
@@ -1,5 +1,6 @@
 page.title=Upgrading the SDK
 sdk.version=1.6
+excludeFromSuggestions=true
 @jd:body
 
 
diff --git a/docs/html/sdk/OLD_RELEASENOTES.jd b/docs/html/sdk/OLD_RELEASENOTES.jd
index 6865db2..b7fd12f 100644
--- a/docs/html/sdk/OLD_RELEASENOTES.jd
+++ b/docs/html/sdk/OLD_RELEASENOTES.jd
@@ -1,4 +1,5 @@
 page.title=Release Notes for Older SDK Versions
+excludeFromSuggestions=true
 @jd:body
 
 <div class="special">
diff --git a/docs/html/sdk/RELEASENOTES.jd b/docs/html/sdk/RELEASENOTES.jd
index c7ece42..cbcbb12 100644
--- a/docs/html/sdk/RELEASENOTES.jd
+++ b/docs/html/sdk/RELEASENOTES.jd
@@ -1,4 +1,5 @@
 page.title=SDK Release Notes
+excludeFromSuggestions=true
 @jd:body
 
 <p>This document provides version-specific information about Android SDK
diff --git a/docs/html/sdk/download.jd b/docs/html/sdk/download.jd
index 8005009..4329102 100644
--- a/docs/html/sdk/download.jd
+++ b/docs/html/sdk/download.jd
@@ -1,4 +1,5 @@
 page.title=Download an Archived Android SDK
+excludeFromSuggestions=true
 hide_license_footer=true
 
 @jd:body
diff --git a/docs/html/sdk/index.jd b/docs/html/sdk/index.jd
index 6307c69..e1d7557 100644
--- a/docs/html/sdk/index.jd
+++ b/docs/html/sdk/index.jd
@@ -1,28 +1,29 @@
 page.title=Android SDK
+page.tags="download"
 page.template=sdk
 header.hide=1
 page.metaDescription=Download the official Android SDK to develop apps for Android-powered devices.
 
 
-sdk.linux32_bundle_download=adt-bundle-linux-x86.zip
-sdk.linux32_bundle_bytes=418614971
-sdk.linux32_bundle_checksum=24506708af221a887326c2a9ca9625dc
+sdk.linux32_bundle_download=adt-bundle-linux-x86-20130219.zip
+sdk.linux32_bundle_bytes=418664018
+sdk.linux32_bundle_checksum=e56ebb5c8eb84eb3227cf7c255373f4b
 
-sdk.linux64_bundle_download=adt-bundle-linux-x86_64.zip
-sdk.linux64_bundle_bytes=418889835
-sdk.linux64_bundle_checksum=464c1fbe92ea293d6b2292c27af5066a
+sdk.linux64_bundle_download=adt-bundle-linux-x86_64-20130219.zip
+sdk.linux64_bundle_bytes=418939098
+sdk.linux64_bundle_checksum=90cb420934170787938d0477c1a83a7f
 
-sdk.mac64_bundle_download=adt-bundle-mac-x86_64.zip
-sdk.mac64_bundle_bytes=390649300
-sdk.mac64_bundle_checksum=f557bc61a4bff466633037839771bffb
+sdk.mac64_bundle_download=adt-bundle-mac-x86_64-20130219.zip
+sdk.mac64_bundle_bytes=390697025
+sdk.mac64_bundle_checksum=b768c28f380c1846479664c4790e9c53
 
-sdk.win32_bundle_download=adt-bundle-windows-x86.zip
-sdk.win32_bundle_bytes=425429957
-sdk.win32_bundle_checksum=cca97f12904774385a57d542e70a490f
+sdk.win32_bundle_download=adt-bundle-windows-x86-20130219.zip
+sdk.win32_bundle_bytes=425487608
+sdk.win32_bundle_checksum=4a40039f28048e6d7b2440adf55b8321
 
-sdk.win64_bundle_download=adt-bundle-windows-x86_64.zip
-sdk.win64_bundle_bytes=425553759
-sdk.win64_bundle_checksum=c51679f4517e1c3ddefa1e662bbf17f6
+sdk.win64_bundle_download=adt-bundle-windows-x86_64-20130219.zip
+sdk.win64_bundle_bytes=425611626
+sdk.win64_bundle_checksum=891f79816b4d19042faab26d670f4f77
 
 
 
diff --git a/docs/html/sdk/installing/next.jd b/docs/html/sdk/installing/next.jd
deleted file mode 100644
index cb974a4..0000000
--- a/docs/html/sdk/installing/next.jd
+++ /dev/null
@@ -1,51 +0,0 @@
-page.title=Next Steps
-
-@jd:body
-
-
-<p>Now that you've installed the Android SDK, here are are a few ways to learn Android
-and start developing: </p>
-
-<h3>Start coding</h3>
-<ul>
-  <li>Follow the training class for <a
-href="{@docRoot}training/basics/firstapp/index.html">Building Your First App</a>.
-    <p>This class is an essential first step for new Android developers.</p>
-    <p>It gives you step by step instructions for building a simple app. You’ll learn how to
-create an Android project and run a debuggable version of the app. You'll also learn some
-fundamentals of Android app design, including how to build a simple user interface and handle user
-input.</p>
-</li>
-</ul>
-
-
-<h3>Learn how to design your app</h3>
-<ul>
-  <li>Learn the best practices for Android design and user experience by reading the Android <a
-href="{@docRoot}design/index.html">Design</a> guidelines.</li>
-</ul>
-
-
-<h3>Read up on the API framework</h3>
-<ul>
-  <li>Start reading about fundamental framework topics in the collection of <a
-href="{@docRoot}guide/components/index.html">API Guides</a>.</li>
-  <li>Browse the API specifications in the <a
-  href="{@docRoot}reference/packages.html">Reference</a>.</li>
-</ul>
-
-
-<h3>Explore the development tools</h3>
-<ul>
-  <li>Learn about developing an app with the Android Developer Tools plugin for Eclipse
-    and other tools from the <a
-  href="{@docRoot}tools/workflow/index.html">Workflow</a>.</li>
-</ul>
-
-
-<h3>Explore some code</h3>
-
-<ul>
-  <li>Browse the sample apps available from the Android SDK Manager. You'll find them in
-<code><em>&lt;sdk&gt;</em>/samples/<em>&lt;platform-version&gt;/</em></code>. </li>
-</ul>
diff --git a/docs/html/sdk/older_releases.jd b/docs/html/sdk/older_releases.jd
index bb274b6..94baa92 100644
--- a/docs/html/sdk/older_releases.jd
+++ b/docs/html/sdk/older_releases.jd
@@ -1,4 +1,5 @@
 page.title=SDK Archives
+excludeFromSuggestions=true
 @jd:body
 
 <p>This page provides a full list of archived and obsolete SDK releases,
diff --git a/docs/html/tools/debugging/ddms.jd b/docs/html/tools/debugging/ddms.jd
index 3d6324b..f641aad 100644
--- a/docs/html/tools/debugging/ddms.jd
+++ b/docs/html/tools/debugging/ddms.jd
@@ -54,7 +54,7 @@
   <p>When DDMS starts, it connects to <a href="{@docRoot}tools/help/adb.html">adb</a>.
   When a device is connected, a VM monitoring service is created between
   <code>adb</code> and DDMS, which notifies DDMS when a VM on the device is started or terminated. Once a VM
-  is running, DDMS retrieves the the VM's process ID (pid), via <code>adb</code>, and opens a connection to the
+  is running, DDMS retrieves the VM's process ID (pid), via <code>adb</code>, and opens a connection to the
   VM's debugger, through the adb daemon (adbd) on the device. DDMS can now talk to the VM using a
   custom wire protocol.</p>
 
diff --git a/docs/html/tools/debugging/debugging-ui.jd b/docs/html/tools/debugging/debugging-ui.jd
index 8ca5192..f927d08 100644
--- a/docs/html/tools/debugging/debugging-ui.jd
+++ b/docs/html/tools/debugging/debugging-ui.jd
@@ -60,7 +60,9 @@
 
   <p>The Hierarchy Viewer application allows you to debug and optimize your user interface. It
   provides a visual representation of the layout's View hierarchy (the View Hierarchy window)
-  and a magnified view of the display (the Pixel Perfect window).</p>
+  with performance information for each node in the layout,
+  and a magnified view of the display (the Pixel Perfect window) to closely examine the pixels
+  in your layout.</p>
 
   <p>Android <code>lint</code> is a static code scanning tool that helps you optimize the layouts and layout
   hierarchies of your applications, as well as detect other common coding problems. You can run it against your layout files or resource
diff --git a/docs/html/tools/device.jd b/docs/html/tools/device.jd
index 9bdaf47..c7827b2 100644
--- a/docs/html/tools/device.jd
+++ b/docs/html/tools/device.jd
@@ -30,7 +30,7 @@
 you don't yet have a device, check with the service providers in your area to determine which
 Android-powered devices are available.</p>
 
-<p>If you want a SIM-unlocked phone, then you might consider the Google Nexus S. To find a place
+<p>If you want a SIM-unlocked phone, then you might consider a Nexus phone. To find a place
 to purchase the Nexus S and other Android-powered devices, visit <a
 href="http://www.google.com/phone/detail/nexus-s">google.com/phone</a>.</p>
 
diff --git a/docs/html/tools/devices/emulator.jd b/docs/html/tools/devices/emulator.jd
index cee6473..fda233d 100644
--- a/docs/html/tools/devices/emulator.jd
+++ b/docs/html/tools/devices/emulator.jd
@@ -898,7 +898,7 @@
 to/from that port to the emulated device's host port. </p>
 
 <p>To set up the network redirection, you create a mapping of host and guest
-ports/addresses on the the emulator instance. There are two ways to set up
+ports/addresses on the emulator instance. There are two ways to set up
 network redirection: using emulator console commands and using the ADB tool, as
 described below. </p>
 
@@ -1254,7 +1254,7 @@
 <td>&nbsp;</td>
 </tr>
 <tr>
-  <td><code>power health &lt;percent&gt;</code></td>
+  <td><code>capacity &lt;percent&gt;</code></td>
   <td>Set remaining battery capacity state (0-100).</td>
 <td>&nbsp;</td>
 </tr>
diff --git a/docs/html/tools/extras/oem-usb.jd b/docs/html/tools/extras/oem-usb.jd
index 774fe87..87734a1 100644
--- a/docs/html/tools/extras/oem-usb.jd
+++ b/docs/html/tools/extras/oem-usb.jd
@@ -306,6 +306,10 @@
 <tr><td>MTK</td> <td><a
 href="http://online.mediatek.com/Public%20Documents/MTK_Android_USB_Driver.zip">http://online.mediatek.com/Public%20Documents/MTK_Android_USB_Driver.zip</a></td>
 </tr>
+<tr><td>Oppo</td> <td><a
+href="http://www.oppo.com/index.php?q=software/view&sw_id=631"
+>http://www.oppo.com/index.php?q=software/view&sw_id=631</a></td>
+</tr>
 <tr><td>Pantech</td>	<td><a
 href="http://www.isky.co.kr/cs/software/software.sky?fromUrl=index">http://www.isky.co.kr/cs/software/software.sky?fromUrl=index</a></td>
 </tr><tr><td>Pegatron</td>	<td><a
@@ -327,6 +331,9 @@
 href="http://www.yulong.com/product/product/product/downloadList.html#downListUL">http://www.yulong.com/product/product/product/downloadList.html#downListUL</a></td>
 </tr>
 
+<tr><td>Xiaomi</td>  <td><a
+href="http://www.xiaomi.com/c/driver/index.html">http://www.xiaomi.com/c/driver/index.html</a></td>
+</tr>
 <tr>
 <td>ZTE</td>	<td><a
 href="http://support.zte.com.cn/support/news/NewsDetail.aspx?newsId=1000442">http://support.zte.com.cn/support/news/NewsDetail.aspx?newsId=1000442</a></td></tr>
diff --git a/docs/html/tools/extras/support-library.jd b/docs/html/tools/extras/support-library.jd
index 08ac172..6475e3c 100644
--- a/docs/html/tools/extras/support-library.jd
+++ b/docs/html/tools/extras/support-library.jd
@@ -46,10 +46,33 @@
 <p>The sections below provide notes about successive releases of
 the Support Package, as denoted by revision number.</p>
 
-
 <div class="toggle-content opened">
   <p><a href="#" onclick="return toggleContent(this)">
     <img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-content-img" alt=""
+/>Support Package, revision 12</a> <em>(February 2013)</em>
+  </p>
+  <div class="toggle-content-toggleme">
+    <dl>
+      <dt>Changes for v4 support library:</dt>
+      <dd>
+        <ul>
+          <li>Improved interaction behavior for {@link android.support.v4.view.ViewPager}.</li>
+          <li>Fixed a bug that could cause {@link android.support.v4.view.ViewPager} to select the
+            wrong page.</li>
+          <li>Fixed use of {@link android.support.v4.view.ViewPager#removeView removeView()} method
+            during layout for {@link android.support.v4.view.ViewPager}.</li>
+          <li>Fixed issue with {@link android.support.v4.widget.SearchViewCompat} where using the
+            back button to dismiss does not clear the search text. This fix only applies to
+            host API levels 14 and higher.</li>
+        </ul>
+      </dd>
+    </dl>
+  </div>
+</div>
+
+<div class="toggle-content closed">
+  <p><a href="#" onclick="return toggleContent(this)">
+    <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-content-img" alt=""
 />Support Package, revision 11</a> <em>(November 2012)</em>
   </p>
   <div class="toggle-content-toggleme">
@@ -119,7 +142,7 @@
       <dt>Changes for v4 support library:</dt>
       <dd>
         <ul>
-          <li>Added support for notification features introduced in Android 4.1 (API Level 16) with
+          <li>Added support for notification features introduced in Android 4.1 (API level 16) with
           additions to {@link android.support.v4.app.NotificationCompat}.</li>
         </ul>
       </dd>
@@ -210,7 +233,7 @@
           <li>Fixed intent flags for {@link android.app.PendingIntent} objects generated
             by {@link android.support.v4.app.TaskStackBuilder}.</li>
           <li>Removed unused attributes from the gridlayout library projects to make sure
-            the library can be built with API Level 7 and higher.</li>
+            the library can be built with API level 7 and higher.</li>
           <li>Added {@code .classpath} and {@code .project} files for the gridlayout
             library project.</li>
         </ul>
diff --git a/docs/html/tools/help/index.jd b/docs/html/tools/help/index.jd
index 0f94395..bed14d1 100644
--- a/docs/html/tools/help/index.jd
+++ b/docs/html/tools/help/index.jd
@@ -1,4 +1,4 @@
-page.title=Tools
+page.title=Tools Help
 @jd:body
 
 
diff --git a/docs/html/tools/projects/index.jd b/docs/html/tools/projects/index.jd
index 6a49ac9..439d3be 100644
--- a/docs/html/tools/projects/index.jd
+++ b/docs/html/tools/projects/index.jd
@@ -68,12 +68,12 @@
     <code>src<em>/your/package/namespace/ActivityName</em>.java</code>. All other source code
      files (such as <code>.java</code> or <code>.aidl</code> files) go here as well.</dd>
 
-    <dt><code>bin</code></dt>
+    <dt><code>bin/</code></dt>
 
     <dd>Output directory of the build. This is where you can find the final <code>.apk</code> file and other
     compiled resources.</dd>
 
-    <dt><code>jni</code></dt>
+    <dt><code>jni/</code></dt>
 
     <dd>Contains native code sources developed using the Android NDK. For more information, see the
     <a href="{@docRoot}tools/sdk/ndk/index.html">Android NDK documentation</a>.</dd>
@@ -88,7 +88,7 @@
     <dd>This is empty. You can use it to store raw asset files. Files that you save here are
     compiled into an <code>.apk</code> file as-is, and the original filename is preserved. You can navigate this
     directory in the same way as a typical file system using URIs and read files as a stream of
-    bytes using the the {@link android.content.res.AssetManager}. For example, this is a good
+    bytes using the {@link android.content.res.AssetManager}. For example, this is a good
     location for textures and game data.</dd>
 
     <dt><code>res/</code></dt>
@@ -114,7 +114,7 @@
         <dt><code>drawable/</code></dt>
 
         <dd>For bitmap files (PNG, JPEG, or GIF), 9-Patch image files, and XML files that describe
-        Drawable shapes or a Drawable objects that contain multiple states (normal, pressed, or
+        Drawable shapes or Drawable objects that contain multiple states (normal, pressed, or
         focused). See the <a href=
         "{@docRoot}guide/topics/resources/drawable-resource.html">Drawable</a> resource type.</dd>
 
@@ -251,7 +251,7 @@
     code and resources as a standard Android project, stored in the same way. For example, source
     code in the library project can access its own resources through its <code>R</code> class.</p>
 
-    <p>However, a library project differs from an standard Android application project in that you
+    <p>However, a library project differs from a standard Android application project in that you
     cannot compile it directly to its own <code>.apk</code> and run it on an Android device.
     Similarly, you cannot export the library project to a self-contained JAR file, as you would do
     for a true library. Instead, you must compile the library indirectly, by referencing the
diff --git a/docs/html/tools/revisions/platforms.jd b/docs/html/tools/revisions/platforms.jd
index c1bc185..31cec0e 100644
--- a/docs/html/tools/revisions/platforms.jd
+++ b/docs/html/tools/revisions/platforms.jd
@@ -44,11 +44,28 @@
 SDK tools to revision 20 or later and restart the Android SDK Manager. If you do not,
 the Android 4.2 system components will not be available for download.</p>
 
-
 <div class="toggle-content opened">
 
   <p><a href="#" onclick="return toggleContent(this)">
     <img src="{@docRoot}assets/images/triangle-opened.png"
+class="toggle-content-img" alt="" />Revision 2</a> <em>(February 2013)</em>
+  </p>
+
+  <div class="toggle-content-toggleme">
+
+    <p>Maintenance update. The system version is 4.2.2.</p>
+    <dl>
+      <dt>Dependencies:</dt>
+      <dd>SDK Tools r21 or higher is required.</dd>
+    </dl>
+
+  </div>
+</div>
+
+<div class="toggle-content closed">
+
+  <p><a href="#" onclick="return toggleContent(this)">
+    <img src="{@docRoot}assets/images/triangle-closed.png"
 class="toggle-content-img" alt="" />Revision 1</a> <em>(November 2012)</em>
   </p>
 
diff --git a/docs/html/tools/sdk/OLD_RELEASENOTES.jd b/docs/html/tools/sdk/OLD_RELEASENOTES.jd
index 6865db2..b7fd12f 100644
--- a/docs/html/tools/sdk/OLD_RELEASENOTES.jd
+++ b/docs/html/tools/sdk/OLD_RELEASENOTES.jd
@@ -1,4 +1,5 @@
 page.title=Release Notes for Older SDK Versions
+excludeFromSuggestions=true
 @jd:body
 
 <div class="special">
diff --git a/docs/html/tools/sdk/RELEASENOTES.jd b/docs/html/tools/sdk/RELEASENOTES.jd
index c7ece42..cbcbb12 100644
--- a/docs/html/tools/sdk/RELEASENOTES.jd
+++ b/docs/html/tools/sdk/RELEASENOTES.jd
@@ -1,4 +1,5 @@
 page.title=SDK Release Notes
+excludeFromSuggestions=true
 @jd:body
 
 <p>This document provides version-specific information about Android SDK
diff --git a/docs/html/tools/sdk/addons.jd b/docs/html/tools/sdk/addons.jd
deleted file mode 100644
index 8c5e1ed..0000000
--- a/docs/html/tools/sdk/addons.jd
+++ /dev/null
@@ -1,9 +0,0 @@
-page.title=SDK Add-Ons
-
-@jd:body
-
-
-
-<p>A page that lists SDK addons and links to release notes. Links to dashboards etc.</p>
-
-
diff --git a/docs/html/tools/sdk/adt-notes.jd b/docs/html/tools/sdk/adt-notes.jd
deleted file mode 100644
index 291b543..0000000
--- a/docs/html/tools/sdk/adt-notes.jd
+++ /dev/null
@@ -1,5 +0,0 @@
-page.title=ADT Plugin for Eclipse
-sdk.redirect=true
-sdk.redirect.path=eclipse-adt.html
-
-@jd:body
diff --git a/docs/html/tools/sdk/adt_download.html b/docs/html/tools/sdk/adt_download.html
deleted file mode 100644
index 5ba2ef5..0000000
--- a/docs/html/tools/sdk/adt_download.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<html>
-<head>
-<meta http-equiv="refresh" content="0;url=http://developer.android.com/sdk/eclipse-adt.html">
-<title>Redirecting...</title>
-</head>
-<body>
-<p>You should be redirected. Please <a
-href="http://developer.android.com/sdk/eclipse-adt.html">click here</a>.</p>
-</body>
-</html>
\ No newline at end of file
diff --git a/docs/html/tools/sdk/download.jd b/docs/html/tools/sdk/download.jd
deleted file mode 100644
index af25609..0000000
--- a/docs/html/tools/sdk/download.jd
+++ /dev/null
@@ -1,93 +0,0 @@
-page.title=Download an Archived Android SDK
-hide_license_footer=true
-
-@jd:body
-
-<script type="text/javascript">
-  function verify() {
-    document.getElementById('download-button').disabled =
-!document.getElementById('checkbox').checked;
-  }
-  function submit() {
-    var location = window.location.href;
-    if (location.indexOf('?v=') != -1) {
-      var filename = location.substring(location.indexOf('=')+1,location.length);
-      if (document.getElementById('checkbox').checked) {
-        document.location = "http://dl.google.com/android/" + filename;
-      }
-      document.getElementById('click-download').setAttribute("href", "http://dl.google.com/android/"
-+ filename);
-      $("#terms-form").hide(500);
-      $("#next-steps").show(500);
-      document.getElementById('checkbox').disabled=true;
-      document.getElementById('download-button').disabled=true;
-    } else {
-      alert("You have not selected an SDK version. Please return to the SDK Archives page");
-    }
-  }
-</script>
-
-<div id="terms-form">
-    <p>Please carefully review the Android SDK License Agreement before downloading the SDK.
-The License Agreement constitutes a contract between you and Google with respect to your use of the
-SDK.</p>
-    <p class="note"><strong>Note:</strong> You must agree to this license agreement in order to
-download one of the archived SDKs, because these SDK packages contain Google software (whereas, the
-<a href="http://developer.android.com/sdk/index.html">current SDK</a> packages do not require a
-license agreement, because they contain only the open sourced SDK tools).</p>
-
-  <iframe id="terms" style="border:1px solid #888;margin:0 0 1em;height:400px;width:95%;"
-src="terms_body.html">
-  </iframe>
-
-  <p>
-    <input type="checkbox" id="checkbox" onclick="verify()" />
-    <label for="checkbox">I agree to the terms of the Android SDK License Agreement.</label>
-  </p>
-  <p>
-    <input type="submit" value="Download" id="download-button" disabled="disabled"
-onclick="submit()" />
-  </p>
-  <p>
-  <script language="javascript">
-    var loc = window.location.href;
-    if (loc.indexOf('?v=') != -1) {
-      var filename = loc.substring(loc.indexOf('=')+1,loc.length).replace(/</g,"&lt;").replace(/>/g,"&gt;");
-      document.write("File: " + filename);
-    }
-  </script>
-  </p>
-</div><!-- end terms-form -->
-
-<noscript>
-  <p><strong>Please enable Javascript in your browser in order to agree to the terms and download
-the SDK.</strong></p>
-</noscript>
-
-<div class="special" id="next-steps" style="display:none">
-  <p>Your download should be underway. If not, <a id="click-download">click here to start the
-download</a>.</p>
-  <p>Beware that you've just downloaded a very old version of the Android SDK, which is not
-recommended. We no longer maintain documentation about how to install these archived SDKs nor
-support the tools contained within.</p>
-  <p>We recommend that you instead download the latest <a
-href="http://developer.android.com/sdk/index.html">Android SDK starter package</a>, which includes
-the latest SDK tools and allows you to develop against any version of the Android platform, back to
-Android 1.1.</p>
-</div>
-
-<script type="text/javascript">
-  var loc = window.location.href;
-  var filename = loc.substring(loc.indexOf('=')+1,loc.length);
-  version = filename.substring(filename.indexOf('.')-1,filename.lastIndexOf('.'));
-  $(".addVersionPath").each(function(i) {
-    var oldHref = $(this).attr("href");
-    $(this).attr({href: "/sdk/" + version + "/" + oldHref});
-  });
-</script>
-
-
-
-
-
-
diff --git a/docs/html/tools/sdk/eclipse-adt.jd b/docs/html/tools/sdk/eclipse-adt.jd
index 4adb7b2..a3f53bbe 100644
--- a/docs/html/tools/sdk/eclipse-adt.jd
+++ b/docs/html/tools/sdk/eclipse-adt.jd
@@ -69,7 +69,7 @@
       <li>Java 1.6 or higher is required for ADT 21.1.0.</li>
       <li>Eclipse Helios (Version 3.6.2) or higher is required for ADT 21.1.0.</li>
       <li>ADT 21.1.0 is designed for use with <a href="{@docRoot}tools/sdk/tools-notes.html">SDK
-      Tools r21.1.0</a>. If you haven't already installed SDK Tools r21.1.0 into your SDK, use the
+      Tools r21.1</a>. If you haven't already installed SDK Tools r21.1 into your SDK, use the
       Android SDK Manager to do so.</li>
     </ul>
   </dd>
diff --git a/docs/html/tools/sdk/libraries.jd b/docs/html/tools/sdk/libraries.jd
deleted file mode 100644
index 9e47c4a..0000000
--- a/docs/html/tools/sdk/libraries.jd
+++ /dev/null
@@ -1,9 +0,0 @@
-page.title=Libraries
-
-@jd:body
-
-
-
-<p>A page that lists libraries and links to release notes. Links to dashboards etc.</p>
-
-
diff --git a/docs/html/tools/sdk/ndk/1.5_r1/index.jd b/docs/html/tools/sdk/ndk/1.5_r1/index.jd
index 4c70a8a..2f6764b 100644
--- a/docs/html/tools/sdk/ndk/1.5_r1/index.jd
+++ b/docs/html/tools/sdk/ndk/1.5_r1/index.jd
@@ -1,6 +1,7 @@
 page.title=Android 1.5 NDK, Release 1
 sdk.redirect=true
 sdk.redirect.path=ndk/index.html
+excludeFromSuggestions=true
 
 @jd:body
 
diff --git a/docs/html/tools/sdk/ndk/1.6_r1/index.jd b/docs/html/tools/sdk/ndk/1.6_r1/index.jd
index 090dcdc..1dc5b6f 100644
--- a/docs/html/tools/sdk/ndk/1.6_r1/index.jd
+++ b/docs/html/tools/sdk/ndk/1.6_r1/index.jd
@@ -1,5 +1,6 @@
 page.title=Android 1.6 NDK, Release 1
 sdk.redirect=true
 sdk.redirect.path=ndk/index.html
+excludeFromSuggestions=true
 
 @jd:body
diff --git a/docs/html/tools/sdk/ndk/index.jd b/docs/html/tools/sdk/ndk/index.jd
index cb4954b..74caaf4 100644
--- a/docs/html/tools/sdk/ndk/index.jd
+++ b/docs/html/tools/sdk/ndk/index.jd
@@ -1,17 +1,29 @@
 ndk=true
 page.template=sdk
 
-ndk.win_download=android-ndk-r8d-windows.zip
-ndk.win_bytes=327014028
-ndk.win_checksum=d78ec3d4ec15ad3b18b9f488a5763c23
+ndk.mac64_download=android-ndk-r8e-darwin-x86_64.tar.bz2
+ndk.mac64_bytes=508419298
+ndk.mac64_checksum=efac96fab20e6ddb1311d6ba5648ce72
 
-ndk.mac_download=android-ndk-r8d-darwin-x86.tar.bz2
-ndk.mac_bytes=308328942
-ndk.mac_checksum=5cd9ef9fb7e03943ee8c9e147e42e571
+ndk.mac32_download=android-ndk-r8e-darwin-x86.tar.bz2
+ndk.mac32_bytes=496238878
+ndk.mac32_checksum=e17e707464c45c0d5615e4d0ae6a5cf7
 
-ndk.linux_download=android-ndk-r8d-linux-x86.tar.bz2
-ndk.linux_bytes=254644383
-ndk.linux_checksum=e1fa0379a3feb59f2f0865f1a90bd382
+ndk.linux64_download=android-ndk-r8e-linux-x86_64.tar.bz2
+ndk.linux64_bytes=466853553
+ndk.linux64_checksum=fa812352956067e7a9eefc0274675e9a
+
+ndk.linux32_download=android-ndk-r8e-linux-x86.tar.bz2
+ndk.linux32_bytes=461526099
+ndk.linux32_checksum=26d774b0884bcd98de08eb4de41ab532
+
+ndk.win64_download=android-ndk-r8e-windows-x86_64.zip
+ndk.win64_bytes=461298980
+ndk.win64_checksum=11eb99b3b56fc86d9d231ebff5c41db3
+
+ndk.win32_download=android-ndk-r8e-windows-x86.zip
+ndk.win32_bytes=434701805
+ndk.win32_checksum=fb41ed2bff5610b14a7b6f085ab86213
 
 page.title=Android NDK
 @jd:body
@@ -250,6 +262,222 @@
 <div class="toggle-content opened">
   <p><a href="#" onclick="return toggleContent(this)">
     <img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-content-img"
+      alt="">Android NDK, Revision 8e</a> <em>(March 2013)</em>
+  </p>
+
+  <div class="toggle-content-toggleme">
+    <dl>
+      <dt>Important changes:</dt>
+      <dd>
+        <ul>
+          <li>Added 64-bit host toolchain set (package name suffix {@code *-x86_64.*}). For more
+            information, see {@code CHANGES.HTML} and {@code NDK-BUILD.html}.</li>
+          <li>Added Clang 3.2 compiler. GCC 4.6 is still the default. For information on using the
+            Clang compiler, see {@code CHANGES.HTML}.</li>
+          <li>Added static code analyzer for Linux/MacOSX hosts. For information on using the
+            analyzer, see {@code CHANGES.HTML}.</li>
+          <li>Added MCLinker for Linux/MacOSX hosts as an experimental feature. The {@code ld.gold}
+            linker is the default where available, so you must explicitly enable it. For more
+            information, see {@code CHANGES.HTML}.</li>
+          <li>Updated ndk-build to use topological sort for module dependencies, which means the
+            build automatically sorts out the order of libraries specified in
+            {@code LOCAL_STATIC_LIBRARIES}, {@code LOCAL_WHOLE_STATIC_LIBRARIES} and
+            {@code LOCAL_SHARED_LIBRARIES}. For more information, see {@code CHANGES.HTML}.
+            (<a href="http://code.google.com/p/android/issues/detail?id=39378">Issue 39378</a>)</li>
+        </ul>
+      </dd>
+
+      <dt>Important bug fixes:</dt>
+      <dd>
+        <ul>
+          <li>Fixed build script to build all toolchains in {@code -O2}. Toolchains in previous
+            releases were incorrectly built without optimization.</li>
+          <li>Fixed build script which unconditionally builds Clang/llvm for MacOSX in 64-bit.</li>
+          <li>Fixed GCC 4.6/4.7 internal compiler error:
+            {@code gen_thumb_movhi_clobber at config/arm/arm.md:5832}.
+            (<a href="http://code.google.com/p/android/issues/detail?id=52732">Issue 52732</a>)</li>
+          <li>Fixed build problem where GCC/ARM 4.6/4.7 fails to link code using 64-bit atomic
+            built-in functions.
+            (<a href="http://code.google.com/p/android/issues/detail?id=41297">Issue 41297</a>)</li>
+          <li>Fixed GCC 4.7 linker DIV usage mismatch errors.
+          (<a href="http://sourceware.org/ml/binutils/2012-12/msg00202.html">Sourceware Issue</a>)
+          <li>Fixed GCC 4.7 internal compiler error {@code build_data_member_initialization, at
+            cp/semantics.c:5790}.</li>
+          <li>Fixed GCC 4.7 internal compiler error {@code redirect_eh_edge_1, at tree-eh.c:2214}.
+            (<a href="http://code.google.com/p/android/issues/detail?id=52909">Issue 52909</a>)</li>
+          <li>Fixed a GCC 4.7 segfault.
+            (<a href="http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55245">GCC Issue</a>)</li>
+          <li>Fixed {@code &lt;chrono&gt;} clock resolution and enabled {@code steady_clock}.
+            (<a href="http://code.google.com/p/android/issues/detail?id=39680">Issue 39680</a>)</li>
+          <li>Fixed toolchain to enable {@code _GLIBCXX_HAS_GTHREADS} for GCC 4.7 libstdc++.
+            (<a href="http://code.google.com/p/android/issues/detail?id=41770">Issue 41770</a>,
+             <a href="http://code.google.com/p/android/issues/detail?id=41859">Issue 41859</a>)</li>
+          <li>Fixed problem with the X86 MXX/SSE code failing to link due to missing
+            {@code posix_memalign}.
+            (<a href="https://android-review.googlesource.com/#/c/51872">Change 51872</a>)</li>
+          <li>Fixed GCC4.7/X86 segmentation fault in {@code i386.c}, function
+            {@code distance_non_agu_define_in_bb()}.
+            (<a href="https://android-review.googlesource.com/#/c/50383">Change 50383</a>)</li>
+          <li>Fixed GCC4.7/X86 to restore earlier {@code cmov} behavior.
+            (<a href="http://gcc.gnu.org/viewcvs?view=revision&revision=193554">GCC Issue</a>)</li>
+          <li>Fixed handling NULL return value of {@code setlocale()} in libstdc++/GCC4.7.
+            (<a href="http://code.google.com/p/android/issues/detail?id=46718">Issue 46718</a>)
+          <li>Fixed {@code ld.gold} runtime undefined reference to {@code __exidx_start} and
+            {@code __exidx_start_end}.
+            (<a href="https://android-review.googlesource.com/#/c/52134">Change 52134</a>)</li>
+          <li>Fixed Clang 3.1 internal compiler error when using Eigen library.
+            (<a href="http://code.google.com/p/android/issues/detail?id=41246">Issue 41246</a>)</li>
+          <li>Fixed Clang 3.1 internal compiler error including {@code &lt;chrono&gt;} in C++11 mode.
+            (<a href="http://code.google.com/p/android/issues/detail?id=39600">Issue 39600</a>)</li>
+          <li>Fixed Clang 3.1 internal compiler error when generating object code for a method
+            call to a uniform initialized {@code rvalue}.
+            (<a href="http://code.google.com/p/android/issues/detail?id=41387">Issue 41387</a>)</li>
+          <li>Fixed Clang 3.1/X86 stack realignment.
+            (<a href="https://android-review.googlesource.com/#/c/52154">Change 52154</a>)</li>
+          <li>Fixed problem with GNU Debugger (GDB) SIGILL when debugging on Android 4.1.2.
+            (<a href="http://code.google.com/p/android/issues/detail?id=40941">Issue 40941</a>)</li>
+          <li>Fixed problem where GDB cannot set {@code source:line} breakpoints when symbols contain
+            long, indirect file paths.
+            (<a href="http://code.google.com/p/android/issues/detail?id=42448">Issue 42448</a>)</li>
+          <li>Fixed GDB {@code read_program_header} for MIPS PIE executables.
+            (<a href="https://android-review.googlesource.com/#/c/49592">Change 49592</a>)</li>
+          <li>Fixed {@code STLport} segmentation fault in {@code uncaught_exception()}.
+            (<a href="https://android-review.googlesource.com/#/c/50236">Change 50236</a>)</li>
+          <li>Fixed {@code STLport} bus error in exception handling due to unaligned access of
+            {@code DW_EH_PE_udata2}, {@code DW_EH_PE_udata4}, and {@code DW_EH_PE_udata8}.</li>
+          <li>Fixed Gabi++ infinite recursion problem with {@code nothrow new[]} operator.
+            (<a href="http://code.google.com/p/android/issues/detail?id=52833">Issue 52833</a>)</li>
+          <li>Fixed Gabi++ wrong offset to exception handler pointer.
+            (<a href="https://android-review.googlesource.com/#/c/53446">Change 53446</a>)</li>
+          <li>Removed Gabi++ redundant free on exception object
+            (<a href="https://android-review.googlesource.com/#/c/53447">Change 53447</a>)</li>
+        </ul>
+      </dd>
+
+      <dt>Other bug fixes:</dt>
+      <dd>
+        <ul>
+          <li>Fixed NDK headers:
+            <ul>
+              <li>Removed redundant definitions of {@code size_t}, {@code ssize_t}, and
+                {@code ptrdiff_t}.</li>
+              <li>Fixed MIPS and ARM {@code fenv.h} header.</li>
+              <li>Fixed {@code stddef.h} to not redefine {@code offsetof} since it already exists
+                in the toolchain.</li>
+              <li>Fixed {@code elf.h} to contain {@code Elf32_auxv_t} and {@code Elf64_auxv_t}.
+                (<a href="http://code.google.com/p/android/issues/detail?id=38441">Issue 38441</a>)
+                </li>
+              <li>Fixed the {@code #ifdef} C++ definitions in the
+                {@code OpenSLES_AndroidConfiguration.h} header file.
+                (<a href="http://code.google.com/p/android/issues/detail?id=53163">Issue 53163</a>)
+                </li>
+            </ul>
+          </li>
+          <li>Fixed {@code STLport} to abort after out of memory error instead of silently exiting.
+            </li>
+          <li>Fixed system and Gabi++ headers to be able to compile with API level 8 and lower.</li>
+          <li>Fixed {@code cpufeatures} to not parse {@code /proc/self/auxv}.
+            (<a href="http://code.google.com/p/android/issues/detail?id=43055">Issue 43055</a>)</li>
+          <li>Fixed {@code ld.gold} to not depend on host libstdc++ and on Windows platforms,
+            to not depend on the {@code libgcc_sjlj_1.dll} library.</li>
+          <li>Fixed Clang 3.1 which emits inconsistent register list in {@code .vsave} and fails
+            assembler.
+            (<a href="https://android-review.googlesource.com/#/c/49930">Change 49930</a>)</li>
+          <li>Fixed Clang 3.1 to be able to compile libgabi++ and pass the {@code test-stlport}
+            tests for MIPS build targets.
+            (<a href="https://android-review.googlesource.com/#/c/51961">Change 51961</a>)</li>
+          <li>Fixed Clang 3.1 to only enable exception by default for C++, not for C.</li>
+          <li>Fixed several issues in Clang 3.1 to pass most GNU exception tests.</li>
+          <li>Fixed scripts {@code clang} and {@code clang++} in standalone NDK compiler to detect
+            {@code -cc1} and to not specify {@code -target} when found.</li>
+          <li>Fixed {@code ndk-build} to observe {@code NDK_APP_OUT} set in {@code Application.mk}.
+            </li>
+          <li>Fixed X86 {@code libc.so} and {@code lib.a} which were missing the {@code sigsetjmp}
+            and {@code siglongjmp} functions already declared in {@code setjmp.h}.
+            (<a href="http://code.google.com/p/android/issues/detail?id=19851">Issue 19851</a>)</li>
+          <li>Patched GCC 4.4.3/4.6/4.7 libstdc++ to work with Clang in C++ 11.
+            (<a href="http://clang.llvm.org/cxx_status.html">Clang Issue</a>)</li>
+          <li>Fixed cygwin path in argument passed to {@code HOST_AWK}.</li>
+          <li>Fixed {@code ndk-build} script warning in windows when running from project's JNI
+            directory.
+            (<a href="http://code.google.com/p/android/issues/detail?id=40192">Issue 40192</a>)</li>
+          <li>Fixed problem where the {@code ndk-build} script does not build if makefile has
+            trailing whitespace in the {@code LOCAL_PATH} definition.
+            (<a href="http://code.google.com/p/android/issues/detail?id=42841">Issue 42841</a>)</li>
+        </ul>
+      </dd>
+
+      <dt>Other changes:</dt>
+      <dd>
+        <ul>
+          <li>Enabled threading support in GCC/MIPS toolchain.</li>
+          <li>Updated GCC exception handling helpers {@code __cxa_begin_cleanup} and
+            {@code __cxa_type_match} to have <em>default</em> visibility from the previous
+            <em>hidden</em> visibility in GNU libstdc++. For more information, see
+            {@code CHANGES.HTML}.</li>
+          <li>Updated build scripts so that Gabi++ and STLport static libraries are now built with
+            hidden visibility except for exception handling helpers.</li>
+          <li>Updated build so that {@code STLport} is built for ARM in Thumb mode.</li>
+          <li>Added support for {@code std::set_new_handler} in Gabi++.
+            (<a href="http://code.google.com/p/android/issues/detail?id=52805">Issue 52805</a>)</li>
+          <li>Enabled {@code FUTEX} system call in GNU libstdc++.</li>
+          <li>Updated {@code ndk-build} so that it  no longer copies prebuilt static library to
+            a project's {@code obj/local/&lt;abi&gt;/} directory.
+            (<a href="http://code.google.com/p/android/issues/detail?id=40302">Issue 40302</a>)</li>
+          <li>Removed {@code __ARM_ARCH_5*__} from ARM {@code toolchains/*/setup.mk} script.
+            (<a href="http://code.google.com/p/android/issues/detail?id=21132">Issue 21132</a>)</li>
+          <li>Built additional GNU libstdc++ libraries in thumb for ARM.</li>
+          <li>Enabled MIPS floating-point {@code madd/msub/nmadd/nmsub/recip/rsqrt}
+            instructions with 32-bit FPU.</li>
+          <li>Enabled graphite loop optimizer in GCC 4.6 and 4.7 to allow more optimizations:
+            {@code -fgraphite}, {@code -fgraphite-identity}, {@code -floop-block}, {@code -floop-flatten},
+            {@code -floop-interchange}, {@code -floop-strip-mine}, {@code -floop-parallelize-all},
+            and {@code -ftree-loop-linear}.
+            (<a href="http://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html">info</a>)</li>
+          <li>Enabled {@code polly} for Clang 3.1 on Linux and Max OS X 32-bit hosts which analyzes
+            and optimizes memory access. (<a href="http://polly.llvm.org">info</a>)</li>
+          <li>Enabled {@code -flto} in GCC 4.7, 4.6, Clang 3.2 and Clang 3.1 on linux (Clang LTO
+            via LLVMgold.so). MIPS compiler targets are not supported because {@code ld.gold}
+            is not available.</li>
+          <li>Enabled {@code --plugin} and {@code --plugin-opt} for {@code ld.gold} in GCC 4.6/4.7.
+            </li>
+          <li>Enabled {@code --text-reorder} for {@code ld.gold} in GCC 4.7.</li>
+          <li>Configured GNU libstdc++ with {@code _GLIBCXX_USE_C99_MATH} which undefines the
+            {@code isinf} script in the bionic header. For more information, see
+            {@code CHANGES.html}.</li>
+          <li>Added {@code APP_LDFLAGS} to the build scripts. For more information, see
+            {@code ANDROID-MK.html}.</li>
+          <li>Updated build scripts to allow {@code NDK_LOG=0} to disable the {@code NDK_LOG}.</li>
+          <li>Updated build scripts to allow {@code NDK_HOST_32BIT=0} to disable the host developer
+            environment 32-bit toolchain.</li>
+          <li>Changed the default GCC/X86 flags {@code -march=} and {@code -mtune=} from
+            {@code pentiumpro} and {@code generic} to {@code i686} and {@code atom}.</li>
+          <li>Enhanced toolchain build scripts:
+            <ul>
+              <li>Fixed a race condition in {@code build-gcc.sh} for the {@code mingw} build type
+                which was preventing a significant amount of parallel build processing.</li>
+              <li>Updated {@code build-gabi++.sh} and {@code build-stlport.sh} so they can now run
+                from the NDK package.
+                (<a href="http://code.google.com/p/android/issues/detail?id=52835">Issue 52835</a>)
+                </li>
+              <li>Fixed {@code run-tests.sh} in the {@code MSys} utilities collection.</li>
+              <li>Improved 64-bit host toolchain and Canadian Cross build support.</li>
+              <li>Updated {@code build-mingw64-toolchain.sh} script to more recent version.</li>
+              <li>Added option to build {@code libgnustl_static.a} and {@code stlport_static.a}
+                without hidden visibility.</li>
+            </ul>
+          </li>
+        </ul>
+
+      </dd>
+    </dl>
+  </div>
+</div>
+
+
+<div class="toggle-content closed">
+  <p><a href="#" onclick="return toggleContent(this)">
+    <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-content-img"
       alt="">Android NDK, Revision 8d</a> <em>(December 2012)</em>
   </p>
 
@@ -769,7 +997,7 @@
       <dd>
         <ul>
           <li>Added GCC 4.6 toolchain ({@code binutils} 2.21 with {@code gold} and GDB 7.3.x) to
-co-exist with the original GCC 4.4.3 toolchain ({@code binutils} 2.19 and GDB 6.6).</p>
+co-exist with the original GCC 4.4.3 toolchain ({@code binutils} 2.19 and GDB 6.6).
             <ul>
               <li>GCC 4.6 is now the default toolchain. You may set {@code
 NDK_TOOLCHAIN_VERSION=4.4.3} in {@code Application.mk} to select the original one.</li>
@@ -816,8 +1044,9 @@
 following options:
 <pre>
 LOCAL_DISABLE_NO_EXECUTE=true  # disable "--noexecstack" and "-z noexecstack"
-DISABLE_RELRO=true             # disable "-z relro" and "-z now"</li>
+DISABLE_RELRO=true             # disable "-z relro" and "-z now"
 </pre>
+                  </li>
                 </ol>
                 <p>See {@code docs/ANDROID-MK.html} for more details.</p>
               </li>
@@ -826,7 +1055,7 @@
 
           <li>Added branding for Android executables with the {@code .note.ABI-tag} section (in
 {@code crtbegin_static/dynamic.o}) so that debugging tools can act accordingly. The structure
-member and values are defined as follows:</p>
+member and values are defined as follows:
 <pre>
 static const struct {
   int32_t namesz;  /* = 4,  sizeof ("GNU") */
@@ -1621,10 +1850,11 @@
           <li>Fixed a bug that caused the build to fail if <code>LOCAL_ARM_NEON</code> was set to
           true (typo in <code>build/core/build-binary.mk</code>).</li>
 
-          <li>Fixed a bug that prevented the compilation of </code>.s</code> assembly files
+          <li>Fixed a bug that prevented the compilation of <code>.s</code> assembly files
           (<code>.S</code> files were okay).</li>
         </ul>
       </dd>
+    </dl>
   </div>
 </div>
 
diff --git a/docs/html/tools/sdk/ndk/overview.jd b/docs/html/tools/sdk/ndk/overview.jd
deleted file mode 100644
index 98ef1fc..0000000
--- a/docs/html/tools/sdk/ndk/overview.jd
+++ /dev/null
@@ -1,588 +0,0 @@
-page.title=What is the NDK?
-@jd:body
-
- <div id="qv-wrapper">
-    <div id="qv">
-      <h2>In this document</h2>
-
-      <ol>
-        <li><a href="#choosing">When to Develop in Native Code</a></li>
-        <li>
-          <a href="#contents">Contents of the NDK</a>
-          <ol>
-            <li><a href="#tools">Development tools</a></li>
-
-            <li><a href="#docs">Documentation</a></li>
-
-            <li><a href="#samples">Sample applications</a></li>
-          </ol>
-        </li>
-        <li><a href="#reqs">System and Software Requirements</a></li>
-      </ol>
-    </div>
-  </div>
-
-  <p>The Android NDK is a toolset that lets you embed components that make use of native code in
-  your Android applications.</p>
-
-  <p>Android applications run in the Dalvik virtual machine. The NDK allows you to implement parts
-  of your applications using native-code languages such as C and C++. This can provide benefits to
-  certain classes of applications, in the form of reuse of existing code and in some cases
-  increased speed.</p>
-
-  <p>The NDK provides:</p>
-
-  <ul>
-    <li>A set of tools and build files used to generate native code libraries from C and C++
-    sources</li>
-
-    <li>A way to embed the corresponding native libraries into an application package file
-    (<code>.apk</code>) that can be deployed on Android devices</li>
-
-    <li>A set of native system headers and libraries that will be supported in all future versions
-    of the Android platform, starting from Android 1.5. Applications that use native activities
-    must be run on Android 2.3 or later.</li>
-
-    <li>Documentation, samples, and tutorials</li>
-  </ul>
-
-  <p>The latest release of the NDK supports the following instruction sets:</p>
-
-  <ul>
-    <li>ARMv5TE, including Thumb-1 instructions (see {@code docs/CPU-ARCH-ABIS.html} for more
-information)</li>
-
-    <li>ARMv7-A, including Thumb-2 and VFPv3-D16 instructions, with optional support for
-    NEON/VFPv3-D32 instructions (see {@code docs/CPU-ARM-NEON.html} for more information)</li>
-
-    <li>x86 instructions (see {@code docs/CPU-X86.html} for more information)</li>
-
-    <li>MIPS instructions (see {@code docs/CPU-MIPS.html} for more information)</li>
-  </ul>
-
-  <p>ARMv5TE machine code will run on all ARM-based Android devices. ARMv7-A will run only on
-  devices such as the Verizon Droid or Google Nexus One that have a compatible CPU. The main
-  difference between the two instruction sets is that ARMv7-A supports hardware FPU, Thumb-2, and
-  NEON instructions. You can target either or both of the instruction sets &mdash; ARMv5TE is the
-  default, but switching to ARMv7-A is as easy as adding a single line to the application's
-  <code>Application.mk</code> file, without needing to change anything else in the file. You can also build for
-  both architectures at the same time and have everything stored in the final <code>.apk</code>.
-  Complete information is provided in the CPU-ARCH-ABIS.HTML in the NDK package.</p>
-
-  <p>The NDK provides stable headers for libc (the C library), libm (the Math library), OpenGL ES
-  (3D graphics library), the JNI interface, and other libraries, as listed in the <a href=
-  "#tools">Development Tools</a> section.</p>
-
-  <h2 id="choosing">When to Develop in Native Code</h2>
-
-  <p>The NDK will not benefit most applications. As a developer, you need to balance its benefits
-  against its drawbacks; notably, using native code does not result in an automatic performance
-  increase, but always increases application complexity. In general, you should only use native
-  code if it is essential to your application, not just because you prefer to program in C/C++.</p>
-
-  <p>Typical good candidates for the NDK are self-contained, CPU-intensive operations that don't
-  allocate much memory, such as signal processing, physics simulation, and so on. Simply re-coding
-  a method to run in C usually does not result in a large performance increase. When examining
-  whether or not you should develop in native code, think about your requirements and see if the
-  Android framework APIs provide the functionality that you need. The NDK can, however, can be an
-  effective way to reuse a large corpus of existing C/C++ code.</p>
-
-  <p>The Android framework provides two ways to use native code:</p>
-
-  <ul>
-    <li>Write your application using the Android framework and use JNI to access the APIs provided
-    by the Android NDK. This technique allows you to take advantage of the convenience of the
-    Android framework, but still allows you to write native code when necessary. If you use this
-    approach, your application must target specific, minimum Android platform levels, see <a
-    href="#platform-compat">Android platform compatibility</a> for more information.</li>
-
-    <li>
-      <p>Write a native activity, which allows you to implement the lifecycle callbacks in native
-      code. The Android SDK provides the {@link android.app.NativeActivity} class, which is a
-      convenience class that notifies your
-      native code of any activity lifecycle callbacks (<code>onCreate()</code>, <code>onPause()</code>,
-      <code>onResume()</code>, etc). You can implement the callbacks in your native code to handle
-      these events when they occur. Applications that use native activities must be run on Android
-      2.3 (API Level 9) or later.</p>
-
-      <p>You cannot access features such as Services and Content Providers natively, so if you want
-      to use them or any other framework API, you can still write JNI code to do so.</p>
-    </li>
-  </ul>
-
-  <h2 id="contents">Contents of the NDK</h2>The NDK contains the APIs, documentation, and sample
-  applications that help you write your native code.
-
-  <h3 id="tools">Development tools</h3>
-
-  <p>The NDK includes a set of cross-toolchains (compilers, linkers, etc..) that can generate
-  native ARM binaries on Linux, OS X, and Windows (with Cygwin) platforms.</p>
-
-  <p>It provides a set of system headers for stable native APIs that are guaranteed to be supported
-  in all later releases of the platform:</p>
-
-  <ul>
-    <li>libc (C library) headers</li>
-
-    <li>libm (math library) headers</li>
-
-    <li>JNI interface headers</li>
-
-    <li>libz (Zlib compression) headers</li>
-
-    <li>liblog (Android logging) header</li>
-
-    <li>OpenGL ES 1.1 and OpenGL ES 2.0 (3D graphics libraries) headers</li>
-
-    <li>libjnigraphics (Pixel buffer access) header (for Android 2.2 and above).</li>
-
-    <li>A Minimal set of headers for C++ support</li>
-    
-    <li>OpenSL ES native audio libraries</li>
-    
-    <li>Android native application APIS</li>
-  </ul>
-
-  <p>The NDK also provides a build system that lets you work efficiently with your sources, without
-  having to handle the toolchain/platform/CPU/ABI details. You create very short build files to
-  describe which sources to compile and which Android application will use them &mdash; the build
-  system compiles the sources and places the shared libraries directly in your application
-  project.</p>
-
-  <p class="caution"><strong>Important:</strong> With the exception of the libraries listed above,
-  native system libraries in the Android platform are <em>not</em> stable and may change in future
-  platform versions. Your applications should <em>only</em> make use of the stable native system
-  libraries provided in this NDK.</p>
-
-  <h3 id="docs">Documentation</h3>
-
-  <p>The NDK package includes a set of documentation that describes the capabilities of the NDK and
-  how to use it to create shared libraries for your Android applications. In this release, the
-  documentation is provided only in the downloadable NDK package. You can find the documentation in
-  the <code>&lt;ndk&gt;/docs/</code> directory. Included are these files (partial listing):</p>
-
-  <ul>
-    <li>
-    INSTALL.HTML &mdash; describes how to install the NDK and configure it for your host
-    system</li>
-
-    <li>OVERVIEW.HTML &mdash; provides an overview of the NDK capabilities and usage</li>
-    
-    <li>ANDROID-MK.HTML &mdash; describes the use of the Android.mk file, which defines the native
-    sources you want to compile</li>
-    
-    <li>APPLICATION-MK.HTML &mdash; describes the use of the Application.mk file, which describes
-    the native sources required by your Android application</li>    
-    <li>CPLUSPLUS-SUPPORT.HTML &mdash; describes the C++ support provided in the Android NDK</li>    
-    <li>CPU-ARCH-ABIS.HTML &mdash; a description of supported CPU architectures and how to target
-    them.</li>
-
-    <li>CPU-FEATURES.HTML &mdash; a description of the <code>cpufeatures</code> static library that
-    lets your application code detect the target device's CPU family and the optional features at
-    runtime.</li>
-
-    <li>CHANGES.HTML &mdash; a complete list of changes to the NDK across all releases.</li>
-
-    <li>DEVELOPMENT.HTML &mdash; describes how to modify the NDK and generate release packages for it</li>
-    
-    <li>HOWTO.HTML &mdash; information about common tasks associated with NDK development</li>
-    
-    <li>IMPORT-MODULE.HTML &mdash; describes how to share and reuse modules</li>
-    
-    <li>LICENSES.HTML  &mdash; information about the various open source licenses that govern the Android NDK</li>
- 
-    <li>NATIVE-ACTIVITY.HTML &mdash; describes how to implement native activities</li>
-    
-    <li>NDK-BUILD.HTML &mdash; describes the usage of the ndk-build script</li>
-
-    <li>NDK-GDB.HTML &mdash; describes how to use the native code debugger</li>
-
-    <li>PREBUILTS.HTML &mdash; information about how shared and static prebuilt libraries work </li>
-
-    <li>STANDALONE-TOOLCHAIN.HTML &mdash; describes how to use Android NDK toolchain as a standalone
-    compiler (still in beta).</li>
-    
-    <li>SYSTEM-ISSUES.HTML &mdash; known issues in the Android system images that you should be
-    aware of, if you are developing using the NDK.</li>
-
-    <li>STABLE-APIS.HTML &mdash; a complete list of the stable APIs exposed by headers in the
-    NDK.</li>
-    
-  </ul>
-
-  <p>Additionally, the package includes detailed information about the "bionic" C library provided
-  with the Android platform that you should be aware of, if you are developing using the NDK. You
-  can find the documentation in the <code>&lt;ndk&gt;/docs/system/libc/</code> directory:</p>
-
-  <ul>
-    <li>OVERVIEW.HTML &mdash; provides an overview of the "bionic" C library and the features it
-    offers.</li>
-  </ul>
-
-  <h3 id="samples">Sample applications</h3>
-
-<p>The NDK includes sample applications that illustrate how to use native code in your Android
-  applications:</p>
-
-  <ul>
-    <li><code>hello-jni</code> &mdash; a simple application that loads a string from a native
-    method implemented in a shared library and then displays it in the application UI.</li>
-
-    <li><code>two-libs</code> &mdash; a simple application that loads a shared library dynamically
-    and calls a native method provided by the library. In this case, the method is implemented in a
-    static library imported by the shared library.</li>
-
-    <li><code>san-angeles</code> &mdash; a simple application that renders 3D graphics through the
-    native OpenGL ES APIs, while managing activity lifecycle with a {@link
-    android.opengl.GLSurfaceView} object.</li>
-
-    <li><code>hello-gl2</code> &mdash; a simple application that renders a triangle using OpenGL ES
-    2.0 vertex and fragment shaders.</li>
-
-    <li><code>hello-neon</code> &mdash; a simple application that shows how to use the
-    <code>cpufeatures</code> library to check CPU capabilities at runtime, then use NEON intrinsics
-    if supported by the CPU. Specifically, the application implements two versions of a tiny
-    benchmark for a FIR filter loop, a C version and a NEON-optimized version for devices that
-    support it.</li>
-
-    <li><code>bitmap-plasma</code> &mdash; a simple application that demonstrates how to access the
-    pixel buffers of Android {@link android.graphics.Bitmap} objects from native code, and uses
-    this to generate an old-school "plasma" effect.</li>
-
-    <li><code>native-activity</code> &mdash; a simple application that demonstrates how to use the
-    native-app-glue static library to create a native activity</li>
-
-    <li><code>native-plasma</code> &mdash; a version of bitmap-plasma implemented with a native
-    activity.</li>
-  </ul>
-
-  <p>For each sample, the NDK includes the corresponding C source code and the necessary Android.mk
-  and Application.mk files. There are located under <code>&lt;ndk&gt;/samples/&lt;name&gt;/</code>
-  and their source code can be found under <code>&lt;ndk&gt;/samples/&lt;name&gt;/jni/</code>.</p>
-
-  <p>You can build the shared libraries for the sample apps by going into
-  <code>&lt;ndk&gt;/samples/&lt;name&gt;/</code> then calling the <code>ndk-build</code> command.
-  The generated shared libraries will be located under
-  <code>&lt;ndk&gt;/samples/&lt;name&gt;/libs/armeabi/</code> for (ARMv5TE machine code) and/or
-  <code>&lt;ndk&gt;/samples/&lt;name&gt;/libs/armeabi-v7a/</code> for (ARMv7 machine code).</p>
-
-  <p>Next, build the sample Android applications that use the shared libraries:</p>
-
-  <ul>
-    <li>If you are developing in Eclipse with ADT, use the New Project Wizard to create a new
-    Android project for each sample, using the "Import from Existing Source" option and importing
-    the source from <code>&lt;ndk&gt;/samples/&lt;name&gt;/</code>. Then, set up an AVD,
-    if necessary, and build/run the application in the emulator.</li>
-
-    <li>If you are developing with Ant, use the <code>android</code> tool to create the build file
-    for each of the sample projects at <code>&lt;ndk&gt;/samples/&lt;name&gt;/</code>.
-    Then set up an AVD, if necessary, build your project in the usual way, and run it in the
-    emulator.</li>    
-    
-  </ul>
-  
-  <p>For more information about developing with the Android SDK tools and what
-  you need to do to create, build, and run your applications, see
-  the <a href="{@docRoot}tools/workflow/index.html">Overview</a>
-  section for developing on Android.</p>
-
-  <h4 id="hello-jni">Exploring the hello-jni Sample</h4>
-
-  <p>The hello-jni sample is a simple demonstration on how to use JNI from an Android application.
-  The HelloJni activity receives a string from a simple C function and displays it in a
-  TextView.</p>
-
-  <p>The main components of the sample include:</p>
-
-  <ul>
-    <li>The familiar basic structure of an Android application (an <code>AndroidManifest.xml</code>
-    file, a <code>src/</code> and <code>res</code> directories, and a main activity)</li>
-
-    <li>A <code>jni/</code> directory that includes the implemented source file for the native code
-    as well as the Android.mk file</li>
-
-    <li>A <code>tests/</code> directory that contains unit test code.</li>
-  </ul>
-
-  <ol>
-    <li>Create a new project in Eclipse from the existing sample source or use the
-    <code>android</code> tool to update the project so it generates a build.xml file that you can
-    use to build the sample.
-
-      <ul>
-        <li>In Eclipse:
-
-          <ol type="a">
-            <li>Click <strong>File &gt; New Android Project...</strong></li>
-
-            <li>Select the <strong>Create project from existing source</strong> radio button.</li>
-
-            <li>Select any API level above Android 1.5.</li>
-
-            <li>In the <strong>Location</strong> field, click <strong>Browse...</strong> and select
-            the <code>&lt;ndk-root&gt;/samples/hello-jni</code> directory.</li>
-
-            <li>Click <strong>Finish</strong>.</li>
-          </ol>
-        </li>
-
-        <li>On the command line:
-
-          <ol type="a">
-            <li>Change to the <code>&lt;ndk-root&gt;/samples/hello-jni</code> directory.</li>
-
-            <li>Run the following command to generate a build.xml file:
-              <pre class="no-pretty-print">android update project -p . -s</pre>
-            </li>
-          </ol>
-        </li>
-      </ul>
-    </li>
-
-    <li>Compile the native code using the <code>ndk-build</code> command.
-      <pre class="no-pretty-print">
-cd &lt;ndk-root&gt;/samples/hello-jni
-&lt;ndk_root&gt;/ndk-build
-</pre>
-    </li>
-
-    <li>Build and install the application as you would a normal Android application. If you are
-    using Eclipse, run the application to build and install it on a device. If you are using Ant,
-    run the following commands from the project directory:
-      <pre class="no-pretty-print">
-ant debug
-adb install bin/HelloJni-debug.apk
-</pre>
-    </li>
-  </ol>
-
-  <p>When you run the application on the device, the string <code>Hello JNI</code> should appear on
-  your device. You can explore the rest of the samples that are located in the
-  <code>&lt;ndk-root&gt;/samples</code> directory for more examples on how to use the JNI.</p>
-
-  <h4 id="native-activity">Exploring the native-activity Sample Application</h4>
-
-  <p>The native-activity sample provided with the Android NDK demonstrates how to use the
-  android_native_app_glue static library. This static library makes creating a native activity
-  easier by providing you with an implementation that handles your callbacks in another thread, so
-  you do not have to worry about them blocking your main UI thread. The main parts of the sample
-  are described below:</p>
-
-  <ul>
-    <li>The familiar basic structure of an Android application (an <code>AndroidManifest.xml</code>
-    file, a <code>src/</code> and <code>res</code> directories). The AndroidManifest.xml declares
-    that the application is native and specifies the .so file of the native activity. See {@link
-    android.app.NativeActivity} for the source or see the
-    <code>&lt;ndk_root&gt;/platforms/samples/native-activity/AndroidManifest.xml</code> file.</li>
-
-    <li>A <code>jni/</code> directory contains the native activity, main.c, which uses the
-    <code>android_native_app_glue.h</code> interface to implement the activity. The Android.mk that
-    describes the native module to the build system also exists here.</li>
-  </ul>
-
-  <p>To build this sample application:</p>
-
-  <ol>
-    <li>Create a new project in Eclipse from the existing sample source or use the
-    <code>android</code> tool to update the project so it generates a build.xml file that you can
-    use to build the sample.
-
-      <ul>
-        <li>In Eclipse:
-
-          <ol type="a">
-            <li>Click <strong>File &gt; New Android Project...</strong></li>
-
-            <li>Select the <strong>Create project from existing source</strong> radio button.</li>
-
-            <li>Select any API level above Android 2.3.</li>
-
-            <li>In the <strong>Location</strong> field, click <strong>Browse...</strong> and select
-            the <code>&lt;ndk-root&gt;/samples/native-activity</code> directory.</li>
-
-            <li>Click <strong>Finish</strong>.</li>
-          </ol>
-        </li>
-
-        <li>On the command line:
-
-          <ol type="a">
-            <li>Change to the <code>&lt;ndk-root&gt;/samples/native-activity</code> directory.</li>
-
-            <li>Run the following command to generate a build.xml file:
-              <pre class="no-pretty-print">
-android update project -p . -s
-</pre>
-            </li>
-          </ol>
-        </li>
-      </ul>
-    </li>
-
-    <li>Compile the native code using the <code>ndk-build</code> command.
-      <pre class="no-pretty-print">
-cd &lt;ndk-root&gt;/platforms/samples/android-9/samples/native-activity
-&lt;ndk_root&gt;/ndk-build
-</pre>
-    </li>
-
-    <li>Build and install the application as you would a normal Android application. If you are
-    using Eclipse, run the application to build and install it on a device. If you are using Ant,
-    run the following commands in the project directory, then run the application on the device:
-      <pre class="no-pretty-print">
-ant debug
-adb install bin/NativeActivity-debug.apk
-</pre>
-    </li>
-  </ol>
-
-
-  <h2 id="reqs">System and Software Requirements</h2>
-
-  <p>The sections below describe the system and software requirements for using the Android NDK, as
-  well as platform compatibility considerations that affect appplications using libraries produced
-  with the NDK.</p>
-
-  <h4>The Android SDK</h4>
-
-  <ul>
-    <li>A complete Android SDK installation (including all dependencies) is required.</li>
-
-    <li>Android 1.5 SDK or later version is required.</li>
-  </ul>
-
-  <h4>Supported operating systems</h4>
-
-  <ul>
-    <li>Windows XP (32-bit) or Vista (32- or 64-bit)</li>
-
-    <li>Mac OS X 10.4.8 or later (x86 only)</li>
-
-    <li>Linux (32 or 64-bit; Ubuntu 8.04, or other Linux distributions using GLibc 2.7 or
-later)</li>
-  </ul>
-
-  <h4>Required development tools</h4>
-
-  <ul>
-    <li>For all development platforms, GNU Make 3.81 or later is required. Earlier versions of GNU
-    Make might work but have not been tested.</li>
-
-    <li>A recent version of awk (either GNU Awk or Nawk) is also required.</li>
-
-    <li>For Windows, <a href="http://www.cygwin.com">Cygwin</a> 1.7 or higher is required. The NDK
-    will <em>not</em> work with Cygwin 1.5 installations.</li>
-  </ul>
-
-  <h4 id="platform-compat">Android platform compatibility</h4>
-
-  <ul>
-    <li>The native libraries created by the Android NDK can only be used on devices running
-      specific minimum Android platform versions. The minimum required platform version depends on
-      the CPU architecture of the devices you are targeting. The following table details which
-      Android platform versions are compatible with native code developed for specific CPU
-      architectures.
-
-    <table style="margin:1em;">
-      <tr>
-        <th>Native Code CPU Architecture Used</th>
-        <th>Compatible Android Platform(s)</th>
-      </tr>
-
-      <tr>
-        <td>ARM, ARM-NEON</td>
-        <td>Android 1.5 (API Level 3) and higher</td>
-      </tr>
-
-      <tr>
-        <td>x86</td>
-        <td>Android 2.3 (API Level 9) and higher</td>
-      </tr>
-
-      <tr>
-        <td>MIPS</td>
-        <td>Android 2.3 (API Level 9) and higher</td>
-      </tr>
-    </table>
-
-      <p>These requirements mean you can use native libraries produced with the NDK in
-      applications that are deployable to ARM-based devices running Android 1.5 or later. If you are
-      deploying native libraries to x86 and MIPS-based devices, your application must target Android
-      2.3 or later.</p>
-    </li>
-
-    <li>To ensure compatibility, an application using a native library produced with the NDK
-    <em>must</em> declare a <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html"><code>
-      &lt;uses-sdk&gt;</code></a> element in its manifest file, with an
-      <code>android:minSdkVersion</code> attribute value of "3" or higher. For example:
-
-<pre style="margin:1em;">
-&lt;manifest&gt;
-  &lt;uses-sdk android:minSdkVersion="3" /&gt;
-  ...
-&lt;/manifest&gt;
-</pre>
-    </li>
-
-    <li>If you use this NDK to create a native library that uses the OpenGL ES APIs, the
-    application containing the library can be deployed only to devices running the minimum platform
-    versions described in the table below. To ensure compatibility, make sure that your application
-    declares the proper <code>android:minSdkVersion</code> attribute value, as shown in the
-    following table.</li>
-
-    <li style="list-style: none; display: inline">
-      <table style="margin:1em;">
-        <tr>
-          <th>OpenGL ES Version Used</th>
-
-          <th>Compatible Android Platform(s)</th>
-
-          <th>Required uses-sdk Attribute</th>
-        </tr>
-
-        <tr>
-          <td>OpenGL ES 1.1</td>
-
-          <td>Android 1.6 (API Level 4) and higher</td>
-
-          <td><code>android:minSdkVersion="4"</code></td>
-        </tr>
-
-        <tr>
-          <td>OpenGL ES 2.0</td>
-
-          <td>Android 2.0 (API Level 5) and higher</td>
-
-          <td><code>android:minSdkVersion="5"</code></td>
-        </tr>
-      </table>
-
-      <p>For more information about API Level and its relationship to Android platform versions,
-      see <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#ApiLevels">Android API Levels</a>.</p>
-    </li>
-
-    <li>Additionally, an application using the OpenGL ES APIs should declare a
-    <code>&lt;uses-feature&gt;</code> element in its manifest, with an
-    <code>android:glEsVersion</code> attribute that specifies the minimum OpenGl ES version
-    required by the application. This ensures that Google Play will show your application only
-    to users whose devices are capable of supporting your application. For example:
-      <pre style="margin:1em;">
-&lt;manifest&gt;
-<!-- Declare that the application uses the OpenGL ES 2.0 API and is designed
-     to run only on devices that support OpenGL ES 2.0 or higher. -->
-  &lt;uses-feature android:glEsVersion="0x00020000" /&gt;
-  ...
-&lt;/manifest&gt;
-</pre>
-
-      <p>For more information, see the <a href=
-      "{@docRoot}guide/topics/manifest/uses-feature-element.html"><code>&lt;uses-feature&gt;</code></a>
-      documentation.</p>
-    </li>
-
-    <li>If you use this NDK to create a native library that uses the API to access Android {@link
-    android.graphics.Bitmap} pixel buffers or utilizes native activities, the application
-    containing the library can be deployed only to devices running Android 2.2 (API level 8) or
-    higher. To ensure compatibility, make sure that your application declares <code>&lt;uses-sdk
-    android:minSdkVersion="8" /&gt;</code> attribute value in its manifest.</li>
-  </ul>
diff --git a/docs/html/tools/sdk/older_releases.jd b/docs/html/tools/sdk/older_releases.jd
index bb274b6..94baa92 100644
--- a/docs/html/tools/sdk/older_releases.jd
+++ b/docs/html/tools/sdk/older_releases.jd
@@ -1,4 +1,5 @@
 page.title=SDK Archives
+excludeFromSuggestions=true
 @jd:body
 
 <p>This page provides a full list of archived and obsolete SDK releases,
diff --git a/docs/html/tools/sdk/platforms.jd b/docs/html/tools/sdk/platforms.jd
deleted file mode 100644
index 27e89de..0000000
--- a/docs/html/tools/sdk/platforms.jd
+++ /dev/null
@@ -1,9 +0,0 @@
-page.title=Android Development Platforms
-
-@jd:body
-
-
-
-<p>A page that lists platforms and links to release notes. Links to dashboards etc.</p>
-
-
diff --git a/docs/html/tools/sdk/tools-notes.jd b/docs/html/tools/sdk/tools-notes.jd
index a5b7eee..4d8aa34 100644
--- a/docs/html/tools/sdk/tools-notes.jd
+++ b/docs/html/tools/sdk/tools-notes.jd
@@ -1,4 +1,5 @@
 page.title=SDK Tools
+excludeFromSuggestions=true
 @jd:body
 
 <p>SDK Tools is a downloadable component for the Android SDK. It includes the
@@ -28,7 +29,7 @@
 <div class="toggle-content opened">
   <p><a href="#" onclick="return toggleContent(this)">
     <img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-content-img"
-      alt=""/>SDK Tools, Revision 21.1.0</a> <em>(February 2013)</em>
+      alt=""/>SDK Tools, Revision 21.1</a> <em>(February 2013)</em>
   </p>
 
   <div class="toggle-content-toggleme">
@@ -38,7 +39,7 @@
     <dd>
       <ul>
         <li>Android SDK Platform-tools revision 16 or later.</li>
-        <li>If you are developing in Eclipse with ADT, note that the SDK Tools r21.1.0 is
+        <li>If you are developing in Eclipse with ADT, note that the SDK Tools r21.1 is
           designed for use with ADT 21.1.0 and later. If you haven't already, update your
         <a href="{@docRoot}tools/sdk/eclipse-adt.html">ADT Plugin</a> to 21.1.0.</li>
         <li>If you are developing outside Eclipse, you must have
diff --git a/docs/html/tools/sdk/usb-drivers.jd b/docs/html/tools/sdk/usb-drivers.jd
deleted file mode 100644
index 27e89de..0000000
--- a/docs/html/tools/sdk/usb-drivers.jd
+++ /dev/null
@@ -1,9 +0,0 @@
-page.title=Android Development Platforms
-
-@jd:body
-
-
-
-<p>A page that lists platforms and links to release notes. Links to dashboards etc.</p>
-
-
diff --git a/docs/html/tools/testing/activity_test.jd b/docs/html/tools/testing/activity_test.jd
index 8288249..096aea5 100644
--- a/docs/html/tools/testing/activity_test.jd
+++ b/docs/html/tools/testing/activity_test.jd
@@ -537,7 +537,7 @@
 import android.widget.SpinnerAdapter;
 </pre>
 <p>
-    You now have the the complete <code>setUp()</code> method.
+    You now have the complete <code>setUp()</code> method.
 </p>
 <h3 id="AddPreConditionsTest">Adding an initial conditions test</h3>
 <p>
@@ -1266,7 +1266,7 @@
   </li>
   <li>
     Follow the tutorial, starting with the section <a href="#CreateTestCaseClass">Creating the Test Case Class</a>. When you are prompted to
-    run the sample application, go the the Launcher screen in your device or emulator and select SpinnerActivity.
+    run the sample application, go to the Launcher screen in your device or emulator and select SpinnerActivity.
     When you are prompted to run the test application, return here to continue with the following instructions.
   </li>
   <li>
diff --git a/docs/html/tools/testing/activity_testing.jd b/docs/html/tools/testing/activity_testing.jd
index 7190b98..88ac9b2 100644
--- a/docs/html/tools/testing/activity_testing.jd
+++ b/docs/html/tools/testing/activity_testing.jd
@@ -77,7 +77,7 @@
   </div>
 </div>
 <p>
-    Activity testing is particularly dependent on the the Android instrumentation framework.
+    Activity testing is particularly dependent on the Android instrumentation framework.
     Unlike other components, activities have a complex lifecycle based on callback methods; these
     can't be invoked directly except by instrumentation. Also, the only way to send events to the
     user interface from a program is through instrumentation.
@@ -322,7 +322,7 @@
     the published application.
 </p>
 <p>
-    To add the the permission, add the element
+    To add the permission, add the element
     <code>&lt;uses-permission android:name="android.permission.DISABLE_KEYGUARD"/&gt;</code>
     as a child of the <code>&lt;manifest&gt;</code> element. To disable the KeyGuard, add the
     following code to the <code>onCreate()</code> method of activities you intend to test:
diff --git a/docs/html/tools/testing/testing_android.jd b/docs/html/tools/testing/testing_android.jd
index acf5ec2..10843e8 100755
--- a/docs/html/tools/testing/testing_android.jd
+++ b/docs/html/tools/testing/testing_android.jd
@@ -111,14 +111,14 @@
     </li>
     <li>
         The SDK tools for building and tests are available in Eclipse with ADT, and also in
-        command-line form for use with other IDES. These tools get information from the project of
+        command-line form for use with other IDEs. These tools get information from the project of
         the application under test and use this information to automatically create the build files,
         manifest file, and directory structure for the test package.
     </li>
     <li>
         The SDK also provides
   <a href="{@docRoot}tools/help/monkeyrunner_concepts.html">monkeyrunner</a>, an API
-        testing devices with Python programs, and <a
+        for testing devices with Python programs, and <a
         href="{@docRoot}tools/help/monkey.html">UI/Application Exerciser Monkey</a>,
         a command-line tool for stress-testing UIs by sending pseudo-random events to a device.
     </li>
diff --git a/docs/html/tools/testing/testing_otheride.jd b/docs/html/tools/testing/testing_otheride.jd
index 0678f52..9484158 100644
--- a/docs/html/tools/testing/testing_otheride.jd
+++ b/docs/html/tools/testing/testing_otheride.jd
@@ -75,9 +75,9 @@
 <p>
     You use the <code>android</code> tool to create test projects.
     You also use <code>android</code> to convert existing test code into an Android test project,
-    or to add the <code>run-tests</code> Ant target to an existing Android test project.
+    or to add the <code>test</code> Ant target to an existing Android test project.
     These operations are described in more detail in the section <a href="#UpdateTestProject">
-    Updating a test project</a>. The <code>run-tests</code> target is described in
+    Updating a test project</a>. The <code>test</code> target is described in
     <a href="#RunTestsAnt">Quick build and run with Ant</a>.
 </p>
 <h3 id="CreateTestProject">Creating a test project</h3>
@@ -300,7 +300,7 @@
 <h3 id="RunTestsAnt">Quick build and run with Ant</h3>
 <p>
     You can use Ant to run all the tests in your test project, using the target
-    <code>run-tests</code>, which is created automatically when you create a test project with
+    <code>test</code>, which is created automatically when you create a test project with
     the <code>android</code> tool.
 </p>
 <p>
diff --git a/docs/html/tools/workflow/index.jd b/docs/html/tools/workflow/index.jd
index 5ae06e6..784b212 100644
--- a/docs/html/tools/workflow/index.jd
+++ b/docs/html/tools/workflow/index.jd
@@ -34,7 +34,7 @@
   </li>
   <li><strong>Development</strong>
     <p>During this phase you set up and develop your Android project, which contains all of the
-    source code and resource files for your application. For more informations, see
+    source code and resource files for your application. For more information, see
     <a href="{@docRoot}tools/projects/index.html">Create an Android project</a>.</p>
   </li>
   <li><strong>Debugging and Testing</strong>
diff --git a/docs/html/training/accessibility/index.jd b/docs/html/training/accessibility/index.jd
index 333f9f2..0af1d87 100644
--- a/docs/html/training/accessibility/index.jd
+++ b/docs/html/training/accessibility/index.jd
@@ -1,9 +1,8 @@
 page.title=Implementing Accessibility
+page.tags="navigation","input"
 
 trainingnavtop=true
 startpage=true
-next.title=Developing Accessible Applications
-next.link=accessible-app.html
 
 @jd:body
 
diff --git a/docs/html/training/accessibility/service.jd b/docs/html/training/accessibility/service.jd
index 373ddbb..953c558 100644
--- a/docs/html/training/accessibility/service.jd
+++ b/docs/html/training/accessibility/service.jd
@@ -204,7 +204,7 @@
 <p>This step is optional, but highly useful.  One of the new features in Android
 4.0 (API Level 14) is the ability for an
 {@link android.accessibilityservice.AccessibilityService} to query the view
-hierarchy, collecting information about the the UI component that generated an event, and
+hierarchy, collecting information about the UI component that generated an event, and
 its parent and children.  In order to do this, make sure that you set the
 following line in your XML configuration:</p>
 <pre>
diff --git a/docs/html/training/animation/index.jd b/docs/html/training/animation/index.jd
index 9cc7e6c..b2815fc 100644
--- a/docs/html/training/animation/index.jd
+++ b/docs/html/training/animation/index.jd
@@ -1,4 +1,5 @@
 page.title=Adding Animations
+page.tags="animation","views","layout","user interface"
 trainingnavtop=true
 startpage=true
 
diff --git a/docs/html/training/articles/perf-anr.jd b/docs/html/training/articles/perf-anr.jd
index abef5456..d3b2318 100644
--- a/docs/html/training/articles/perf-anr.jd
+++ b/docs/html/training/articles/perf-anr.jd
@@ -1,4 +1,6 @@
 page.title=Keeping Your App Responsive
+page.tags="threads","asynctask"
+
 page.article=true
 @jd:body
 
diff --git a/docs/html/training/articles/perf-jni.jd b/docs/html/training/articles/perf-jni.jd
index 2abb000..0d1f04e 100644
--- a/docs/html/training/articles/perf-jni.jd
+++ b/docs/html/training/articles/perf-jni.jd
@@ -1,4 +1,6 @@
 page.title=JNI Tips
+page.tags="ndk","native"
+
 page.article=true
 @jd:body
 
diff --git a/docs/html/training/articles/security-ssl.jd b/docs/html/training/articles/security-ssl.jd
index 9a6320b..d3f68e2 100644
--- a/docs/html/training/articles/security-ssl.jd
+++ b/docs/html/training/articles/security-ssl.jd
@@ -1,4 +1,6 @@
 page.title=Security with HTTPS and SSL
+page.tags="network","certificates"
+
 page.article=true
 @jd:body
 
diff --git a/docs/html/training/articles/smp.jd b/docs/html/training/articles/smp.jd
index d46787d..0f667d7 100644
--- a/docs/html/training/articles/smp.jd
+++ b/docs/html/training/articles/smp.jd
@@ -1,4 +1,6 @@
 page.title=SMP Primer for Android
+page.tags="ndk","native"
+
 page.article=true
 @jd:body
 
diff --git a/docs/html/training/backward-compatible-ui/index.jd b/docs/html/training/backward-compatible-ui/index.jd
index f81b5a7..82087a6 100644
--- a/docs/html/training/backward-compatible-ui/index.jd
+++ b/docs/html/training/backward-compatible-ui/index.jd
@@ -1,9 +1,8 @@
 page.title=Creating Backward-Compatible UIs
+page.tags="widgets","support"
 
 trainingnavtop=true
 startpage=true
-next.title=Abstracting the New Implementation
-next.link=abstracting.html
 
 @jd:body
 
diff --git a/docs/html/training/basics/data-storage/databases.jd b/docs/html/training/basics/data-storage/databases.jd
index fbefce4..61fb758 100644
--- a/docs/html/training/basics/data-storage/databases.jd
+++ b/docs/html/training/basics/data-storage/databases.jd
@@ -1,6 +1,4 @@
 page.title=Saving Data in SQL Databases
-parent.title=Data Storage
-parent.link=index.html
 
 trainingnavtop=true
 previous.title=Saving Data in Files
diff --git a/docs/html/training/basics/data-storage/files.jd b/docs/html/training/basics/data-storage/files.jd
index dd081a6..52bea4c 100644
--- a/docs/html/training/basics/data-storage/files.jd
+++ b/docs/html/training/basics/data-storage/files.jd
@@ -1,6 +1,4 @@
 page.title=Saving Files
-parent.title=Data Storage
-parent.link=index.html
 
 trainingnavtop=true
 
diff --git a/docs/html/training/basics/data-storage/index.jd b/docs/html/training/basics/data-storage/index.jd
index 4334936..4ccad75 100644
--- a/docs/html/training/basics/data-storage/index.jd
+++ b/docs/html/training/basics/data-storage/index.jd
@@ -1,4 +1,5 @@
 page.title=Saving Data
+page.tags="data storage","files","sql","database","preferences"
 
 trainingnavtop=true
 startpage=true
diff --git a/docs/html/training/basics/data-storage/shared-preferences.jd b/docs/html/training/basics/data-storage/shared-preferences.jd
index 099da67..a6717c4 100644
--- a/docs/html/training/basics/data-storage/shared-preferences.jd
+++ b/docs/html/training/basics/data-storage/shared-preferences.jd
@@ -1,6 +1,4 @@
 page.title=Saving Key-Value Sets
-parent.title=Data Storage
-parent.link=index.html
 
 trainingnavtop=true
 
diff --git a/docs/html/training/basics/firstapp/building-ui.jd b/docs/html/training/basics/firstapp/building-ui.jd
index 0f18861..2615bee 100644
--- a/docs/html/training/basics/firstapp/building-ui.jd
+++ b/docs/html/training/basics/firstapp/building-ui.jd
@@ -240,7 +240,7 @@
     &lt;string name="app_name">My First App&lt;/string>
     &lt;string name="edit_message">Enter a message&lt;/string>
     &lt;string name="button_send">Send&lt;/string>
-    &lt;string name="menu_settings">Settings&lt;/string>
+    &lt;string name="action_settings">Settings&lt;/string>
     &lt;string name="title_activity_main">MainActivity&lt;/string>
 &lt;/resources>
 </pre>
diff --git a/docs/html/training/basics/fragments/communicating.jd b/docs/html/training/basics/fragments/communicating.jd
index eb9b368..b30045d 100644
--- a/docs/html/training/basics/fragments/communicating.jd
+++ b/docs/html/training/basics/fragments/communicating.jd
@@ -1,10 +1,6 @@
 page.title=Communicating with Other Fragments
-parent.title=Building a Dynamic UI with Fragments
-parent.link=index.html
 
 trainingnavtop=true
-previous.title=Building a Flexible UI
-previous.link=fragment-ui.html
 
 @jd:body
 
diff --git a/docs/html/training/basics/fragments/creating.jd b/docs/html/training/basics/fragments/creating.jd
index 0646230..b5df4e1 100644
--- a/docs/html/training/basics/fragments/creating.jd
+++ b/docs/html/training/basics/fragments/creating.jd
@@ -1,12 +1,6 @@
 page.title=Creating a Fragment
-parent.title=Building a Dynamic UI with Fragments
-parent.link=index.html
 
 trainingnavtop=true
-previous.title=Using the Android Support Library
-previous.link=support-lib.html
-next.title=Building a Flexible UI
-next.link=fragment-ui.html
 
 @jd:body
 
diff --git a/docs/html/training/basics/fragments/fragment-ui.jd b/docs/html/training/basics/fragments/fragment-ui.jd
index 1e134ca..db3119b 100644
--- a/docs/html/training/basics/fragments/fragment-ui.jd
+++ b/docs/html/training/basics/fragments/fragment-ui.jd
@@ -1,12 +1,6 @@
 page.title=Building a Flexible UI
-parent.title=Building a Dynamic UI with Fragments
-parent.link=index.html
 
 trainingnavtop=true
-previous.title=Create a Fragment
-previous.link=creating.html
-next.title=Communicating with Other Fragments
-next.link=communicating.html
 
 @jd:body
 
diff --git a/docs/html/training/basics/fragments/index.jd b/docs/html/training/basics/fragments/index.jd
index bc93f43..1b82f2c 100644
--- a/docs/html/training/basics/fragments/index.jd
+++ b/docs/html/training/basics/fragments/index.jd
@@ -1,9 +1,8 @@
 page.title=Building a Dynamic UI with Fragments
+page.tags="fragments", "user interface", "support library"
 
 trainingnavtop=true
 startpage=true
-next.title=Using the Android Support Library
-next.link=support-lib.html
 
 @jd:body
 
diff --git a/docs/html/training/basics/fragments/support-lib.jd b/docs/html/training/basics/fragments/support-lib.jd
index cc867d3..b097de1 100644
--- a/docs/html/training/basics/fragments/support-lib.jd
+++ b/docs/html/training/basics/fragments/support-lib.jd
@@ -1,10 +1,7 @@
 page.title=Using the Support Library
-parent.title=Building a Dynamic UI with Fragments
-parent.link=index.html
+page.tags="support library"
 
 trainingnavtop=true
-next.title=Creating a Fragment
-next.link=creating.html
 
 @jd:body
 
diff --git a/docs/html/training/basics/intents/index.jd b/docs/html/training/basics/intents/index.jd
index d94ff015..8876a33 100644
--- a/docs/html/training/basics/intents/index.jd
+++ b/docs/html/training/basics/intents/index.jd
@@ -1,9 +1,8 @@
 page.title=Interacting with Other Apps
+page.tags="intents","activity"
 
 trainingnavtop=true
 startpage=true
-next.title=Sending the User to Another App
-next.link=sending.html
 
 @jd:body
 
diff --git a/docs/html/training/basics/intents/result.jd b/docs/html/training/basics/intents/result.jd
index 0086913..24ecc46 100644
--- a/docs/html/training/basics/intents/result.jd
+++ b/docs/html/training/basics/intents/result.jd
@@ -62,7 +62,7 @@
 static final int PICK_CONTACT_REQUEST = 1;  // The request code
 ...
 private void pickContact() {
-    Intent pickContactIntent = new Intent(Intent.ACTION_PICK, new Uri("content://contacts"));
+    Intent pickContactIntent = new Intent(Intent.ACTION_PICK, Uri.parse("content://contacts"));
     pickContactIntent.setType(Phone.CONTENT_TYPE); // Show user only contacts w/ phone numbers
     startActivityForResult(pickContactIntent, PICK_CONTACT_REQUEST);
 }
diff --git a/docs/html/training/basics/location/index.jd b/docs/html/training/basics/location/index.jd
index 48cfbc3..240bbb2 100644
--- a/docs/html/training/basics/location/index.jd
+++ b/docs/html/training/basics/location/index.jd
@@ -1,9 +1,8 @@
 page.title=Making Your App Location Aware
+page.tags="geolocation","maps"
 
 trainingnavtop=true
 startpage=true
-next.title=Using the Location Manager
-next.link=locationmanager.html
 
 @jd:body
 
diff --git a/docs/html/training/basics/network-ops/connecting.jd b/docs/html/training/basics/network-ops/connecting.jd
index ac8d993..50a9e1b 100644
--- a/docs/html/training/basics/network-ops/connecting.jd
+++ b/docs/html/training/basics/network-ops/connecting.jd
@@ -136,7 +136,7 @@
             getSystemService(Context.CONNECTIVITY_SERVICE);
         NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
         if (networkInfo != null &amp;&amp; networkInfo.isConnected()) {
-            new DownloadWebpageText().execute(stringUrl);
+            new DownloadWebpageTask().execute(stringUrl);
         } else {
             textView.setText("No network connection available.");
         }
@@ -147,7 +147,7 @@
      // has been established, the AsyncTask downloads the contents of the webpage as
      // an InputStream. Finally, the InputStream is converted into a string, which is
      // displayed in the UI by the AsyncTask's onPostExecute method.
-     private class DownloadWebpageText extends AsyncTask<String, Void, String> {
+     private class DownloadWebpageTask extends AsyncTask&lt;String, Void, String&gt; {
         &#64;Override
         protected String doInBackground(String... urls) {
               
diff --git a/docs/html/training/basics/network-ops/index.jd b/docs/html/training/basics/network-ops/index.jd
index b213c03..cb3a390 100644
--- a/docs/html/training/basics/network-ops/index.jd
+++ b/docs/html/training/basics/network-ops/index.jd
@@ -1,4 +1,5 @@
 page.title=Performing Network Operations
+page.tags="network","wireless"
 
 trainingnavtop=true
 startpage=true
diff --git a/docs/html/training/basics/network-ops/managing.jd b/docs/html/training/basics/network-ops/managing.jd
index 0f3d495..990b8cb 100644
--- a/docs/html/training/basics/network-ops/managing.jd
+++ b/docs/html/training/basics/network-ops/managing.jd
@@ -269,7 +269,7 @@
   
     // When the user changes the preferences selection, 
     // onSharedPreferenceChanged() restarts the main activity as a new
-    // task. Sets the the refreshDisplay flag to "true" to indicate that 
+    // task. Sets the refreshDisplay flag to "true" to indicate that
     // the main activity should update its display.
     // The main activity queries the PreferenceManager to get the latest settings.
     
diff --git a/docs/html/training/basics/supporting-devices/index.jd b/docs/html/training/basics/supporting-devices/index.jd
index 49ea81d..1e3eb42 100644
--- a/docs/html/training/basics/supporting-devices/index.jd
+++ b/docs/html/training/basics/supporting-devices/index.jd
@@ -1,9 +1,8 @@
 page.title=Supporting Different Devices
+page.tags="resources","screens","versions","localization"
 
 trainingnavtop=true
 startpage=true
-next.title=Supporting Multiple Languages
-next.link=languages.html
 
 @jd:body
 
diff --git a/docs/html/training/camera/index.jd b/docs/html/training/camera/index.jd
index 282bed8..fa754a0 100644
--- a/docs/html/training/camera/index.jd
+++ b/docs/html/training/camera/index.jd
@@ -1,4 +1,5 @@
 page.title=Capturing Photos
+page.tags="camera","video"
 
 trainingnavtop=true
 startpage=true
diff --git a/docs/html/training/cloudsync/index.jd b/docs/html/training/cloudsync/index.jd
index 91885e8..55b275b 100644
--- a/docs/html/training/cloudsync/index.jd
+++ b/docs/html/training/cloudsync/index.jd
@@ -1,9 +1,8 @@
 page.title=Syncing to the Cloud
+page.tags="cloud","sync","backup"
 
 trainingnavtop=true
 startpage=true
-next.title=Making the Most of Google Cloud Messaging
-next.link=gcm.html
 
 @jd:body
 
diff --git a/docs/html/training/connect-devices-wirelessly/index.jd b/docs/html/training/connect-devices-wirelessly/index.jd
index 37cf633..f27b9c3 100644
--- a/docs/html/training/connect-devices-wirelessly/index.jd
+++ b/docs/html/training/connect-devices-wirelessly/index.jd
@@ -1,9 +1,8 @@
 page.title=Connecting Devices Wirelessly
+page.tags="wifi","network","wireless"
 
 trainingnavtop=true
 startpage=true
-next.title=Using Network Service Discovery
-next.link=nsd.html
 
 @jd:body
 
diff --git a/docs/html/training/contacts-provider/display-contact-badge.jd b/docs/html/training/contacts-provider/display-contact-badge.jd
index f08935d..041eb58 100644
--- a/docs/html/training/contacts-provider/display-contact-badge.jd
+++ b/docs/html/training/contacts-provider/display-contact-badge.jd
@@ -169,8 +169,8 @@
     // Gets a content URI for the contact
     mContactUri =
             Contacts.getLookupUri(
-                Cursor.getLong(mIdColumn),
-                Cursor.getString(mLookupKeyColumn)
+                mCursor.getLong(mIdColumn),
+                mCursor.getString(mLookupKeyColumn)
             );
     mBadge.assignContactUri(mContactUri);
 </pre>
@@ -221,7 +221,7 @@
      * Assuming the current Cursor position is the contact you want,
      * gets the thumbnail ID
      */
-    mThumbnailUri = Cursor.getString(mThumbnailColumn);
+    mThumbnailUri = mCursor.getString(mThumbnailColumn);
     ...
 </pre>
 <p>
diff --git a/docs/html/training/custom-views/index.jd b/docs/html/training/custom-views/index.jd
index cec75b4..1c09e66 100644
--- a/docs/html/training/custom-views/index.jd
+++ b/docs/html/training/custom-views/index.jd
@@ -1,9 +1,8 @@
 page.title=Creating Custom Views
+page.tags="widgets","ui","layout"
 
 trainingnavtop=true
 startpage=true
-next.title=Creating a View Class
-next.link=create-view.html
 
 @jd:body
 
diff --git a/docs/html/training/design-navigation/index.jd b/docs/html/training/design-navigation/index.jd
index af60717..f888c93a 100644
--- a/docs/html/training/design-navigation/index.jd
+++ b/docs/html/training/design-navigation/index.jd
@@ -2,8 +2,6 @@
 
 trainingnavtop=true
 startpage=true
-next.title=Planning Screens and Their Relationships
-next.link=screen-planning.html
 
 @jd:body
 
diff --git a/docs/html/training/displaying-bitmaps/cache-bitmap.jd b/docs/html/training/displaying-bitmaps/cache-bitmap.jd
index 417ec5b..b1608c3 100644
--- a/docs/html/training/displaying-bitmaps/cache-bitmap.jd
+++ b/docs/html/training/displaying-bitmaps/cache-bitmap.jd
@@ -3,10 +3,6 @@
 parent.link=index.html
 
 trainingnavtop=true
-next.title=Displaying Bitmaps in Your UI
-next.link=display-bitmap.html
-previous.title=Processing Bitmaps Off the UI Thread
-previous.link=process-bitmap.html
 
 @jd:body
 
diff --git a/docs/html/training/displaying-bitmaps/display-bitmap.jd b/docs/html/training/displaying-bitmaps/display-bitmap.jd
index 4572c42..ed1836c 100644
--- a/docs/html/training/displaying-bitmaps/display-bitmap.jd
+++ b/docs/html/training/displaying-bitmaps/display-bitmap.jd
@@ -3,8 +3,6 @@
 parent.link=index.html
 
 trainingnavtop=true
-previous.title=Caching Bitmaps
-previous.link=cache-bitmap.html
 
 @jd:body
 
diff --git a/docs/html/training/displaying-bitmaps/index.jd b/docs/html/training/displaying-bitmaps/index.jd
index b91172b..857edee 100644
--- a/docs/html/training/displaying-bitmaps/index.jd
+++ b/docs/html/training/displaying-bitmaps/index.jd
@@ -1,9 +1,8 @@
 page.title=Displaying Bitmaps Efficiently
+page.tags="bitmaps","images","graphics"
 
 trainingnavtop=true
 startpage=true
-next.title=Loading Large Bitmaps Efficiently
-next.link=load-bitmap.html
 
 @jd:body
 
@@ -26,7 +25,7 @@
 </div>
 </div>
 
-<p>This class covers some common techniques for processing and loading {@link
+<p>Learn how to use common techniques to process and load {@link
 android.graphics.Bitmap} objects in a way that keeps your user interface (UI) components responsive
 and avoids exceeding your application memory limit. If you're not careful, bitmaps can quickly
 consume your available memory budget leading to an application crash due to the dreaded
@@ -70,6 +69,9 @@
     <dd>This lesson walks you through using a memory and disk bitmap cache to improve the
     responsiveness and fluidity of your UI when loading multiple bitmaps.</dd>
 
+  <dt><b><a href="manage-memory.html">Managing Bitmap Memory</a></b></dt>
+    <dd>This lesson explains how to manage bitmap memory to maximize your app's performance.</dd>
+
   <dt><b><a href="display-bitmap.html">Displaying Bitmaps in Your UI</a></b></dt>
     <dd>This lesson brings everything together, showing you how to load multiple bitmaps into
     components like {@link android.support.v4.view.ViewPager} and {@link android.widget.GridView}
diff --git a/docs/html/training/displaying-bitmaps/load-bitmap.jd b/docs/html/training/displaying-bitmaps/load-bitmap.jd
index 283f272..633ffd2 100644
--- a/docs/html/training/displaying-bitmaps/load-bitmap.jd
+++ b/docs/html/training/displaying-bitmaps/load-bitmap.jd
@@ -3,8 +3,6 @@
 parent.link=index.html
 
 trainingnavtop=true
-next.title=Processing Bitmaps Off the UI Thread
-next.link=process-bitmap.html
 
 @jd:body
 
@@ -167,4 +165,4 @@
 <p>You can follow a similar process to decode bitmaps from other sources, by substituting the
 appropriate {@link
 android.graphics.BitmapFactory#decodeByteArray(byte[],int,int,android.graphics.BitmapFactory.Options)
-BitmapFactory.decode*} method as needed.</p>
\ No newline at end of file
+BitmapFactory.decode*} method as needed.</p>
diff --git a/docs/html/training/displaying-bitmaps/manage-memory.jd b/docs/html/training/displaying-bitmaps/manage-memory.jd
new file mode 100644
index 0000000..60ac2e6
--- /dev/null
+++ b/docs/html/training/displaying-bitmaps/manage-memory.jd
@@ -0,0 +1,297 @@
+page.title=Managing Bitmap Memory
+parent.title=Displaying Bitmaps Efficiently
+parent.link=index.html
+
+trainingnavtop=true
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+
+<h2>This lesson teaches you to</h2>
+<ol>
+  <li><a href="#recycle">Manage Memory on Android 2.3.3 and Lower</a></li>
+  <li><a href="#inBitmap">Manage Memory on Android 3.0 and Higher</a></li>
+</ol>
+
+<h2>You should also read</h2>
+<ul>
+  <li><a href="http://android-developers.blogspot.com/2011/03/memory-analysis-for-android.html">Memory Analysis for Android Applications</a> blog post</li>
+  <li><a href="http://www.google.com/events/io/2011/sessions/memory-management-for-android-apps.html">Memory management for Android Apps</a> Google I/O presentation</li>
+  <li><a href="{@docRoot}design/patterns/swipe-views.html">Android Design: Swipe Views</a></li>
+  <li><a href="{@docRoot}design/building-blocks/grid-lists.html">Android Design: Grid Lists</a></li>
+</ul>
+
+<h2>Try it out</h2>
+
+<div class="download-box">
+  <a href="{@docRoot}shareables/training/BitmapFun.zip" class="button">Download the sample</a>
+  <p class="filename">BitmapFun.zip</p>
+</div>
+
+</div>
+</div>
+
+<p>In addition to the steps described in <a href="cache-bitmap.html">Caching Bitmaps</a>,
+there are  specific things you can do to facilitate garbage collection
+and bitmap reuse. The recommended strategy depends on which version(s)
+of Android you are targeting. The {@code BitmapFun} sample app included with
+this class shows you how to design your app to work efficiently across
+different versions of Android.</p>
+
+<p>To set the stage for this lesson, here is how Android's management of
+bitmap memory has evolved:</p>
+<ul> 
+  <li>
+On Android Android 2.2 (API level 8) and lower, when garbage 
+collection occurs, your app's threads get stopped. This causes a lag that
+can degrade performance. 
+<strong>Android 2.3 adds concurrent garbage collection, which means that
+the memory is reclaimed soon after a bitmap is no longer referenced.</strong>
+</li>
+
+  <li>On Android 2.3.3 (API level 10) and lower, the backing pixel data for a
+bitmap is stored in native memory. It is separate from the bitmap itself,
+which is stored in the Dalvik heap. The pixel data in native memory is
+not released in a predictable manner, potentially causing an application
+to briefly exceed its memory limits and crash.
+<strong>As of Android 3.0 (API Level 11), the pixel data is stored on the
+Dalvik heap along with the associated bitmap.</strong></li>
+
+</ul>
+
+<p>The following sections describe how to optimize bitmap memory
+management for different Android versions.</p>
+
+<h2 id="recycle">Manage Memory on Android 2.3.3 and Lower</h2>
+
+<p>On Android 2.3.3 (API level 10) and lower, using 
+{@link android.graphics.Bitmap#recycle recycle()}
+is recommended. If you're displaying large amounts of bitmap data in your app,
+you're likely to run into
+{@link java.lang.OutOfMemoryError} errors. The
+{@link android.graphics.Bitmap#recycle recycle()} method allows an app
+to reclaim memory as soon as possible.</p>
+
+<p class="note"><strong>Caution:</strong> You should use
+{@link android.graphics.Bitmap#recycle recycle()} only when you are sure that the
+bitmap is no longer being used. If you call {@link android.graphics.Bitmap#recycle recycle()}
+and later attempt to draw the bitmap, you will get the error:
+{@code &quot;Canvas: trying to use a recycled bitmap&quot;}.</p>
+
+<p>The following code snippet gives an example of calling
+{@link android.graphics.Bitmap#recycle recycle()}. It uses reference counting
+(in the variables {@code mDisplayRefCount} and {@code mCacheRefCount}) to track 
+whether a bitmap is currently being displayed or in the cache. The
+code recycles the bitmap when these conditions are met:</p>
+
+<ul>
+<li>The reference count for both {@code mDisplayRefCount} and 
+{@code mCacheRefCount} is 0.</li>
+<li>The bitmap is not {@code null}, and it hasn't been recycled yet.</li>
+</ul>
+
+<pre>private int mCacheRefCount = 0;
+private int mDisplayRefCount = 0;
+...
+// Notify the drawable that the displayed state has changed.
+// Keep a count to determine when the drawable is no longer displayed.
+public void setIsDisplayed(boolean isDisplayed) {
+    synchronized (this) {
+        if (isDisplayed) {
+            mDisplayRefCount++;
+            mHasBeenDisplayed = true;
+        } else {
+            mDisplayRefCount--;
+        }
+    }
+    // Check to see if recycle() can be called.
+    checkState();
+}
+
+// Notify the drawable that the cache state has changed.
+// Keep a count to determine when the drawable is no longer being cached.
+public void setIsCached(boolean isCached) {
+    synchronized (this) {
+        if (isCached) {
+            mCacheRefCount++;
+        } else {
+            mCacheRefCount--;
+        }
+    }
+    // Check to see if recycle() can be called.
+    checkState();
+}
+
+private synchronized void checkState() {
+    // If the drawable cache and display ref counts = 0, and this drawable
+    // has been displayed, then recycle.
+    if (mCacheRefCount <= 0 && mDisplayRefCount <= 0 && mHasBeenDisplayed
+            && hasValidBitmap()) {
+        getBitmap().recycle();
+    }
+}
+
+private synchronized boolean hasValidBitmap() {
+    Bitmap bitmap = getBitmap();
+    return bitmap != null && !bitmap.isRecycled();
+}</pre>
+
+<h2 id="inBitmap">Manage Memory on Android 3.0 and Higher</h2>
+
+<p>Android 3.0 (API Level 11) introduces the
+{@link android.graphics.BitmapFactory.Options#inBitmap BitmapFactory.Options.inBitmap}
+field. If this option is set, decode methods that take the 
+{@link android.graphics.BitmapFactory.Options Options} object
+will attempt to reuse an existing bitmap when loading content. This means
+that the bitmap's memory is reused, resulting in improved performance, and
+removing both memory allocation and de-allocation. There are some caveats in using
+{@link android.graphics.BitmapFactory.Options#inBitmap}:</p>
+<ul>
+  <li>The reused bitmap must be of the same size as the source content (to make
+sure that the same amount of memory is used), and in JPEG or PNG format
+(whether as a resource or as a stream).</li>
+
+
+<li>The {@link android.graphics.Bitmap.Config configuration} of the reused bitmap
+overrides the setting of
+{@link android.graphics.BitmapFactory.Options#inPreferredConfig}, if set. </li>
+
+  <li>You should always use the returned bitmap of the decode method,
+because you can't assume that reusing the bitmap worked (for example, if there is
+a size mismatch).</li>
+
+<h3>Save a bitmap for later use</h3>
+
+<p>The following snippet demonstrates how an existing bitmap is stored for possible
+later use in the sample app. When an app is running on Android 3.0 or higher and 
+a bitmap is evicted from the {@link android.util.LruCache},
+a soft reference to the bitmap is placed
+in a {@link java.util.HashSet}, for possible reuse later with
+{@link android.graphics.BitmapFactory.Options#inBitmap}:
+
+<pre>HashSet&lt;SoftReference&lt;Bitmap&gt;&gt; mReusableBitmaps;
+private LruCache&lt;String, BitmapDrawable&gt; mMemoryCache;
+
+// If you're running on Honeycomb or newer, create
+// a HashSet of references to reusable bitmaps.
+if (Utils.hasHoneycomb()) {
+    mReusableBitmaps = new HashSet&lt;SoftReference&lt;Bitmap&gt;&gt;();
+}
+
+mMemoryCache = new LruCache&lt;String, BitmapDrawable&gt;(mCacheParams.memCacheSize) {
+
+    // Notify the removed entry that is no longer being cached.
+    &#64;Override
+    protected void entryRemoved(boolean evicted, String key,
+            BitmapDrawable oldValue, BitmapDrawable newValue) {
+        if (RecyclingBitmapDrawable.class.isInstance(oldValue)) {
+            // The removed entry is a recycling drawable, so notify it
+            // that it has been removed from the memory cache.
+            ((RecyclingBitmapDrawable) oldValue).setIsCached(false);
+        } else {
+            // The removed entry is a standard BitmapDrawable.
+            if (Utils.hasHoneycomb()) {
+                // We're running on Honeycomb or later, so add the bitmap
+                // to a SoftReference set for possible use with inBitmap later.
+                mReusableBitmaps.add
+                        (new SoftReference&lt;Bitmap&gt;(oldValue.getBitmap()));
+            }
+        }
+    }
+....
+}</pre>
+
+
+<h3>Use an existing bitmap</h3>
+<p>In the running app, decoder methods check to see if there is an existing
+bitmap they can use. For example:</p>
+
+<pre>public static Bitmap decodeSampledBitmapFromFile(String filename,
+        int reqWidth, int reqHeight, ImageCache cache) {
+
+    final BitmapFactory.Options options = new BitmapFactory.Options();
+    ...
+    BitmapFactory.decodeFile(filename, options);
+    ...
+
+    // If we're running on Honeycomb or newer, try to use inBitmap.
+    if (Utils.hasHoneycomb()) {
+        addInBitmapOptions(options, cache);
+    }
+    ...
+    return BitmapFactory.decodeFile(filename, options);
+}</pre
+
+<p>The next snippet shows the {@code addInBitmapOptions()} method that is called in the
+above snippet. It looks for an existing bitmap to set as the value for
+{@link android.graphics.BitmapFactory.Options#inBitmap}. Note that this
+method only sets a value for {@link android.graphics.BitmapFactory.Options#inBitmap}
+if it finds a suitable match (your code should never assume that a match will be found):</p>
+
+<pre>private static void addInBitmapOptions(BitmapFactory.Options options,
+        ImageCache cache) {
+    // inBitmap only works with mutable bitmaps, so force the decoder to
+    // return mutable bitmaps.
+    options.inMutable = true;
+
+    if (cache != null) {
+        // Try to find a bitmap to use for inBitmap.
+        Bitmap inBitmap = cache.getBitmapFromReusableSet(options);
+
+        if (inBitmap != null) {
+            // If a suitable bitmap has been found, set it as the value of
+            // inBitmap.
+            options.inBitmap = inBitmap;
+        }
+    }
+}
+
+// This method iterates through the reusable bitmaps, looking for one 
+// to use for inBitmap:
+protected Bitmap getBitmapFromReusableSet(BitmapFactory.Options options) {
+        Bitmap bitmap = null;
+
+    if (mReusableBitmaps != null && !mReusableBitmaps.isEmpty()) {
+        final Iterator&lt;SoftReference&lt;Bitmap&gt;&gt; iterator
+                = mReusableBitmaps.iterator();
+        Bitmap item;
+
+        while (iterator.hasNext()) {
+            item = iterator.next().get();
+
+            if (null != item && item.isMutable()) {
+                // Check to see it the item can be used for inBitmap.
+                if (canUseForInBitmap(item, options)) {
+                    bitmap = item;
+
+                    // Remove from reusable set so it can't be used again.
+                    iterator.remove();
+                    break;
+                }
+            } else {
+                // Remove from the set if the reference has been cleared.
+                iterator.remove();
+            }
+        }
+    }
+    return bitmap;
+}</pre>
+
+<p>Finally, this method determines whether a candidate bitmap
+satisfies the size criteria to be used for
+{@link android.graphics.BitmapFactory.Options#inBitmap}:</p>
+
+<pre>private static boolean canUseForInBitmap(
+        Bitmap candidate, BitmapFactory.Options targetOptions) {
+    int width = targetOptions.outWidth / targetOptions.inSampleSize;
+    int height = targetOptions.outHeight / targetOptions.inSampleSize;
+
+    // Returns true if "candidate" can be used for inBitmap re-use with
+    // "targetOptions".
+    return candidate.getWidth() == width && candidate.getHeight() == height;
+}</pre>
+
+</body>
+</html>
diff --git a/docs/html/training/displaying-bitmaps/process-bitmap.jd b/docs/html/training/displaying-bitmaps/process-bitmap.jd
index d4fcff3..272b8bc 100644
--- a/docs/html/training/displaying-bitmaps/process-bitmap.jd
+++ b/docs/html/training/displaying-bitmaps/process-bitmap.jd
@@ -3,10 +3,6 @@
 parent.link=index.html
 
 trainingnavtop=true
-next.title=Caching Bitmaps
-next.link=cache-bitmap.html
-previous.title=Loading Large Bitmaps Efficiently
-previous.link=load-bitmap.html
 
 @jd:body
 
diff --git a/docs/html/training/efficient-downloads/index.jd b/docs/html/training/efficient-downloads/index.jd
index a29be91..2ab93ae 100644
--- a/docs/html/training/efficient-downloads/index.jd
+++ b/docs/html/training/efficient-downloads/index.jd
@@ -1,9 +1,8 @@
 page.title=Transferring Data Without Draining the Battery
+page.tags="battery","network","wireless"
 
 trainingnavtop=true
 startpage=true
-next.title=Optimizing Downloads for Efficient Network Access
-next.link=efficient-network-access.html
 
 @jd:body
 
diff --git a/docs/html/training/enterprise/index.jd b/docs/html/training/enterprise/index.jd
index 0db9009..ac1b565 100644
--- a/docs/html/training/enterprise/index.jd
+++ b/docs/html/training/enterprise/index.jd
@@ -1,4 +1,5 @@
 page.title=Developing for Enterprise
+page.tags="policy","privacy"
 
 trainingnavtop=true
 startpage=true
diff --git a/docs/html/training/gestures/detector.jd b/docs/html/training/gestures/detector.jd
index 06d0e98..65ddb1b 100644
--- a/docs/html/training/gestures/detector.jd
+++ b/docs/html/training/gestures/detector.jd
@@ -25,12 +25,18 @@
    <li><a href="http://developer.android.com/guide/topics/ui/ui-events.html">Input Events</a> API Guide
     </li>
     <li><a href="{@docRoot}guide/topics/sensors/sensors_overview.html">Sensors Overview</a></li>
-    <li><a href="http://android-developers.blogspot.com/2010/06/making-sense-of-multitouch.html">Making Sense of Multitouch</a> blog post</li>
     <li><a href="{@docRoot}training/custom-views/making-interactive.html">Making the View Interactive</a> </li>
     <li>Design Guide for <a href="{@docRoot}design/patterns/gestures.html">Gestures</a></li>
     <li>Design Guide for <a href="{@docRoot}design/style/touch-feedback.html">Touch Feedback</a></li>
 </ul>
 
+<h2>Try it out</h2>
+
+<div class="download-box">
+  <a href="{@docRoot}shareables/training/InteractiveChart.zip"
+class="button">Download the sample</a>
+ <p class="filename">InteractiveChart.zip</p>
+</div>
 
 </div>
 </div>
diff --git a/docs/html/training/gestures/index.jd b/docs/html/training/gestures/index.jd
index 0191450..9d21b08 100644
--- a/docs/html/training/gestures/index.jd
+++ b/docs/html/training/gestures/index.jd
@@ -1,8 +1,8 @@
 page.title=Using Touch Gestures
+page.tags="input","navigation","gesturedetector","scroller"
+
 trainingnavtop=true
 startpage=true
-next.title=Detect Built-in Gestures
-next.link=detector.html
 
 
 @jd:body
@@ -20,12 +20,18 @@
     <li><a href="http://developer.android.com/guide/topics/ui/ui-events.html">Input Events</a> API Guide
     </li>
     <li><a href="{@docRoot}guide/topics/sensors/sensors_overview.html">Sensors Overview</a></li>
-    <li><a href="http://android-developers.blogspot.com/2010/06/making-sense-of-multitouch.html">Making Sense of Multitouch</a> blog post</li>
     <li><a href="{@docRoot}training/custom-views/making-interactive.html">Making the View Interactive</a> </li>
     <li>Design Guide for <a href="{@docRoot}design/patterns/gestures.html">Gestures</a></li>
     <li>Design Guide for <a href="{@docRoot}design/style/touch-feedback.html">Touch Feedback</a></li>
 </ul>
 
+<h2>Try it out</h2>
+
+<div class="download-box">
+  <a href="{@docRoot}shareables/training/InteractiveChart.zip"
+class="button">Download the sample</a>
+ <p class="filename">InteractiveChart.zip</p>
+</div>
 
 </div>
 </div>
diff --git a/docs/html/training/gestures/movement.jd b/docs/html/training/gestures/movement.jd
index f2c49d7..fdc1ea4 100644
--- a/docs/html/training/gestures/movement.jd
+++ b/docs/html/training/gestures/movement.jd
@@ -24,12 +24,18 @@
     <li><a href="http://developer.android.com/guide/topics/ui/ui-events.html">Input Events</a> API Guide
     </li>
     <li><a href="{@docRoot}guide/topics/sensors/sensors_overview.html">Sensors Overview</a></li>
-    <li><a href="http://android-developers.blogspot.com/2010/06/making-sense-of-multitouch.html">Making Sense of Multitouch</a> blog post</li>
     <li><a href="{@docRoot}training/custom-views/making-interactive.html">Making the View Interactive</a> </li>
     <li>Design Guide for <a href="{@docRoot}design/patterns/gestures.html">Gestures</a></li>
     <li>Design Guide for <a href="{@docRoot}design/style/touch-feedback.html">Touch Feedback</a></li>
 </ul>
 
+<h2>Try it out</h2>
+
+<div class="download-box">
+  <a href="{@docRoot}shareables/training/InteractiveChart.zip"
+class="button">Download the sample</a>
+ <p class="filename">InteractiveChart.zip</p>
+</div>
 
 </div>
 </div>
diff --git a/docs/html/training/gestures/multi.jd b/docs/html/training/gestures/multi.jd
index d4c5b1d..6a0df11 100644
--- a/docs/html/training/gestures/multi.jd
+++ b/docs/html/training/gestures/multi.jd
@@ -25,12 +25,18 @@
    <li><a href="http://developer.android.com/guide/topics/ui/ui-events.html">Input Events</a> API Guide
     </li>
     <li><a href="{@docRoot}guide/topics/sensors/sensors_overview.html">Sensors Overview</a></li>
-    <li><a href="http://android-developers.blogspot.com/2010/06/making-sense-of-multitouch.html">Making Sense of Multitouch</a> blog post</li>
     <li><a href="{@docRoot}training/custom-views/making-interactive.html">Making the View Interactive</a> </li>
     <li>Design Guide for <a href="{@docRoot}design/patterns/gestures.html">Gestures</a></li>
     <li>Design Guide for <a href="{@docRoot}design/style/touch-feedback.html">Touch Feedback</a></li>
 </ul>
 
+<h2>Try it out</h2>
+
+<div class="download-box">
+  <a href="{@docRoot}shareables/training/InteractiveChart.zip"
+class="button">Download the sample</a>
+ <p class="filename">InteractiveChart.zip</p>
+</div>
 
 </div>
 </div>
diff --git a/docs/html/training/gestures/scale.jd b/docs/html/training/gestures/scale.jd
index 17e4085..f2e4eb8 100644
--- a/docs/html/training/gestures/scale.jd
+++ b/docs/html/training/gestures/scale.jd
@@ -15,6 +15,7 @@
 <h2>This lesson teaches you to</h2>
 <ol>
   <li><a href="#drag">Drag an Object</a></li>
+  <li><a href="#pan">Drag to Pan</a></li>
   <li><a href="#scale">Use Touch to Perform Scaling</a></li>
 </ol>
 
@@ -25,20 +26,25 @@
     <li><a href="http://developer.android.com/guide/topics/ui/ui-events.html">Input Events</a> API Guide
     </li>
     <li><a href="{@docRoot}guide/topics/sensors/sensors_overview.html">Sensors Overview</a></li>
-    <li><a href="http://android-developers.blogspot.com/2010/06/making-sense-of-multitouch.html">Making Sense of Multitouch</a> blog post</li>
     <li><a href="{@docRoot}training/custom-views/making-interactive.html">Making the View Interactive</a> </li>
     <li>Design Guide for <a href="{@docRoot}design/patterns/gestures.html">Gestures</a></li>
     <li>Design Guide for <a href="{@docRoot}design/style/touch-feedback.html">Touch Feedback</a></li>
 </ul>
 
+<h2>Try it out</h2>
+
+<div class="download-box">
+  <a href="{@docRoot}shareables/training/InteractiveChart.zip"
+class="button">Download the sample</a>
+ <p class="filename">InteractiveChart.zip</p>
+</div>
 
 </div>
 </div>
+
 <p>This lesson describes how to use touch gestures to drag and scale on-screen
 objects, using {@link android.view.View#onTouchEvent onTouchEvent()} to intercept
-touch events. Here is the original <a
-href="http://code.google.com/p/android-touchexample/">source code</a>
-for the examples used in this lesson.
+touch events. 
 </p>
 
 <h2 id="drag">Drag an Object</h2>
@@ -128,17 +134,15 @@
         final float x = MotionEventCompat.getX(ev, pointerIndex);
         final float y = MotionEventCompat.getY(ev, pointerIndex);
             
-        // Only move if the ScaleGestureDetector isn't processing a gesture.
-        if (!mScaleDetector.isInProgress()) {
-            // Calculate the distance moved
-            final float dx = x - mLastTouchX;
-            final float dy = y - mLastTouchY;
+        // Calculate the distance moved
+        final float dx = x - mLastTouchX;
+        final float dy = y - mLastTouchY;
 
-            mPosX += dx;
-            mPosY += dy;
+        mPosX += dx;
+        mPosY += dy;
 
-            invalidate();
-        }
+        invalidate();
+
         // Remember this touch position for the next move event
         mLastTouchX = x;
         mLastTouchY = y;
@@ -175,6 +179,88 @@
     return true;
 }</pre>
 
+<h2 id="pan">Drag to Pan</h2>
+
+<p>The previous section showed an example of dragging an object around the screen. Another 
+common scenario is <em>panning</em>, which is when a user's dragging motion causes scrolling 
+in both the x and y axes. The above snippet directly intercepted the {@link android.view.MotionEvent} 
+actions to implement dragging. The snippet in this section takes advantage of the platform's 
+built-in support for common gestures. It overrides 
+{@link android.view.GestureDetector.OnGestureListener#onScroll onScroll()} in 
+{@link android.view.GestureDetector.SimpleOnGestureListener}.</p>
+
+<p>To provide a little more context, {@link android.view.GestureDetector.OnGestureListener#onScroll onScroll()} 
+is called when a user is dragging his finger to pan the content. 
+{@link android.view.GestureDetector.OnGestureListener#onScroll onScroll()} is only called when 
+a finger is down; as soon as the finger is lifted from the screen, the gesture either ends, 
+or a fling gesture is started (if the finger was moving with some speed just before it was lifted). 
+For more discussion of scrolling vs. flinging, see <a href="scroll.html">Animating a Scroll Gesture</a>.</p>
+
+<p>Here is the snippet for {@link android.view.GestureDetector.OnGestureListener#onScroll onScroll()}:
+
+
+<pre>// The current viewport. This rectangle represents the currently visible 
+// chart domain and range. 
+private RectF mCurrentViewport = 
+        new RectF(AXIS_X_MIN, AXIS_Y_MIN, AXIS_X_MAX, AXIS_Y_MAX);
+
+// The current destination rectangle (in pixel coordinates) into which the 
+// chart data should be drawn.
+private Rect mContentRect;
+
+private final GestureDetector.SimpleOnGestureListener mGestureListener
+            = new GestureDetector.SimpleOnGestureListener() {
+...
+
+&#64;Override
+public boolean onScroll(MotionEvent e1, MotionEvent e2, 
+            float distanceX, float distanceY) {
+    // Scrolling uses math based on the viewport (as opposed to math using pixels).
+    
+    // Pixel offset is the offset in screen pixels, while viewport offset is the
+    // offset within the current viewport. 
+    float viewportOffsetX = distanceX * mCurrentViewport.width() 
+            / mContentRect.width();
+    float viewportOffsetY = -distanceY * mCurrentViewport.height() 
+            / mContentRect.height();
+    ...
+    // Updates the viewport, refreshes the display. 
+    setViewportBottomLeft(
+            mCurrentViewport.left + viewportOffsetX,
+            mCurrentViewport.bottom + viewportOffsetY);
+    ...
+    return true;
+}</pre>
+
+<p>The implementation of {@link android.view.GestureDetector.OnGestureListener#onScroll onScroll()} 
+scrolls the viewport in response to the touch gesture:</p>
+
+<pre>
+/**
+ * Sets the current viewport (defined by mCurrentViewport) to the given
+ * X and Y positions. Note that the Y value represents the topmost pixel position, 
+ * and thus the bottom of the mCurrentViewport rectangle.
+ */
+private void setViewportBottomLeft(float x, float y) {
+    /*
+     * Constrains within the scroll range. The scroll range is simply the viewport 
+     * extremes (AXIS_X_MAX, etc.) minus the viewport size. For example, if the 
+     * extremes were 0 and 10, and the viewport size was 2, the scroll range would 
+     * be 0 to 8.
+     */
+
+    float curWidth = mCurrentViewport.width();
+    float curHeight = mCurrentViewport.height();
+    x = Math.max(AXIS_X_MIN, Math.min(x, AXIS_X_MAX - curWidth));
+    y = Math.max(AXIS_Y_MIN + curHeight, Math.min(y, AXIS_Y_MAX));
+
+    mCurrentViewport.set(x, y - curHeight, x + curWidth, y);
+
+    // Invalidates the View to update the display.
+    ViewCompat.postInvalidateOnAnimation(this);
+}
+</pre>
+
 <h2 id="scale">Use Touch to Perform Scaling</h2>
 
 <p>As discussed in <a href="detector.html">Detecting Common Gestures</a>,
@@ -191,10 +277,10 @@
 {@link android.view.ScaleGestureDetector.SimpleOnScaleGestureListener} 
 as a helper class that you can extend if you don’t care about all of the reported events.</p>
 
-<p>Here is a snippet that gives you the basic idea of how to perform scaling.
-Here is the original <a
-href="http://code.google.com/p/android-touchexample/">source code</a>
-for the examples.</p>
+
+<h3>Basic scaling example</h3>
+
+<p>Here is a snippet that illustrates the basic ingredients involved in scaling.</p>
 
 <pre>private ScaleGestureDetector mScaleDetector;
 private float mScaleFactor = 1.f;
@@ -238,3 +324,88 @@
         return true;
     }
 }</pre>
+
+
+
+
+<h3>More complex scaling example</h3>
+<p>Here is a more complex example from the {@code InteractiveChart} sample provided with this class. 
+The {@code InteractiveChart} sample supports both scrolling (panning) and scaling with multiple fingers,
+using the {@link android.view.ScaleGestureDetector} "span" 
+({@link android.view.ScaleGestureDetector#getCurrentSpanX getCurrentSpanX/Y}) and 
+"focus" ({@link android.view.ScaleGestureDetector#getFocusX getFocusX/Y}) features:</p>
+
+<pre>&#64;Override
+private RectF mCurrentViewport = 
+        new RectF(AXIS_X_MIN, AXIS_Y_MIN, AXIS_X_MAX, AXIS_Y_MAX);
+private Rect mContentRect;
+private ScaleGestureDetector mScaleGestureDetector;
+...
+public boolean onTouchEvent(MotionEvent event) {
+    boolean retVal = mScaleGestureDetector.onTouchEvent(event);
+    retVal = mGestureDetector.onTouchEvent(event) || retVal;
+    return retVal || super.onTouchEvent(event);
+}
+
+/**
+ * The scale listener, used for handling multi-finger scale gestures.
+ */
+private final ScaleGestureDetector.OnScaleGestureListener mScaleGestureListener
+        = new ScaleGestureDetector.SimpleOnScaleGestureListener() {
+    /**
+     * This is the active focal point in terms of the viewport. Could be a local
+     * variable but kept here to minimize per-frame allocations.
+     */
+    private PointF viewportFocus = new PointF();
+    private float lastSpanX;
+    private float lastSpanY;
+
+    // Detects that new pointers are going down.
+    &#64;Override
+    public boolean onScaleBegin(ScaleGestureDetector scaleGestureDetector) {
+        lastSpanX = ScaleGestureDetectorCompat.
+                getCurrentSpanX(scaleGestureDetector);
+        lastSpanY = ScaleGestureDetectorCompat.
+                getCurrentSpanY(scaleGestureDetector);
+        return true;
+    }
+
+    &#64;Override
+    public boolean onScale(ScaleGestureDetector scaleGestureDetector) {
+
+        float spanX = ScaleGestureDetectorCompat.
+                getCurrentSpanX(scaleGestureDetector);
+        float spanY = ScaleGestureDetectorCompat.
+                getCurrentSpanY(scaleGestureDetector);
+
+        float newWidth = lastSpanX / spanX * mCurrentViewport.width();
+        float newHeight = lastSpanY / spanY * mCurrentViewport.height();
+
+        float focusX = scaleGestureDetector.getFocusX();
+        float focusY = scaleGestureDetector.getFocusY();
+        // Makes sure that the chart point is within the chart region.
+        // See the sample for the implementation of hitTest().
+        hitTest(scaleGestureDetector.getFocusX(),
+                scaleGestureDetector.getFocusY(),
+                viewportFocus);
+
+        mCurrentViewport.set(
+                viewportFocus.x
+                        - newWidth * (focusX - mContentRect.left)
+                        / mContentRect.width(),
+                viewportFocus.y
+                        - newHeight * (mContentRect.bottom - focusY)
+                        / mContentRect.height(),
+                0,
+                0);
+        mCurrentViewport.right = mCurrentViewport.left + newWidth;
+        mCurrentViewport.bottom = mCurrentViewport.top + newHeight;     
+        ...
+        // Invalidates the View to update the display.
+        ViewCompat.postInvalidateOnAnimation(InteractiveLineGraphView.this);
+
+        lastSpanX = spanX;
+        lastSpanY = spanY;
+        return true;
+    }
+};</pre>
diff --git a/docs/html/training/gestures/scroll.jd b/docs/html/training/gestures/scroll.jd
index 8576948b..3e3aa14 100644
--- a/docs/html/training/gestures/scroll.jd
+++ b/docs/html/training/gestures/scroll.jd
@@ -14,6 +14,7 @@
 <!-- table of contents -->
 <h2>This lesson teaches you to</h2>
 <ol>
+  <li><a href="#term">Understand Scrolling Terminology</a></li>
   <li><a href="#scroll">Implement Touch-Based Scrolling</a></li>
 </ol>
 
@@ -24,12 +25,18 @@
     <li><a href="http://developer.android.com/guide/topics/ui/ui-events.html">Input Events</a> API Guide
     </li>
     <li><a href="{@docRoot}guide/topics/sensors/sensors_overview.html">Sensors Overview</a></li>
-    <li><a href="http://android-developers.blogspot.com/2010/06/making-sense-of-multitouch.html">Making Sense of Multitouch</a> blog post</li>
     <li><a href="{@docRoot}training/custom-views/making-interactive.html">Making the View Interactive</a> </li>
     <li>Design Guide for <a href="{@docRoot}design/patterns/gestures.html">Gestures</a></li>
     <li>Design Guide for <a href="{@docRoot}design/style/touch-feedback.html">Touch Feedback</a></li>
 </ul>
 
+<h2>Try it out</h2>
+
+<div class="download-box">
+  <a href="{@docRoot}shareables/training/InteractiveChart.zip"
+class="button">Download the sample</a>
+ <p class="filename">InteractiveChart.zip</p>
+</div>
 
 </div>
 </div>
@@ -45,7 +52,26 @@
 
 <p>You can use scrollers ({@link android.widget.Scroller} or {@link
 android.widget.OverScroller}) to collect the data you need to produce a
-scrolling animation in response to a touch event.</p>
+scrolling animation in response to a touch event. They are similar, but
+{@link android.widget.OverScroller}
+includes methods for indicating to users that they've reached the content edges 
+after a pan or fling gesture. The {@code InteractiveChart} sample 
+uses the {@link android.widget.EdgeEffect} class
+(actually the {@link android.support.v4.widget.EdgeEffectCompat} class)
+to display a "glow" effect when users reach the content edges.</p>
+
+<p class="note"><strong>Note:</strong> We recommend that you
+use {@link android.widget.OverScroller} rather than {@link
+android.widget.Scroller} for scrolling animations.
+{@link android.widget.OverScroller} provides the best backward
+compatibility with older devices.
+<br />
+Also note that you generally only need to use scrollers
+when implementing scrolling yourself. {@link android.widget.ScrollView} and
+{@link android.widget.HorizontalScrollView} do all of this for you if you nest your 
+layout within them.
+</p>
+
 
 <p>A scroller is used  to animate scrolling over time, using platform-standard
 scrolling physics (friction, velocity, etc.). The scroller itself doesn't
@@ -54,101 +80,280 @@
 responsibility to get and apply new coordinates at a rate that will make the
 scrolling animation look smooth.</p>
 
-<p class="note"><strong>Note:</strong> You generally only need to use scrollers
-when implementing scrolling yourself. {@link android.widget.ScrollView} and
-{@link android.widget.HorizontalScrollView} do all this for you do all of this for you if you nest your layout within them.</p>
-
-<h2 id = "scroll">Implement Touch-Based Scrolling</h2>
 
 
-<p>This snippet illustrates the basics of using a scroller. It uses a 
-{@link android.view.GestureDetector}, and overrides the  
-{@link android.view.GestureDetector.SimpleOnGestureListener} methods 
-{@link android.view.GestureDetector.OnGestureListener#onDown onDown()} and 
-{@link android.view.GestureDetector.OnGestureListener#onFling onFling()}. It also 
-overrides {@link android.view.GestureDetector.OnGestureListener#onScroll onScroll()} 
-to return {@code false} since you don't need to animate a scroll.</p>
+<h2 id="term">Understand Scrolling Terminology</h2>
 
+<p>"Scrolling" is a word that can take on different meanings in Android, depending on the context.</p>
 
-<p>It's common to use scrollers in conjunction with a fling gesture, but they
+<p><strong>Scrolling</strong> is the general process of moving the viewport (that is, the 'window' 
+of content you're looking at). When scrolling is in both the x and y axes, it's called 
+<em>panning</em>. The sample application provided with this class, {@code InteractiveChart}, illustrates 
+two different types of scrolling, dragging and flinging:</p>
+<ul>
+    <li><strong>Dragging</strong> is the type of scrolling that occurs when a user drags her 
+finger across the touch screen. Simple dragging is often implemented by overriding 
+{@link android.view.GestureDetector.OnGestureListener#onScroll onScroll()} in 
+{@link android.view.GestureDetector.OnGestureListener}. For more discussion of dragging, see 
+<a href="dragging.jd">Dragging and Scaling</a>.</li>
+
+    <li><strong>Flinging</strong> is the type of scrolling that occurs when a user 
+drags and lifts her finger quickly. After the user lifts her finger, you generally 
+want to keep scrolling (moving the viewport), but decelerate until the viewport stops moving. 
+Flinging can be implemented by overriding 
+{@link android.view.GestureDetector.OnGestureListener#onFling onFling()} 
+in {@link android.view.GestureDetector.OnGestureListener}, and by using 
+a scroller object. This is the use 
+case that is the topic of this lesson.</li>
+</ul>
+
+<p>It's common to use scroller objects 
+in conjunction with a fling gesture, but they
 can be used in pretty much any context where you want the UI to display
-scrolling in response to a touch event. For example, you could override {@link
-android.view.View#onTouchEvent onTouchEvent()} to process touch events directly,
-and produce a scrolling effect in response to those touch events.</p>
+scrolling in response to a touch event. For example, you could override  
+{@link android.view.View#onTouchEvent onTouchEvent()} to process touch 
+events directly, and produce a scrolling effect or a "snapping to page" animation 
+in response to those touch events.</p>
 
-<pre>
-private OverScroller mScroller = new OverScroller(context);
 
-private GestureDetector.SimpleOnGestureListener mGestureListener
+<h2 id="#scroll">Implement Touch-Based Scrolling</h2> 
+
+<p>This section describes how to use a scroller.
+The snippet shown below comes from the {@code InteractiveChart} sample 
+provided with this class.
+It uses a 
+{@link android.view.GestureDetector}, and overrides the  
+{@link android.view.GestureDetector.SimpleOnGestureListener} method 
+{@link android.view.GestureDetector.OnGestureListener#onFling onFling()}.
+It uses {@link android.widget.OverScroller} to track the fling gesture.
+If the user reaches the content edges 
+after the fling gesture, the app displays a "glow" effect.
+</p>
+
+<p class="note"><strong>Note:</strong> The {@code InteractiveChart} sample app displays a 
+chart that you can zoom, pan, scroll, and so on. In the following snippet, 
+{@code mContentRect} represents the rectangle coordinates within the view that the chart 
+will be drawn into. At any given time, a subset of the total chart domain and range are drawn 
+into this rectangular area. 
+{@code mCurrentViewport} represents the portion of the chart that is currently 
+visible in the screen. Because pixel offsets are generally treated as integers, 
+{@code mContentRect} is of the type {@link android.graphics.Rect}. Because the 
+graph domain and range are decimal/float values, {@code mCurrentViewport} is of 
+the type {@link android.graphics.RectF}.</p>
+
+<p>The first part of the snippet shows the implementation of 
+{@link android.view.GestureDetector.OnGestureListener#onFling onFling()}:</p>
+
+<pre>// The current viewport. This rectangle represents the currently visible 
+// chart domain and range. The viewport is the part of the app that the
+// user manipulates via touch gestures.
+private RectF mCurrentViewport = 
+        new RectF(AXIS_X_MIN, AXIS_Y_MIN, AXIS_X_MAX, AXIS_Y_MAX);
+
+// The current destination rectangle (in pixel coordinates) into which the 
+// chart data should be drawn.
+private Rect mContentRect;
+
+private OverScroller mScroller;
+private RectF mScrollerStartViewport;
+...
+private final GestureDetector.SimpleOnGestureListener mGestureListener
         = new GestureDetector.SimpleOnGestureListener() {
     &#64;Override
     public boolean onDown(MotionEvent e) {
-        // Abort any active scroll animations and invalidate.
+        // Initiates the decay phase of any active edge effects.
+        releaseEdgeEffects();
+        mScrollerStartViewport.set(mCurrentViewport);
+        // Aborts any active scroll animations and invalidates.
         mScroller.forceFinished(true);
-        // There is also a compatibility version: 
-        // ViewCompat.postInvalidateOnAnimation
-        postInvalidateOnAnimation();
+        ViewCompat.postInvalidateOnAnimation(InteractiveLineGraphView.this);
         return true;
     }
-
-    &#64;Override
-    public boolean onScroll(MotionEvent e1, MotionEvent e2, 
-            float distanceX, float distanceY) {
-        // You don't use a scroller in onScroll because you don't need to animate
-        // a scroll. The scroll occurs instantly in response to touch feedback.
-        return false;
-    }
-
+    ...
     &#64;Override
     public boolean onFling(MotionEvent e1, MotionEvent e2, 
             float velocityX, float velocityY) {
-        // Before flinging, abort the current animation.
-        mScroller.forceFinished(true);
-        // Begin the scroll animation
-        mScroller.fling(
-                // Current scroll position
-                startX,
-                startY,
-                // Velocities, negated for natural touch response
-                (int) -velocityX,
-                (int) -velocityY,
-                // Minimum and maximum scroll positions. The minimum scroll 
-                // position is generally zero and the maximum scroll position 
-                // is generally the content size less the screen size. So if the 
-                // content width is 1000 pixels and the screen width is 200  
-                // pixels, the maximum scroll offset should be 800 pixels.
-                minX, maxX,
-                minY, maxY,
-                // The maximum overscroll bounds. This is useful when using
-                // the EdgeEffect class to draw overscroll "glow" overlays.
-                mContentRect.width() / 2,
-                mContentRect.height() / 2);
-        // Invalidate to trigger computeScroll()
-        postInvalidateOnAnimation();
+        fling((int) -velocityX, (int) -velocityY);
         return true;
     }
 };
 
+private void fling(int velocityX, int velocityY) {
+    // Initiates the decay phase of any active edge effects.
+    releaseEdgeEffects();
+    // Flings use math in pixels (as opposed to math based on the viewport).
+    Point surfaceSize = computeScrollSurfaceSize();
+    mScrollerStartViewport.set(mCurrentViewport);
+    int startX = (int) (surfaceSize.x * (mScrollerStartViewport.left - 
+            AXIS_X_MIN) / (
+            AXIS_X_MAX - AXIS_X_MIN));
+    int startY = (int) (surfaceSize.y * (AXIS_Y_MAX - 
+            mScrollerStartViewport.bottom) / (
+            AXIS_Y_MAX - AXIS_Y_MIN));
+    // Before flinging, aborts the current animation.
+    mScroller.forceFinished(true);
+    // Begins the animation
+    mScroller.fling(
+            // Current scroll position
+            startX,
+            startY,
+            velocityX,
+            velocityY,
+            /*
+             * Minimum and maximum scroll positions. The minimum scroll 
+             * position is generally zero and the maximum scroll position 
+             * is generally the content size less the screen size. So if the 
+             * content width is 1000 pixels and the screen width is 200  
+             * pixels, the maximum scroll offset should be 800 pixels.
+             */
+            0, surfaceSize.x - mContentRect.width(),
+            0, surfaceSize.y - mContentRect.height(),
+            // The edges of the content. This comes into play when using
+            // the EdgeEffect class to draw "glow" overlays.
+            mContentRect.width() / 2,
+            mContentRect.height() / 2);
+    // Invalidates to trigger computeScroll()
+    ViewCompat.postInvalidateOnAnimation(this);
+}</pre>
+
+<p>When {@link android.view.GestureDetector.OnGestureListener#onFling onFling()} calls 
+{@link android.support.v4.view.ViewCompat#postInvalidateOnAnimation postInvalidateOnAnimation()}, 
+it triggers 
+{@link android.view.View#computeScroll computeScroll()} to update the values for x and y. 
+This is typically be done when a view child is animating a scroll using a scroller object, as in this example. </p>
+
+<p>Most views pass the scroller object's x and y position directly to 
+{@link android.view.View#scrollTo scrollTo()}. 
+The following implementation of {@link android.view.View#computeScroll computeScroll()} 
+takes a different approach&mdash;it calls 
+{@link android.widget.OverScroller#computeScrollOffset computeScrollOffset()} to get the current 
+location of x and y. When the criteria for displaying an overscroll "glow" edge effect are met 
+(the display is zoomed in, x or y is out of bounds, and the app isn't already showing an overscroll), 
+the code sets up the overscroll glow effect and calls 
+{@link android.support.v4.view.ViewCompat#postInvalidateOnAnimation postInvalidateOnAnimation()} 
+to trigger an invalidate on the view:</p>
+
+<pre>// Edge effect / overscroll tracking objects.
+private EdgeEffectCompat mEdgeEffectTop;
+private EdgeEffectCompat mEdgeEffectBottom;
+private EdgeEffectCompat mEdgeEffectLeft;
+private EdgeEffectCompat mEdgeEffectRight;
+
+private boolean mEdgeEffectTopActive;
+private boolean mEdgeEffectBottomActive;
+private boolean mEdgeEffectLeftActive;
+private boolean mEdgeEffectRightActive;
+
 &#64;Override
 public void computeScroll() {
     super.computeScroll();
 
-    // Compute the current scroll offsets. If this returns true, then the 
-    // scroll has not yet finished.
+    boolean needsInvalidate = false;
+
+    // The scroller isn't finished, meaning a fling or programmatic pan 
+    // operation is currently active.
     if (mScroller.computeScrollOffset()) {
+        Point surfaceSize = computeScrollSurfaceSize();
         int currX = mScroller.getCurrX();
         int currY = mScroller.getCurrY();
 
-        // Actually render the scrolled viewport, or actually scroll the 
-        // view using View.scrollTo.
+        boolean canScrollX = (mCurrentViewport.left > AXIS_X_MIN
+                || mCurrentViewport.right < AXIS_X_MAX);
+        boolean canScrollY = (mCurrentViewport.top > AXIS_Y_MIN
+                || mCurrentViewport.bottom < AXIS_Y_MAX);
 
-        // If currX or currY are outside the bounds, render the overscroll 
-        // glow using EdgeEffect.
+        /*          
+         * If you are zoomed in and currX or currY is
+         * outside of bounds and you're not already
+         * showing overscroll, then render the overscroll
+         * glow edge effect.
+         */
+        if (canScrollX
+                && currX < 0
+                && mEdgeEffectLeft.isFinished()
+                && !mEdgeEffectLeftActive) {
+            mEdgeEffectLeft.onAbsorb((int) 
+                    OverScrollerCompat.getCurrVelocity(mScroller));
+            mEdgeEffectLeftActive = true;
+            needsInvalidate = true;
+        } else if (canScrollX
+                && currX > (surfaceSize.x - mContentRect.width())
+                && mEdgeEffectRight.isFinished()
+                && !mEdgeEffectRightActive) {
+            mEdgeEffectRight.onAbsorb((int) 
+                    OverScrollerCompat.getCurrVelocity(mScroller));
+            mEdgeEffectRightActive = true;
+            needsInvalidate = true;
+        }
 
-    } else {
-        // The scroll has finished.
-    }
+        if (canScrollY
+                && currY < 0
+                && mEdgeEffectTop.isFinished()
+                && !mEdgeEffectTopActive) {
+            mEdgeEffectTop.onAbsorb((int) 
+                    OverScrollerCompat.getCurrVelocity(mScroller));
+            mEdgeEffectTopActive = true;
+            needsInvalidate = true;
+        } else if (canScrollY
+                && currY > (surfaceSize.y - mContentRect.height())
+                && mEdgeEffectBottom.isFinished()
+                && !mEdgeEffectBottomActive) {
+            mEdgeEffectBottom.onAbsorb((int) 
+                    OverScrollerCompat.getCurrVelocity(mScroller));
+            mEdgeEffectBottomActive = true;
+            needsInvalidate = true;
+        }
+        ...
+    }</pre>
+
+<p>Here is the section of the code that performs the actual zoom:</p>
+
+<pre>// Custom object that is functionally similar to Scroller
+Zoomer mZoomer;
+private PointF mZoomFocalPoint = new PointF();
+...
+
+// If a zoom is in progress (either programmatically or via double
+// touch), performs the zoom.
+if (mZoomer.computeZoom()) {
+    float newWidth = (1f - mZoomer.getCurrZoom()) * 
+            mScrollerStartViewport.width();
+    float newHeight = (1f - mZoomer.getCurrZoom()) * 
+            mScrollerStartViewport.height();
+    float pointWithinViewportX = (mZoomFocalPoint.x - 
+            mScrollerStartViewport.left)
+            / mScrollerStartViewport.width();
+    float pointWithinViewportY = (mZoomFocalPoint.y - 
+            mScrollerStartViewport.top)
+            / mScrollerStartViewport.height();
+    mCurrentViewport.set(
+            mZoomFocalPoint.x - newWidth * pointWithinViewportX,
+            mZoomFocalPoint.y - newHeight * pointWithinViewportY,
+            mZoomFocalPoint.x + newWidth * (1 - pointWithinViewportX),
+            mZoomFocalPoint.y + newHeight * (1 - pointWithinViewportY));
+    constrainViewport();
+    needsInvalidate = true;
+}
+if (needsInvalidate) {
+    ViewCompat.postInvalidateOnAnimation(this);
+}
+</pre>
+
+<p>This is the {@code computeScrollSurfaceSize()} method that's called in the above snippet. It 
+computes the current scrollable surface size, in pixels. For example, if the entire chart area is visible, 
+this is simply the current size of {@code mContentRect}. If the chart is zoomed in 200% in both directions, 
+the returned size will be twice as large horizontally and vertically.</p>
+
+<pre>private Point computeScrollSurfaceSize() {
+    return new Point(
+            (int) (mContentRect.width() * (AXIS_X_MAX - AXIS_X_MIN)
+                    / mCurrentViewport.width()),
+            (int) (mContentRect.height() * (AXIS_Y_MAX - AXIS_Y_MIN)
+                    / mCurrentViewport.height()));
 }</pre>
 
-<p>For another example of scroller usage, see the <a href="http://github.com/android/platform_frameworks_support/blob/master/v4/java/android/support/v4/view/ViewPager.java">source code</a> for the 
-{@link android.support.v4.view.ViewPager} class.</p>
+<p>For another example of scroller usage, see the 
+<a href="http://github.com/android/platform_frameworks_support/blob/master/v4/java/android/support/v4/view/ViewPager.java">source code</a> for the 
+{@link android.support.v4.view.ViewPager} class. It scrolls in response to flings, 
+and uses scrolling to implement the "snapping to page" animation.</p>
+
diff --git a/docs/html/training/gestures/viewgroup.jd b/docs/html/training/gestures/viewgroup.jd
index 257a5d8..5b32300 100644
--- a/docs/html/training/gestures/viewgroup.jd
+++ b/docs/html/training/gestures/viewgroup.jd
@@ -26,12 +26,19 @@
     <li><a href="http://developer.android.com/guide/topics/ui/ui-events.html">Input Events</a> API Guide
     </li>
     <li><a href="{@docRoot}guide/topics/sensors/sensors_overview.html">Sensors Overview</a></li>
-    <li><a href="http://android-developers.blogspot.com/2010/06/making-sense-of-multitouch.html">Making Sense of Multitouch</a> blog post</li>
     <li><a href="{@docRoot}training/custom-views/making-interactive.html">Making the View Interactive</a> </li>
     <li>Design Guide for <a href="{@docRoot}design/patterns/gestures.html">Gestures</a></li>
     <li>Design Guide for <a href="{@docRoot}design/style/touch-feedback.html">Touch Feedback</a></li>
 </ul>
 
+<h2>Try it out</h2>
+
+<div class="download-box">
+  <a href="{@docRoot}shareables/training/InteractiveChart.zip"
+class="button">Download the sample</a>
+ <p class="filename">InteractiveChart.zip</p>
+</div>
+
 
 </div>
 </div>
diff --git a/docs/html/training/graphics/opengl/index.jd b/docs/html/training/graphics/opengl/index.jd
index 23a734a..cf33d80 100644
--- a/docs/html/training/graphics/opengl/index.jd
+++ b/docs/html/training/graphics/opengl/index.jd
@@ -1,7 +1,6 @@
 page.title=Displaying Graphics with OpenGL ES
+page=tags="open gl","graphics"
 trainingnavtop=true
-next.title=Building an OpenGL ES Environment
-next.link=environment.html
 
 @jd:body
 
diff --git a/docs/html/training/id-auth/authenticate.jd b/docs/html/training/id-auth/authenticate.jd
index c316af7..3084bea 100644
--- a/docs/html/training/id-auth/authenticate.jd
+++ b/docs/html/training/id-auth/authenticate.jd
@@ -114,7 +114,7 @@
     new Handler(new OnError()));    // Callback called if an error occurs
 </pre>
 
-<p>In this example, <code>OnTokenAcquired</code> is a class that extends
+<p>In this example, <code>OnTokenAcquired</code> is a class that implements
 {@link android.accounts.AccountManagerCallback}. {@link android.accounts.AccountManager} calls
 {@link android.accounts.AccountManagerCallback#run run()} on <code>OnTokenAcquired</code> with an
 {@link android.accounts.AccountManagerFuture} that contains a {@link android.os.Bundle}. If
diff --git a/docs/html/training/id-auth/index.jd b/docs/html/training/id-auth/index.jd
index 140545c..2bae9c4 100644
--- a/docs/html/training/id-auth/index.jd
+++ b/docs/html/training/id-auth/index.jd
@@ -1,9 +1,8 @@
 page.title=Remembering Users
+page.tags="privacy","oauth","accounts"
 
 trainingnavtop=true
 startpage=true
-next.title=Remembering Your User
-next.link=identify.html
 
 @jd:body
 
diff --git a/docs/html/training/implementing-navigation/index.jd b/docs/html/training/implementing-navigation/index.jd
index ebb4995..990bcfe 100644
--- a/docs/html/training/implementing-navigation/index.jd
+++ b/docs/html/training/implementing-navigation/index.jd
@@ -1,9 +1,8 @@
 page.title=Implementing Effective Navigation
+page.tags="viewpager","tasks","back","up"
 
 trainingnavtop=true
 startpage=true
-next.title=Implementing Lateral Navigation
-next.link=lateral.html
 
 @jd:body
 
diff --git a/docs/html/training/implementing-navigation/lateral.jd b/docs/html/training/implementing-navigation/lateral.jd
index b59bab2..c8f57a2 100644
--- a/docs/html/training/implementing-navigation/lateral.jd
+++ b/docs/html/training/implementing-navigation/lateral.jd
@@ -43,7 +43,8 @@
 
 <p>Tabs allow the user to navigate between sibling screens by selecting the appropriate tab indicator available at the top of the display. In Android 3.0 and later, tabs are implemented using the {@link android.app.ActionBar} class, and are generally set up in {@link android.app.Activity#onCreate Activity.onCreate()}. In some cases, such as when horizontal space is limited and/or the number of tabs is large, an appropriate alternate presentation for tabs is a dropdown list (sometimes implemented using a {@link android.widget.Spinner}).</p>
 
-<p>In previous versions of Android, tabs could be implemented using a {@link android.widget.TabWidget} and {@link android.widget.TabHost}. For details, see the <a href="{@docRoot}resources/tutorials/views/hello-tabwidget.html">Hello, Views</a> tutorial.</p>
+<p>In previous versions of Android, tabs could be implemented using a
+{@link android.widget.TabWidget} and {@link android.widget.TabHost}.</p>
 
 <p>As of Android 3.0, however, you should use either {@link android.app.ActionBar#NAVIGATION_MODE_TABS} or {@link android.app.ActionBar#NAVIGATION_MODE_LIST} along with the {@link android.app.ActionBar} class.</p>
 
@@ -131,6 +132,9 @@
     ViewPager mViewPager;
 
     public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_collection_demo);
+
         // ViewPager and its adapters use support library
         // fragments, so use getSupportFragmentManager.
         mDemoCollectionPagerAdapter =
diff --git a/docs/html/training/improving-layouts/index.jd b/docs/html/training/improving-layouts/index.jd
index a0ac13e..af29d3f 100644
--- a/docs/html/training/improving-layouts/index.jd
+++ b/docs/html/training/improving-layouts/index.jd
@@ -1,4 +1,5 @@
 page.title=Improving Layout Performance
+page.tags="include","merge","viewstub","listview"
 
 trainingnavtop=true
 startpage=true
diff --git a/docs/html/training/in-app-billing/index.jd b/docs/html/training/in-app-billing/index.jd
index 3d07481..94708b8 100644
--- a/docs/html/training/in-app-billing/index.jd
+++ b/docs/html/training/in-app-billing/index.jd
@@ -1,4 +1,5 @@
 page.title=Selling In-app Products
+page.tags="billing"
 
 trainingnavtop=true
 startpage=true
diff --git a/docs/html/training/in-app-billing/list-iab-products.jd b/docs/html/training/in-app-billing/list-iab-products.jd
index 36ff34a..c423fc1 100644
--- a/docs/html/training/in-app-billing/list-iab-products.jd
+++ b/docs/html/training/in-app-billing/list-iab-products.jd
@@ -54,7 +54,7 @@
 <li>The {@code List} argument consists of one or more product IDs (also called SKUs) for the products that you want to query.</li>
 <li>Finally, the {@code QueryInventoryFinishedListener} argument specifies a listener is notified when the query operation has completed and handles the query response.</li>
 </ul>
-If you use the the convenience classes provided in the sample, the classes will handle background thread management for In-app Billing requests, so you can safely make queries from the main thread of your application.
+If you use the convenience classes provided in the sample, the classes will handle background thread management for In-app Billing requests, so you can safely make queries from the main thread of your application.
 </p>
 <p>The following code shows how you can retrieve the details for two products with IDs {@code SKU_APPLE} and {@code SKU_BANANA} that you previously defined in the Developer Console.</p>
 
diff --git a/docs/html/training/in-app-billing/preparing-iab-app.jd b/docs/html/training/in-app-billing/preparing-iab-app.jd
index a7b3528..4698cf7 100644
--- a/docs/html/training/in-app-billing/preparing-iab-app.jd
+++ b/docs/html/training/in-app-billing/preparing-iab-app.jd
@@ -33,15 +33,15 @@
 <p>Before you can start using the In-app Billing service, you'll need to add the library that contains the In-app Billing Version 3 API to your Android project. You also need to setting the permissions for your application to communicate with Google Play. In addition, you'll need to establish a connection between your application and  Google Play. You should also verify that the In-app Billing API version that you are using in your application is supported by Google Play.</p>
 
 <h2 id="GetSample">Download the Sample Application</h2>
-<p>In this training class, you will use a reference implementation for the In-app Billing Version 3 API called the {@code TrivialDrive} sample application. The sample includes convenience classes to quickly set up the In-app Billing service, marshal and unmarshal data types, and handle In-app Billing requests from the main thread of your application.  </p>
+<p>In this training class, you will use a reference implementation for the In-app Billing Version 3 API called the {@code TrivialDrive} sample application. The sample includes convenience classes to quickly set up the In-app Billing service, marshal and unmarshal data types, and handle In-app Billing requests from the main thread of your application.</p>
 <p>To download the sample application:</p>
 <ol>
 <li>Open the <a href="{@docRoot}tools/help/sdk-manager.html">Android SDK Manager</a>.</li>
 <li>In the SDK Manager, expand the {@code Extras} section.</li>
-<li>Select <strong>Google Play Billing Library</strong>. Make sure to select the download for In-app Billing Version 3 or above.</li>
-<li>Click <strong>Install</strong> to complete the download.</li>
+<li>Select <strong>Google Play Billing Library</strong>.</li>
+<li>Click <strong>Install packages</strong> to complete the download.</li>
 </ol>
-<p>The sample files will be installed to {@code /your/sdk/location/extras/google/play_billing/in-app-billing-v03}.</p>
+<p>The sample files will be installed to {@code &lt;sdk&gt;/extras/google/play_billing/}.</p>
 
 <h2 id="AddToDevConsole">Add Your Application to the Developer Console</h2>
 <p>The Google Play Developer Console is where you publish your In-app Billing application and  manage the various digital goods that are available for purchase from your application. When you create a new application entry in the Developer Console, it automatically generates a public license key for your application. You will need this key to establish a trusted connection from your application to the Google Play servers. You only need to generate this key once per application, and don’t need to repeat these steps when you update the APK file for your application.</p>
@@ -133,6 +133,7 @@
 <pre>
 &#64;Override
 public void onDestroy() {
+   super.onDestroy();
    if (mHelper != null) mHelper.dispose();
    mHelper = null;
 }
diff --git a/docs/html/training/in-app-billing/purchase-iab-products.jd b/docs/html/training/in-app-billing/purchase-iab-products.jd
index 7fa77d3..4e6e035 100644
--- a/docs/html/training/in-app-billing/purchase-iab-products.jd
+++ b/docs/html/training/in-app-billing/purchase-iab-products.jd
@@ -104,7 +104,7 @@
 </pre>
 
 <h2 id="Consume">Consume a Purchase</h2>
-<p>You can use the In-app Billing Version 3 API to track the ownership of purchased items in Google Play. Once an item is purchased, it is considered to be "owned" and cannot be purchased again from Google Play while in that state. You must send a consumption request for the item before Google Play makes it available for purchase again. All managed in-app products are consumable.  How you use the consumption mechanism in your app is up to you. Typically, you would implement consumption for products with temporary benefits that users may want to purchase multiple times (for example, in-game currency or replensihable game tokens). You would typically not want to implement consumption for products that are purchased once and provide a permanent effect (for example, a premium upgrade).</p>
+<p>You can use the In-app Billing Version 3 API to track the ownership of purchased items in Google Play. Once an item is purchased, it is considered to be "owned" and cannot be purchased again from Google Play while in that state. You must send a consumption request for the item before Google Play makes it available for purchase again. All managed in-app products are consumable.  How you use the consumption mechanism in your app is up to you. Typically, you would implement consumption for products with temporary benefits that users may want to purchase multiple times (for example, in-game currency or replenishable game tokens). You would typically not want to implement consumption for products that are purchased once and provide a permanent effect (for example, a premium upgrade).</p>
 <p>It's your responsibility to control and track how the in-app product is provisioned to the user. For example, if the user purchased in-game currency, you should update the player's inventory with the amount of currency purchased.</p>
 <p class="note"><strong>Security Recommendation:</strong> You must send a consumption request before provisioning the benefit of the consumable in-app purchase to the user. Make sure that you have received a successful consumption response from Google Play before you provision the item.</p>
 <p>To record a purchase consumption, call {@code consumeAsync(Purchase, OnConsumeFinishedListener)} on your {@code IabHelper} instance. The first argument that the method takes is the {@code Purchase} object representing the item to consume. The second argument is a {@code OnConsumeFinishedListener} that is notified when the consumption operation has completed and handles the consumption response from Google Play. It is safe to make this call fom your main thread.</p>
diff --git a/docs/html/training/keyboard-input/index.jd b/docs/html/training/keyboard-input/index.jd
index ba4e598..7ac79e6 100644
--- a/docs/html/training/keyboard-input/index.jd
+++ b/docs/html/training/keyboard-input/index.jd
@@ -1,4 +1,5 @@
 page.title=Handling Keyboard Input
+page.tags="edittext","accessibility"
 
 trainingnavtop=true
 startpage=true
diff --git a/docs/html/training/load-data-background/index.jd b/docs/html/training/load-data-background/index.jd
index dc9d84a..221ae57 100644
--- a/docs/html/training/load-data-background/index.jd
+++ b/docs/html/training/load-data-background/index.jd
@@ -1,4 +1,6 @@
 page.title=Loading Data in the Background
+page.tags="cursorloader"
+
 trainingnavtop=true
 startpage=true
 
diff --git a/docs/html/training/managing-audio/index.jd b/docs/html/training/managing-audio/index.jd
index 0f7bbfd..3e3bcf0 100644
--- a/docs/html/training/managing-audio/index.jd
+++ b/docs/html/training/managing-audio/index.jd
@@ -1,9 +1,8 @@
 page.title=Managing Audio Playback
+page.tags="audio","media"
 
 trainingnavtop=true
 startpage=true
-next.title=Controlling Your App's Volume and Playback
-next.link=volume-playback.html
 
 @jd:body
 
diff --git a/docs/html/training/monitoring-device-state/docking-monitoring.jd b/docs/html/training/monitoring-device-state/docking-monitoring.jd
index 3787a55..5c8bfd6 100644
--- a/docs/html/training/monitoring-device-state/docking-monitoring.jd
+++ b/docs/html/training/monitoring-device-state/docking-monitoring.jd
@@ -79,7 +79,7 @@
 
 <h2 id="MonitorDockState">Monitor for Changes in the Dock State or Type</h2> 
 
-<p>Whenever the the device is docked or undocked, the {@link
+<p>Whenever the device is docked or undocked, the {@link
 android.content.Intent#ACTION_DOCK_EVENT} action is broadcast. To monitor changes in the
 device's dock-state, simply register a broadcast receiver in your application manifest as shown in
 the snippet below:</p>
diff --git a/docs/html/training/monitoring-device-state/index.jd b/docs/html/training/monitoring-device-state/index.jd
index 585b669..c3d700a 100644
--- a/docs/html/training/monitoring-device-state/index.jd
+++ b/docs/html/training/monitoring-device-state/index.jd
@@ -1,9 +1,8 @@
 page.title=Optimizing Battery Life
+page.tags="network","internet"
 
 trainingnavtop=true
 startpage=true
-next.title=Monitoring the Battery Level and Charging State
-next.link=battery-monitoring.html
 
 @jd:body
 
diff --git a/docs/html/training/multiple-apks/index.jd b/docs/html/training/multiple-apks/index.jd
index 37286c3..5754da9 100644
--- a/docs/html/training/multiple-apks/index.jd
+++ b/docs/html/training/multiple-apks/index.jd
@@ -1,9 +1,8 @@
 page.title=Maintaining Multiple APKs
+page.tags="support"
 
 trainingnavtop=true
 startpage=true
-next.title=Creating Multiple APKs for Different API Levels
-next.link=api.html
 
 @jd:body
 
diff --git a/docs/html/training/multiple-threads/define-runnable.jd b/docs/html/training/multiple-threads/define-runnable.jd
index 17640a9..40853d3 100644
--- a/docs/html/training/multiple-threads/define-runnable.jd
+++ b/docs/html/training/multiple-threads/define-runnable.jd
@@ -98,7 +98,7 @@
         android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND);
         ...
         /*
-         * Stores the current Thread in the the PhotoTask instance,
+         * Stores the current Thread in the PhotoTask instance,
          * so that the instance
          * can interrupt the Thread.
          */
diff --git a/docs/html/training/multiple-threads/index.jd b/docs/html/training/multiple-threads/index.jd
index 3ea57c5..cbd42b4 100644
--- a/docs/html/training/multiple-threads/index.jd
+++ b/docs/html/training/multiple-threads/index.jd
@@ -1,4 +1,5 @@
 page.title=Sending Operations to Multiple Threads
+page.tags="threadpool","runnable"
 
 trainingnavtop=true
 startpage=true
diff --git a/docs/html/training/multiscreen/index.jd b/docs/html/training/multiscreen/index.jd
index 23f6564..d09540e 100644
--- a/docs/html/training/multiscreen/index.jd
+++ b/docs/html/training/multiscreen/index.jd
@@ -1,9 +1,8 @@
 page.title=Designing for Multiple Screens
+page.tags="tablet","tv","fragments","support"
 
 trainingnavtop=true
 startpage=true
-next.title=Supporting Different Screen Sizes
-next.link=screensizes.html
 
 @jd:body
 
diff --git a/docs/html/training/notify-user/build-notification.jd b/docs/html/training/notify-user/build-notification.jd
index ba66028..80f2cd5 100644
--- a/docs/html/training/notify-user/build-notification.jd
+++ b/docs/html/training/notify-user/build-notification.jd
@@ -149,12 +149,14 @@
 <p>For example:</p>
 
 <pre>
+NotificationCompat.Builder mBuilder;
+...
 // Sets an ID for the notification
 int mNotificationId = 001;
 // Gets an instance of the NotificationManager service
 NotificationManager mNotifyMgr = 
         (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
 // Builds the notification and issues it.
-mNotifyMgr.notify(mNotificationId, builder.build());
+mNotifyMgr.notify(mNotificationId, mBuilder.build());
 </pre>
 
diff --git a/docs/html/training/notify-user/index.jd b/docs/html/training/notify-user/index.jd
index 510f2c4..51f058f 100644
--- a/docs/html/training/notify-user/index.jd
+++ b/docs/html/training/notify-user/index.jd
@@ -1,8 +1,8 @@
 page.title=Notifying the User
+page.tags="notifications"
+
 trainingnavtop=true
 startpage=true
-next.title=Build a Notification
-next.link=build-notification.html
 
 
 @jd:body
diff --git a/docs/html/training/run-background-service/index.jd b/docs/html/training/run-background-service/index.jd
index 173b87a..3360df5 100644
--- a/docs/html/training/run-background-service/index.jd
+++ b/docs/html/training/run-background-service/index.jd
@@ -1,7 +1,11 @@
 page.title=Running in a Background Service
+page.tags="intentservice"
+
 trainingnavtop=true
 startpage=true
+
 @jd:body
+
 <div id="tb-wrapper">
 <div id="tb">
 <h2>Dependencies and prerequisites</h2>
diff --git a/docs/html/training/search/index.jd b/docs/html/training/search/index.jd
index bfd1618..4070372 100644
--- a/docs/html/training/search/index.jd
+++ b/docs/html/training/search/index.jd
@@ -1,8 +1,8 @@
 page.title=Adding Search Functionality
+page.tags="searchview","database"
+
 trainingnavtop=true
 startpage=true
-next.title=Setting Up the Search Interface
-next.link=setup.html
 
 @jd:body
 
diff --git a/docs/html/training/sharing/index.jd b/docs/html/training/sharing/index.jd
index c2e8dbc..2aa22b6 100644
--- a/docs/html/training/sharing/index.jd
+++ b/docs/html/training/sharing/index.jd
@@ -1,9 +1,8 @@
 page.title=Sharing Content
+page.tags="intents","share"
 
 trainingnavtop=true
 startpage=true
-next.title=Sending Content to Other Apps
-next.link=send.html
 
 @jd:body
 
diff --git a/docs/html/training/training_toc.cs b/docs/html/training/training_toc.cs
index 40273f8..7a3f2ca 100644
--- a/docs/html/training/training_toc.cs
+++ b/docs/html/training/training_toc.cs
@@ -287,6 +287,10 @@
             Caching Bitmaps
           </a>
           </li>
+          <li><a href="<?cs var:toroot ?>training/displaying-bitmaps/manage-memory.html">
+            Managing Bitmap Memory
+          </a>
+          </li>
           <li><a href="<?cs var:toroot ?>training/displaying-bitmaps/display-bitmap.html">
             Displaying Bitmaps in Your UI
           </a></li>
diff --git a/docs/html/training/tv/index.jd b/docs/html/training/tv/index.jd
index ae13c4a..9d15f46 100644
--- a/docs/html/training/tv/index.jd
+++ b/docs/html/training/tv/index.jd
@@ -1,9 +1,8 @@
 page.title=Designing for TV
+page.tags="input","screens"
 
 trainingnavtop=true
 startpage=true
-next.title=Optimizing layouts for TV
-next.link=optimizing-layouts-tv.html
 
 @jd:body
 
diff --git a/graphics/java/android/graphics/DashPathEffect.java b/graphics/java/android/graphics/DashPathEffect.java
index 4f16dc4..2bdecce 100644
--- a/graphics/java/android/graphics/DashPathEffect.java
+++ b/graphics/java/android/graphics/DashPathEffect.java
@@ -26,7 +26,7 @@
      * controls the length of the dashes. The paint's strokeWidth controls the
      * thickness of the dashes.
      * Note: this patheffect only affects drawing with the paint's style is set
-     * to STROKE or STROKE_AND_FILL. It is ignored if the drawing is done with
+     * to STROKE or FILL_AND_STROKE. It is ignored if the drawing is done with
      * style == FILL.
      * @param intervals array of ON and OFF distances
      * @param phase offset into the intervals array
diff --git a/graphics/java/android/graphics/Path.java b/graphics/java/android/graphics/Path.java
index b4f1e84d..f6b5ffc 100644
--- a/graphics/java/android/graphics/Path.java
+++ b/graphics/java/android/graphics/Path.java
@@ -59,6 +59,10 @@
         int valNative = 0;
         if (src != null) {
             valNative = src.mNativePath;
+            isSimplePath = src.isSimplePath;
+            if (src.rects != null) {
+                rects = new Region(src.rects);
+            }
         }
         mNativePath = init2(valNative);
         mDetectSimplePaths = HardwareRenderer.isAvailable();
@@ -544,6 +548,7 @@
         int dstNative = 0;
         if (dst != null) {
             dstNative = dst.mNativePath;
+            dst.isSimplePath = false;
         }
         native_offset(mNativePath, dx, dy, dstNative);
     }
@@ -555,6 +560,7 @@
      * @param dy The amount in the Y direction to offset the entire path
      */
     public void offset(float dx, float dy) {
+        isSimplePath = false;
         native_offset(mNativePath, dx, dy);
     }
 
@@ -580,6 +586,7 @@
     public void transform(Matrix matrix, Path dst) {
         int dstNative = 0;
         if (dst != null) {
+            dst.isSimplePath = false;
             dstNative = dst.mNativePath;
         }
         native_transform(mNativePath, matrix.native_instance, dstNative);
@@ -591,6 +598,7 @@
      * @param matrix The matrix to apply to the path
      */
     public void transform(Matrix matrix) {
+        isSimplePath = false;
         native_transform(mNativePath, matrix.native_instance);
     }
 
diff --git a/graphics/java/android/graphics/Point.java b/graphics/java/android/graphics/Point.java
index 338e880a..e0d8ccc 100644
--- a/graphics/java/android/graphics/Point.java
+++ b/graphics/java/android/graphics/Point.java
@@ -70,20 +70,29 @@
         return this.x == x && this.y == y;
     }
 
-    @Override public boolean equals(Object o) {
-        if (o instanceof Point) {
-            Point p = (Point) o;
-            return this.x == p.x && this.y == p.y;
-        }
-        return false;
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        Point point = (Point) o;
+
+        if (x != point.x) return false;
+        if (y != point.y) return false;
+
+        return true;
     }
 
-    @Override public int hashCode() {
-        return x * 32713 + y;
+    @Override
+    public int hashCode() {
+        int result = x;
+        result = 31 * result + y;
+        return result;
     }
 
-    @Override public String toString() {
-        return "Point(" + x + ", " + y+ ")";
+    @Override
+    public String toString() {
+        return "Point(" + x + ", " + y + ")";
     }
 
     /**
diff --git a/graphics/java/android/graphics/PointF.java b/graphics/java/android/graphics/PointF.java
index e00271f..ee38dbb 100644
--- a/graphics/java/android/graphics/PointF.java
+++ b/graphics/java/android/graphics/PointF.java
@@ -73,6 +73,31 @@
         return this.x == x && this.y == y; 
     }
 
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        PointF pointF = (PointF) o;
+
+        if (Float.compare(pointF.x, x) != 0) return false;
+        if (Float.compare(pointF.y, y) != 0) return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = (x != +0.0f ? Float.floatToIntBits(x) : 0);
+        result = 31 * result + (y != +0.0f ? Float.floatToIntBits(y) : 0);
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        return "PointF(" + x + ", " + y + ")";
+    }
+
     /**
      * Return the euclidian distance from (0,0) to the point
      */
diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java
index 41b272d..8280d2d 100644
--- a/graphics/java/android/graphics/drawable/DrawableContainer.java
+++ b/graphics/java/android/graphics/drawable/DrawableContainer.java
@@ -491,6 +491,8 @@
                 mComputedConstantSize = orig.mComputedConstantSize;
                 mConstantWidth = orig.mConstantWidth;
                 mConstantHeight = orig.mConstantHeight;
+                mConstantMinimumWidth = orig.mConstantMinimumWidth;
+                mConstantMinimumHeight = orig.mConstantMinimumHeight;
                 
                 mOpacity = orig.mOpacity;
                 mHaveStateful = orig.mHaveStateful;
diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java
index 0623a9e..b966bb4 100644
--- a/graphics/java/android/graphics/drawable/GradientDrawable.java
+++ b/graphics/java/android/graphics/drawable/GradientDrawable.java
@@ -479,7 +479,7 @@
             mFillPaint.setDither(mDither);
             mFillPaint.setColorFilter(mColorFilter);
             if (mColorFilter != null && !mGradientState.mHasSolidColor) {
-                mFillPaint.setColor(0xff000000);
+                mFillPaint.setColor(mAlpha << 24);
             }
             if (haveStroke) {
                 mStrokePaint.setAlpha(currStrokeAlpha);
@@ -743,7 +743,7 @@
                     mFillPaint.setShader(new LinearGradient(x0, y0, x1, y1,
                             colors, st.mPositions, Shader.TileMode.CLAMP));
                     if (!mGradientState.mHasSolidColor) {
-                        mFillPaint.setColor(0xff000000);
+                        mFillPaint.setColor(mAlpha << 24);
                     }
                 } else if (st.mGradient == RADIAL_GRADIENT) {
                     x0 = r.left + (r.right - r.left) * st.mCenterX;
@@ -755,7 +755,7 @@
                             level * st.mGradientRadius, colors, null,
                             Shader.TileMode.CLAMP));
                     if (!mGradientState.mHasSolidColor) {
-                        mFillPaint.setColor(0xff000000);
+                        mFillPaint.setColor(mAlpha << 24);
                     }
                 } else if (st.mGradient == SWEEP_GRADIENT) {
                     x0 = r.left + (r.right - r.left) * st.mCenterX;
@@ -788,7 +788,7 @@
                     }
                     mFillPaint.setShader(new SweepGradient(x0, y0, tempColors, tempPositions));
                     if (!mGradientState.mHasSolidColor) {
-                        mFillPaint.setColor(0xff000000);
+                        mFillPaint.setColor(mAlpha << 24);
                     }
                 }
             }
diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java
index 0351b71..dd692c6 100644
--- a/graphics/java/android/graphics/drawable/LayerDrawable.java
+++ b/graphics/java/android/graphics/drawable/LayerDrawable.java
@@ -575,10 +575,6 @@
     @Override
     public Drawable mutate() {
         if (!mMutated && super.mutate() == this) {
-            if (!mLayerState.canConstantState()) {
-                throw new IllegalStateException("One or more children of this LayerDrawable does " +
-                        "not have constant state; this drawable cannot be mutated.");
-            }
             mLayerState = new LayerState(mLayerState, this, null);
             final ChildDrawable[] array = mLayerState.mChildren;
             final int N = mLayerState.mNum;
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index 0107da4..dfef47e 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -1526,7 +1526,8 @@
     if (navigation != o.navigation) diffs |= CONFIG_NAVIGATION;
     if (screenSize != o.screenSize) diffs |= CONFIG_SCREEN_SIZE;
     if (version != o.version) diffs |= CONFIG_VERSION;
-    if (screenLayout != o.screenLayout) diffs |= CONFIG_SCREEN_LAYOUT;
+    if ((screenLayout & MASK_LAYOUTDIR) != (o.screenLayout & MASK_LAYOUTDIR)) diffs |= CONFIG_LAYOUTDIR;
+    if ((screenLayout & ~MASK_LAYOUTDIR) != (o.screenLayout & ~MASK_LAYOUTDIR)) diffs |= CONFIG_SCREEN_LAYOUT;
     if (uiMode != o.uiMode) diffs |= CONFIG_UI_MODE;
     if (smallestScreenWidthDp != o.smallestScreenWidthDp) diffs |= CONFIG_SMALLEST_SCREEN_SIZE;
     if (screenSizeDp != o.screenSizeDp) diffs |= CONFIG_SCREEN_SIZE;
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 6787705..bc30738 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -339,6 +339,7 @@
     size_t count = mFunctors.size();
 
     if (count > 0) {
+        interrupt();
         SortedVector<Functor*> functors(mFunctors);
         mFunctors.clear();
 
@@ -365,10 +366,7 @@
                 mFunctors.add(f);
             }
         }
-        // protect against functors binding to other buffers
-        mCaches.unbindMeshBuffer();
-        mCaches.unbindIndicesBuffer();
-        mCaches.activeTexture(0);
+        resume();
     }
 
     return result;
diff --git a/location/java/android/location/Geofence.java b/location/java/android/location/Geofence.java
index 5fef626..5de779a 100644
--- a/location/java/android/location/Geofence.java
+++ b/location/java/android/location/Geofence.java
@@ -38,8 +38,8 @@
     /**
      * Create a circular geofence (on a flat, horizontal plane).
      *
-     * @param latitude latitude in degrees
-     * @param longitude longitude in degrees
+     * @param latitude latitude in degrees, between -90 and +90 inclusive
+     * @param longitude longitude in degrees, between -180 and +180 inclusive
      * @param radius radius in meters
      * @return a new geofence
      * @throws IllegalArgumentException if any parameters are out of range
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index 315196e..ef97d2a 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -157,6 +157,7 @@
     private static final int MSG_BROADCAST_AUDIO_BECOMING_NOISY = 25;
     private static final int MSG_CONFIGURE_SAFE_MEDIA_VOLUME = 26;
     private static final int MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED = 27;
+    private static final int MSG_PERSIST_SAFE_VOLUME_STATE = 28;
 
     // flags for MSG_PERSIST_VOLUME indicating if current and/or last audible volume should be
     // persisted
@@ -436,6 +437,8 @@
 
     private boolean mDockAudioMediaEnabled = true;
 
+    private int mDockState = Intent.EXTRA_DOCK_STATE_UNDOCKED;
+
     ///////////////////////////////////////////////////////////////////////////
     // Construction
     ///////////////////////////////////////////////////////////////////////////
@@ -479,6 +482,14 @@
                 null,
                 0);
 
+        mSafeMediaVolumeState = new Integer(Settings.Global.getInt(mContentResolver,
+                                                        Settings.Global.AUDIO_SAFE_VOLUME_STATE,
+                                                        SAFE_MEDIA_VOLUME_NOT_CONFIGURED));
+        // The default safe volume index read here will be replaced by the actual value when
+        // the mcc is read by onConfigureSafeVolume()
+        mSafeMediaVolumeIndex = mContext.getResources().getInteger(
+                com.android.internal.R.integer.config_safe_media_volume_index) * 10;
+
         readPersistedSettings();
         mSettingsObserver = new SettingsObserver();
         updateStreamVolumeAlias(false /*updateVolumes*/);
@@ -486,8 +497,6 @@
 
         mMediaServerOk = true;
 
-        mSafeMediaVolumeState = new Integer(SAFE_MEDIA_VOLUME_NOT_CONFIGURED);
-
         // Call setRingerModeInt() to apply correct mute
         // state on streams affected by ringer mode.
         mRingerModeMutedStreams = 0;
@@ -820,70 +829,72 @@
         // convert one UI step (+/-1) into a number of internal units on the stream alias
         int step = rescaleIndex(10, streamType, streamTypeAlias);
 
-        if ((direction == AudioManager.ADJUST_RAISE) &&
-                !checkSafeMediaVolume(streamTypeAlias, aliasIndex + step, device)) {
-            return;
-        }
-
         int index;
         int oldIndex;
 
-        flags &= ~AudioManager.FLAG_FIXED_VOLUME;
-        if ((streamTypeAlias == AudioSystem.STREAM_MUSIC) &&
-               ((device & mFixedVolumeDevices) != 0)) {
-            flags |= AudioManager.FLAG_FIXED_VOLUME;
-            index = mStreamStates[streamType].getMaxIndex();
+        if ((direction == AudioManager.ADJUST_RAISE) &&
+                !checkSafeMediaVolume(streamTypeAlias, aliasIndex + step, device)) {
+            index = mStreamStates[streamType].getIndex(device,
+                                                 (streamState.muteCount() != 0)  /* lastAudible */);
             oldIndex = index;
         } else {
-            // If either the client forces allowing ringer modes for this adjustment,
-            // or the stream type is one that is affected by ringer modes
-            if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) ||
-                    (streamTypeAlias == getMasterStreamType())) {
-                int ringerMode = getRingerMode();
-                // do not vibrate if already in vibrate mode
-                if (ringerMode == AudioManager.RINGER_MODE_VIBRATE) {
-                    flags &= ~AudioManager.FLAG_VIBRATE;
-                }
-                // Check if the ringer mode changes with this volume adjustment. If
-                // it does, it will handle adjusting the volume, so we won't below
-                adjustVolume = checkForRingerModeChange(aliasIndex, direction, step);
-                if ((streamTypeAlias == getMasterStreamType()) &&
-                        (mRingerMode == AudioManager.RINGER_MODE_SILENT)) {
-                    streamState.setLastAudibleIndex(0, device);
-                }
-            }
-
-            // If stream is muted, adjust last audible index only
-            oldIndex = mStreamStates[streamType].getIndex(device,
-                    (mStreamStates[streamType].muteCount() != 0) /* lastAudible */);
-
-            if (streamState.muteCount() != 0) {
-                if (adjustVolume) {
-                    // Post a persist volume msg
-                    // no need to persist volume on all streams sharing the same alias
-                    streamState.adjustLastAudibleIndex(direction * step, device);
-                    sendMsg(mAudioHandler,
-                            MSG_PERSIST_VOLUME,
-                            SENDMSG_QUEUE,
-                            PERSIST_LAST_AUDIBLE,
-                            device,
-                            streamState,
-                            PERSIST_DELAY);
-                }
-                index = mStreamStates[streamType].getIndex(device, true  /* lastAudible */);
+            flags &= ~AudioManager.FLAG_FIXED_VOLUME;
+            if ((streamTypeAlias == AudioSystem.STREAM_MUSIC) &&
+                   ((device & mFixedVolumeDevices) != 0)) {
+                flags |= AudioManager.FLAG_FIXED_VOLUME;
+                index = mStreamStates[streamType].getMaxIndex();
+                oldIndex = index;
             } else {
-                if (adjustVolume && streamState.adjustIndex(direction * step, device)) {
-                    // Post message to set system volume (it in turn will post a message
-                    // to persist). Do not change volume if stream is muted.
-                    sendMsg(mAudioHandler,
-                            MSG_SET_DEVICE_VOLUME,
-                            SENDMSG_QUEUE,
-                            device,
-                            0,
-                            streamState,
-                            0);
+                // If either the client forces allowing ringer modes for this adjustment,
+                // or the stream type is one that is affected by ringer modes
+                if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) ||
+                        (streamTypeAlias == getMasterStreamType())) {
+                    int ringerMode = getRingerMode();
+                    // do not vibrate if already in vibrate mode
+                    if (ringerMode == AudioManager.RINGER_MODE_VIBRATE) {
+                        flags &= ~AudioManager.FLAG_VIBRATE;
+                    }
+                    // Check if the ringer mode changes with this volume adjustment. If
+                    // it does, it will handle adjusting the volume, so we won't below
+                    adjustVolume = checkForRingerModeChange(aliasIndex, direction, step);
+                    if ((streamTypeAlias == getMasterStreamType()) &&
+                            (mRingerMode == AudioManager.RINGER_MODE_SILENT)) {
+                        streamState.setLastAudibleIndex(0, device);
+                    }
                 }
-                index = mStreamStates[streamType].getIndex(device, false  /* lastAudible */);
+
+                // If stream is muted, adjust last audible index only
+                oldIndex = mStreamStates[streamType].getIndex(device,
+                        (mStreamStates[streamType].muteCount() != 0) /* lastAudible */);
+
+                if (streamState.muteCount() != 0) {
+                    if (adjustVolume) {
+                        // Post a persist volume msg
+                        // no need to persist volume on all streams sharing the same alias
+                        streamState.adjustLastAudibleIndex(direction * step, device);
+                        sendMsg(mAudioHandler,
+                                MSG_PERSIST_VOLUME,
+                                SENDMSG_QUEUE,
+                                PERSIST_LAST_AUDIBLE,
+                                device,
+                                streamState,
+                                PERSIST_DELAY);
+                    }
+                    index = mStreamStates[streamType].getIndex(device, true  /* lastAudible */);
+                } else {
+                    if (adjustVolume && streamState.adjustIndex(direction * step, device)) {
+                        // Post message to set system volume (it in turn will post a message
+                        // to persist). Do not change volume if stream is muted.
+                        sendMsg(mAudioHandler,
+                                MSG_SET_DEVICE_VOLUME,
+                                SENDMSG_QUEUE,
+                                device,
+                                0,
+                                streamState,
+                                0);
+                    }
+                    index = mStreamStates[streamType].getIndex(device, false  /* lastAudible */);
+                }
             }
         }
         sendVolumeUpdate(streamType, oldIndex, index, flags);
@@ -2304,13 +2315,31 @@
                         com.android.internal.R.integer.config_safe_media_volume_index) * 10;
                 boolean safeMediaVolumeEnabled = mContext.getResources().getBoolean(
                         com.android.internal.R.bool.config_safe_media_volume_enabled);
+
+                // The persisted state is either "disabled" or "active": this is the state applied
+                // next time we boot and cannot be "inactive"
+                int persistedState;
                 if (safeMediaVolumeEnabled) {
-                    mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_ACTIVE;
-                    enforceSafeMediaVolume();
+                    persistedState = SAFE_MEDIA_VOLUME_ACTIVE;
+                    // The state can already be "inactive" here if the user has forced it before
+                    // the 30 seconds timeout for forced configuration. In this case we don't reset
+                    // it to "active".
+                    if (mSafeMediaVolumeState != SAFE_MEDIA_VOLUME_INACTIVE) {
+                        mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_ACTIVE;
+                        enforceSafeMediaVolume();
+                    }
                 } else {
+                    persistedState = SAFE_MEDIA_VOLUME_DISABLED;
                     mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_DISABLED;
                 }
                 mMcc = mcc;
+                sendMsg(mAudioHandler,
+                        MSG_PERSIST_SAFE_VOLUME_STATE,
+                        SENDMSG_QUEUE,
+                        persistedState,
+                        0,
+                        null,
+                        0);
             }
         }
     }
@@ -3222,6 +3251,12 @@
             AudioSystem.setForceUse(usage, config);
         }
 
+        private void onPersistSafeVolumeState(int state) {
+            Settings.Global.putInt(mContentResolver,
+                    Settings.Global.AUDIO_SAFE_VOLUME_STATE,
+                    state);
+        }
+
         @Override
         public void handleMessage(Message msg) {
 
@@ -3324,6 +3359,13 @@
                                 mBluetoothA2dpEnabled ?
                                         AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP);
                     }
+
+                    synchronized (mSettingsLock) {
+                        AudioSystem.setForceUse(AudioSystem.FOR_DOCK,
+                                mDockAudioMediaEnabled ?
+                                        AudioSystem.FORCE_ANALOG_DOCK : AudioSystem.FORCE_NONE);
+                    }
+
                     // indicate the end of reconfiguration phase to audio HAL
                     AudioSystem.setParameters("restarting=false");
                     break;
@@ -3424,6 +3466,9 @@
                 case MSG_CONFIGURE_SAFE_MEDIA_VOLUME:
                     onConfigureSafeVolume((msg.what == MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED));
                     break;
+                case MSG_PERSIST_SAFE_VOLUME_STATE:
+                    onPersistSafeVolumeState(msg.arg1);
+                    break;
             }
         }
     }
@@ -3751,13 +3796,7 @@
                         config = AudioSystem.FORCE_BT_CAR_DOCK;
                         break;
                     case Intent.EXTRA_DOCK_STATE_LE_DESK:
-                        synchronized (mSettingsLock) {
-                            if (mDockAudioMediaEnabled) {
-                                config = AudioSystem.FORCE_ANALOG_DOCK;
-                            } else {
-                                config = AudioSystem.FORCE_NONE;
-                            }
-                        }
+                        config = AudioSystem.FORCE_ANALOG_DOCK;
                         break;
                     case Intent.EXTRA_DOCK_STATE_HE_DESK:
                         config = AudioSystem.FORCE_DIGITAL_DOCK;
@@ -3766,8 +3805,14 @@
                     default:
                         config = AudioSystem.FORCE_NONE;
                 }
-
-                AudioSystem.setForceUse(AudioSystem.FOR_DOCK, config);
+                // Low end docks have a menu to enable or disable audio
+                // (see mDockAudioMediaEnabled)
+                if (!((dockState == Intent.EXTRA_DOCK_STATE_LE_DESK) ||
+                      ((dockState == Intent.EXTRA_DOCK_STATE_UNDOCKED) &&
+                       (mDockState == Intent.EXTRA_DOCK_STATE_LE_DESK)))) {
+                    AudioSystem.setForceUse(AudioSystem.FOR_DOCK, config);
+                }
+                mDockState = dockState;
             } else if (action.equals(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED)) {
                 state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE,
                                                BluetoothProfile.STATE_DISCONNECTED);
@@ -5079,18 +5124,23 @@
         // top of the stack for the media button event receivers : simply using the top of the
         // stack would make the entry disappear from the RemoteControlDisplay in conditions such as
         // notifications playing during music playback.
-        // crawl the AudioFocus stack until an entry is found with the following characteristics:
+        // Crawl the AudioFocus stack from the top until an entry is found with the following
+        // characteristics:
         // - focus gain on STREAM_MUSIC stream
         // - non-transient focus gain on a stream other than music
         FocusStackEntry af = null;
-        Iterator<FocusStackEntry> stackIterator = mFocusStack.iterator();
-        while(stackIterator.hasNext()) {
-            FocusStackEntry fse = (FocusStackEntry)stackIterator.next();
-            if ((fse.mStreamType == AudioManager.STREAM_MUSIC)
-                    || (fse.mFocusChangeType == AudioManager.AUDIOFOCUS_GAIN)) {
-                af = fse;
-                break;
+        try {
+            for (int index = mFocusStack.size()-1; index >= 0; index--) {
+                FocusStackEntry fse = mFocusStack.elementAt(index);
+                if ((fse.mStreamType == AudioManager.STREAM_MUSIC)
+                        || (fse.mFocusChangeType == AudioManager.AUDIOFOCUS_GAIN)) {
+                    af = fse;
+                    break;
+                }
             }
+        } catch (ArrayIndexOutOfBoundsException e) {
+            Log.e(TAG, "Wrong index accessing audio focus stack when updating RCD: " + e);
+            af = null;
         }
         if (af == null) {
             clearRemoteControlDisplay_syncAfRcs();
@@ -5111,6 +5161,7 @@
             clearRemoteControlDisplay_syncAfRcs();
             return;
         }
+
         // refresh conditions were verified: update the remote controls
         // ok to call: synchronized mAudioFocusLock then on mRCStack, mRCStack is not empty
         updateRemoteControlDisplay_syncAfRcs(infoChangedFlags);
diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java
index 4414191..a2eb8d9 100644
--- a/media/java/android/media/MediaFormat.java
+++ b/media/java/android/media/MediaFormat.java
@@ -26,7 +26,7 @@
  *
  * The format of the media data is specified as string/value pairs.
  *
- * Keys common to all formats:
+ * Keys common to all formats, <b>all keys not marked optional are mandatory</b>:
  *
  * <table>
  * <tr><th>Name</th><th>Value Type</th><th>Description</th></tr>
@@ -50,9 +50,9 @@
  * <tr><th>Name</th><th>Value Type</th><th>Description</th></tr>
  * <tr><td>{@link #KEY_CHANNEL_COUNT}</td><td>Integer</td><td></td></tr>
  * <tr><td>{@link #KEY_SAMPLE_RATE}</td><td>Integer</td><td></td></tr>
- * <tr><td>{@link #KEY_IS_ADTS}</td><td>Integer</td><td>optional, if content is AAC audio, setting this key to 1 indicates that each audio frame is prefixed by the ADTS header.</td></tr>
+ * <tr><td>{@link #KEY_IS_ADTS}</td><td>Integer</td><td>optional, if <em>decoding</em> AAC audio content, setting this key to 1 indicates that each audio frame is prefixed by the ADTS header.</td></tr>
  * <tr><td>{@link #KEY_AAC_PROFILE}</td><td>Integer</td><td><b>encoder-only</b>, optional, if content is AAC audio, specifies the desired profile.</td></tr>
- * <tr><td>{@link #KEY_CHANNEL_MASK}</td><td>Integer</td><td>A mask of audio channel assignments</td></tr>
+ * <tr><td>{@link #KEY_CHANNEL_MASK}</td><td>Integer</td><td>optional, a mask of audio channel assignments</td></tr>
  * <tr><td>{@link #KEY_FLAC_COMPRESSION_LEVEL}</td><td>Integer</td><td><b>encoder-only</b>, optional, if content is FLAC audio, specifies the desired compression level.</td></tr>
  * </table>
  *
@@ -140,6 +140,8 @@
      * A key mapping to a value of 1 if the content is AAC audio and
      * audio frames are prefixed with an ADTS header.
      * The associated value is an integer (0 or 1).
+     * This key is only supported when _decoding_ content, it cannot
+     * be used to configure an encoder to emit ADTS output.
      */
     public static final String KEY_IS_ADTS = "is-adts";
 
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index ef0da3a..7c547ec 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -328,8 +328,8 @@
  *         the state. Calling this method in an invalid state transfers the
  *         object to the <em>Error</em> state. </p></td></tr>
  * <tr><td>pause </p></td>
- *     <td>{Started, Paused}</p></td>
- *     <td>{Idle, Initialized, Prepared, Stopped, PlaybackCompleted, Error}</p></td>
+ *     <td>{Started, Paused, PlaybackCompleted}</p></td>
+ *     <td>{Idle, Initialized, Prepared, Stopped, Error}</p></td>
  *     <td>Successful invoke of this method in a valid state transfers the
  *         object to the <em>Paused</em> state. Calling this method in an
  *         invalid state transfers the object to the <em>Error</em> state.</p></td></tr>
diff --git a/media/java/android/media/MediaRouter.java b/media/java/android/media/MediaRouter.java
index 2a5a16e..8b489b1 100644
--- a/media/java/android/media/MediaRouter.java
+++ b/media/java/android/media/MediaRouter.java
@@ -313,13 +313,25 @@
     }
 
     /**
-     * Return the currently selected route for the given types
+     * Return the currently selected route for any of the given types
      *
      * @param type route types
      * @return the selected route
      */
     public RouteInfo getSelectedRoute(int type) {
-        return sStatic.mSelectedRoute;
+        if (sStatic.mSelectedRoute != null &&
+                (sStatic.mSelectedRoute.mSupportedTypes & type) != 0) {
+            // If the selected route supports any of the types supplied, it's still considered
+            // 'selected' for that type.
+            return sStatic.mSelectedRoute;
+        } else if (type == ROUTE_TYPE_USER) {
+            // The caller specifically asked for a user route and the currently selected route
+            // doesn't qualify.
+            return null;
+        }
+        // If the above didn't match and we're not specifically asking for a user route,
+        // consider the default selected.
+        return sStatic.mDefaultAudioVideo;
     }
 
     /**
@@ -862,7 +874,7 @@
     private static WifiDisplay findMatchingDisplay(WifiDisplay d, WifiDisplay[] displays) {
         for (int i = 0; i < displays.length; i++) {
             final WifiDisplay other = displays[i];
-            if (d.getDeviceAddress().equals(other.getDeviceAddress())) {
+            if (d.hasSameAddress(other)) {
                 return other;
             }
         }
diff --git a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
index cf56cba..731a09c 100644
--- a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
+++ b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
@@ -80,7 +80,7 @@
  */
 public class DefaultContainerService extends IntentService {
     private static final String TAG = "DefContainer";
-    private static final boolean localLOGV = true;
+    private static final boolean localLOGV = false;
 
     private static final String LIB_DIR_NAME = "lib";
 
diff --git a/packages/FusedLocation/src/com/android/location/fused/FusionEngine.java b/packages/FusedLocation/src/com/android/location/fused/FusionEngine.java
index f137373..f909158 100644
--- a/packages/FusedLocation/src/com/android/location/fused/FusionEngine.java
+++ b/packages/FusedLocation/src/com/android/location/fused/FusionEngine.java
@@ -249,7 +249,11 @@
             }
         }
 
-        mCallback.reportLocation(mFusedLocation);
+        if (mCallback != null) {
+          mCallback.reportLocation(mFusedLocation);
+        } else {
+          Log.w(TAG, "Location updates received while fusion engine not started");
+        }
     }
 
     /** Called on mLooper thread */
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index 94e2286..2b02049 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -75,6 +75,8 @@
     <integer name="def_lockscreen_sounds_enabled">1</integer>
     <string name="def_lock_sound" translatable="false">/system/media/audio/ui/Lock.ogg</string>
     <string name="def_unlock_sound" translatable="false">/system/media/audio/ui/Unlock.ogg</string>
+    <string name="def_wireless_charging_started_sound" translatable="false">/system/media/audio/ui/WirelessChargingStarted.ogg</string>
+
     <bool name="def_lockscreen_disabled">false</bool>
     <bool name="def_device_provisioned">false</bool>
 
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index b649b43..2454fb0 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -21,6 +21,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
+import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
 import android.content.res.XmlResourceParser;
 import android.database.Cursor;
@@ -31,6 +32,8 @@
 import android.media.AudioService;
 import android.net.ConnectivityManager;
 import android.os.Environment;
+import android.os.RemoteException;
+import android.os.ServiceManager;
 import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.provider.Settings;
@@ -68,7 +71,7 @@
     // database gets upgraded properly. At a minimum, please confirm that 'upgradeVersion'
     // is properly propagated through your change.  Not doing so will result in a loss of user
     // settings.
-    private static final int DATABASE_VERSION = 94;
+    private static final int DATABASE_VERSION = 95;
 
     private Context mContext;
     private int mUserHandle;
@@ -171,7 +174,15 @@
         db.execSQL("CREATE INDEX bookmarksIndex2 ON bookmarks (shortcut);");
 
         // Populate bookmarks table with initial bookmarks
-        loadBookmarks(db);
+        boolean onlyCore = false;
+        try {
+            onlyCore = IPackageManager.Stub.asInterface(ServiceManager.getService(
+                    "package")).isOnlyCoreApps();
+        } catch (RemoteException e) {
+        }
+        if (!onlyCore) {
+            loadBookmarks(db);
+        }
 
         // Load initial volume levels into DB
         loadVolumeLevels(db);
@@ -1494,6 +1505,25 @@
             upgradeVersion = 94;
         }
 
+        if (upgradeVersion == 94) {
+            // Add wireless charging started sound setting
+            if (mUserHandle == UserHandle.USER_OWNER) {
+                db.beginTransaction();
+                SQLiteStatement stmt = null;
+                try {
+                    stmt = db.compileStatement("INSERT OR REPLACE INTO global(name,value)"
+                            + " VALUES(?,?);");
+                    loadStringSetting(stmt, Settings.Global.WIRELESS_CHARGING_STARTED_SOUND,
+                            R.string.def_wireless_charging_started_sound);
+                    db.setTransactionSuccessful();
+                } finally {
+                    db.endTransaction();
+                    if (stmt != null) stmt.close();
+                }
+            }
+            upgradeVersion = 95;
+        }
+
         // *** Remember to update DATABASE_VERSION above!
 
         if (upgradeVersion != currentVersion) {
@@ -2180,6 +2210,8 @@
                     R.string.def_car_dock_sound);
             loadStringSetting(stmt, Settings.Global.CAR_UNDOCK_SOUND,
                     R.string.def_car_undock_sound);
+            loadStringSetting(stmt, Settings.Global.WIRELESS_CHARGING_STARTED_SOUND,
+                    R.string.def_wireless_charging_started_sound);
 
             loadSetting(stmt, Settings.Global.SET_INSTALL_LOCATION, 0);
             loadSetting(stmt, Settings.Global.DEFAULT_INSTALL_LOCATION,
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 8086bbc..f18338a 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -455,8 +455,8 @@
                     cache.setFullyMatchesDisk(false);
                     Log.d(TAG, "row count exceeds max cache entries for table " + table);
                 }
-                Log.d(TAG, "cache for settings table '" + table + "' rows=" + rows + "; fullycached=" +
-                      cache.fullyMatchesDisk());
+                if (LOCAL_LOGV) Log.d(TAG, "cache for settings table '" + table
+                        + "' rows=" + rows + "; fullycached=" + cache.fullyMatchesDisk());
             }
         } finally {
             c.close();
diff --git a/packages/SystemUI/res/layout-sw600dp/navigation_bar.xml b/packages/SystemUI/res/layout-sw600dp/navigation_bar.xml
index 2669c7e..b1104cc 100644
--- a/packages/SystemUI/res/layout-sw600dp/navigation_bar.xml
+++ b/packages/SystemUI/res/layout-sw600dp/navigation_bar.xml
@@ -141,7 +141,7 @@
                 />
         </LinearLayout>
 
-        <ImageView
+        <com.android.systemui.statusbar.policy.KeyButtonView
             android:layout_width="128dp"
             android:id="@+id/search_light"
             android:layout_height="match_parent"
@@ -282,7 +282,7 @@
                 />
         </LinearLayout>
 
-        <ImageView
+        <com.android.systemui.statusbar.policy.KeyButtonView
             android:layout_width="162dp"
             android:id="@+id/search_light"
             android:layout_height="match_parent"
diff --git a/packages/SystemUI/res/layout/navigation_bar.xml b/packages/SystemUI/res/layout/navigation_bar.xml
index 440a4e1..da52d89 100644
--- a/packages/SystemUI/res/layout/navigation_bar.xml
+++ b/packages/SystemUI/res/layout/navigation_bar.xml
@@ -145,7 +145,7 @@
                 />
         </LinearLayout>
 
-        <ImageView
+        <com.android.systemui.statusbar.policy.KeyButtonView
             android:layout_width="80dp"
             android:id="@+id/search_light"
             android:layout_height="match_parent"
@@ -289,7 +289,7 @@
                 />
         </LinearLayout>
 
-        <ImageView
+        <com.android.systemui.statusbar.policy.KeyButtonView
             android:id="@+id/search_light"
             android:layout_height="80dp"
             android:layout_width="match_parent"
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java b/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java
index 4338fa0..9281c75 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java
@@ -138,6 +138,10 @@
         return mLoadedTasks;
     }
 
+    public void remove(TaskDescription td) {
+        mLoadedTasks.remove(td);
+    }
+
     public boolean isFirstScreenful() {
         return mFirstScreenful;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java
index 6cb7dec..3330301 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java
@@ -336,19 +336,6 @@
         });
     }
 
-    @Override
-    protected void onVisibilityChanged(View changedView, int visibility) {
-        super.onVisibilityChanged(changedView, visibility);
-        // scroll to bottom after reloading
-        if (visibility == View.VISIBLE && changedView == this) {
-            post(new Runnable() {
-                public void run() {
-                    update();
-                }
-            });
-        }
-    }
-
     public void setAdapter(TaskDescriptionAdapter adapter) {
         mAdapter = adapter;
         mAdapter.registerDataSetObserver(new DataSetObserver() {
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
index cd3bc42..9a1e38d 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
@@ -77,9 +77,10 @@
 
     private boolean mShowing;
     private boolean mWaitingToShow;
-    private int mNumItemsWaitingForThumbnailsAndIcons;
     private ViewHolder mItemToAnimateInWhenWindowAnimationIsFinished;
+    private boolean mAnimateIconOfFirstTask;
     private boolean mWaitingForWindowAnimation;
+    private long mWindowAnimationStartTime;
 
     private RecentTasksLoader mRecentTasksLoader;
     private ArrayList<TaskDescription> mRecentTaskDescriptions;
@@ -174,10 +175,9 @@
             if (td.isLoaded()) {
                 updateThumbnail(holder, td.getThumbnail(), true, false);
                 updateIcon(holder, td.getIcon(), true, false);
-                mNumItemsWaitingForThumbnailsAndIcons--;
             }
             if (index == 0) {
-                if (mWaitingForWindowAnimation) {
+                if (mAnimateIconOfFirstTask) {
                     if (mItemToAnimateInWhenWindowAnimationIsFinished != null) {
                         holder.iconView.setAlpha(1f);
                         holder.iconView.setTranslationX(0f);
@@ -206,6 +206,9 @@
                         holder.iconView.setAlpha(0f);
                         holder.iconView.setTranslationY(translation);
                     }
+                    if (!mWaitingForWindowAnimation) {
+                        animateInIconOfFirstTask();
+                    }
                 }
             }
 
@@ -220,7 +223,9 @@
             updateThumbnail(holder, mRecentTasksLoader.getDefaultThumbnail(), false, false);
             holder.iconView.setImageBitmap(mRecentTasksLoader.getDefaultIcon());
             holder.iconView.setVisibility(INVISIBLE);
+            holder.iconView.animate().cancel();
             holder.labelView.setText(null);
+            holder.labelView.animate().cancel();
             holder.thumbnailView.setContentDescription(null);
             holder.thumbnailView.setTag(null);
             holder.thumbnailView.setOnLongClickListener(null);
@@ -235,6 +240,7 @@
                 holder.calloutLine.setAlpha(1f);
                 holder.calloutLine.setTranslationX(0f);
                 holder.calloutLine.setTranslationY(0f);
+                holder.calloutLine.animate().cancel();
             }
             holder.taskDescription = null;
             holder.loadedThumbnailAndIcon = false;
@@ -291,8 +297,9 @@
     }
 
     public void show(boolean show, ArrayList<TaskDescription> recentTaskDescriptions,
-            boolean firstScreenful, boolean waitingForWindowAnimation) {
-        mWaitingForWindowAnimation = waitingForWindowAnimation;
+            boolean firstScreenful, boolean animateIconOfFirstTask) {
+        mAnimateIconOfFirstTask = animateIconOfFirstTask;
+        mWaitingForWindowAnimation = animateIconOfFirstTask;
         if (show) {
             mWaitingToShow = true;
             refreshRecentTasksList(recentTaskDescriptions, firstScreenful);
@@ -527,7 +534,6 @@
                             updateIcon(h, td.getIcon(), true, animateShow);
                             updateThumbnail(h, td.getThumbnail(), true, animateShow);
                             h.loadedThumbnailAndIcon = true;
-                            mNumItemsWaitingForThumbnailsAndIcons--;
                         }
                     }
                 }
@@ -536,9 +542,14 @@
         showIfReady();
     }
 
-    public void onWindowAnimationStart() {
-        if (mItemToAnimateInWhenWindowAnimationIsFinished != null) {
-            final int startDelay = 150;
+    private void animateInIconOfFirstTask() {
+        if (mItemToAnimateInWhenWindowAnimationIsFinished != null &&
+                !mRecentTasksLoader.isFirstScreenful()) {
+            int timeSinceWindowAnimation =
+                    (int) (System.currentTimeMillis() - mWindowAnimationStartTime);
+            final int minStartDelay = 150;
+            final int startDelay = Math.max(0, Math.min(
+                    minStartDelay - timeSinceWindowAnimation, minStartDelay));
             final int duration = 250;
             final ViewHolder holder = mItemToAnimateInWhenWindowAnimationIsFinished;
             final TimeInterpolator cubic = new DecelerateInterpolator(1.5f);
@@ -550,10 +561,16 @@
                 }
             }
             mItemToAnimateInWhenWindowAnimationIsFinished = null;
-            mWaitingForWindowAnimation = false;
+            mAnimateIconOfFirstTask = false;
         }
     }
 
+    public void onWindowAnimationStart() {
+        mWaitingForWindowAnimation = false;
+        mWindowAnimationStartTime = System.currentTimeMillis();
+        animateInIconOfFirstTask();
+    }
+
     public void clearRecentTasksList() {
         // Clear memory used by screenshots
         if (mRecentTaskDescriptions != null) {
@@ -590,9 +607,6 @@
     }
 
     public void onTasksLoaded(ArrayList<TaskDescription> tasks, boolean firstScreenful) {
-        mNumItemsWaitingForThumbnailsAndIcons = firstScreenful
-                ? tasks.size() : mRecentTaskDescriptions == null
-                        ? 0 : mRecentTaskDescriptions.size();
         if (mRecentTaskDescriptions == null) {
             mRecentTaskDescriptions = new ArrayList<TaskDescription>(tasks);
         } else {
@@ -689,6 +703,7 @@
         }
         if (DEBUG) Log.v(TAG, "Jettison " + ad.getLabel());
         mRecentTaskDescriptions.remove(ad);
+        mRecentTasksLoader.remove(ad);
 
         // Handled by widget containers to enable LayoutTransitions properly
         // mListAdapter.notifyDataSetChanged();
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java
index 47b0113..b3adbaf 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java
@@ -345,19 +345,6 @@
         });
     }
 
-    @Override
-    protected void onVisibilityChanged(View changedView, int visibility) {
-        super.onVisibilityChanged(changedView, visibility);
-        // scroll to bottom after reloading
-        if (visibility == View.VISIBLE && changedView == this) {
-            post(new Runnable() {
-                public void run() {
-                    update();
-                }
-            });
-        }
-    }
-
     public void setAdapter(TaskDescriptionAdapter adapter) {
         mAdapter = adapter;
         mAdapter.registerDataSetObserver(new DataSetObserver() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 248a516..2bad353 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -31,7 +31,7 @@
 public class NotificationPanelView extends PanelView {
 
     Drawable mHandleBar;
-    float mHandleBarHeight;
+    int mHandleBarHeight;
     View mHandleView;
     int mFingers;
     PhoneStatusBar mStatusBar;
@@ -51,7 +51,7 @@
 
         Resources resources = getContext().getResources();
         mHandleBar = resources.getDrawable(R.drawable.status_bar_close);
-        mHandleBarHeight = resources.getDimension(R.dimen.close_handle_height);
+        mHandleBarHeight = resources.getDimensionPixelSize(R.dimen.close_handle_height);
         mHandleView = findViewById(R.id.handle);
 
         setContentDescription(resources.getString(R.string.accessibility_desc_notification_shade));
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index 7035006..5d9c7bc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -16,6 +16,10 @@
 
 package com.android.systemui.statusbar.phone;
 
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Iterator;
+
 import android.animation.ObjectAnimator;
 import android.animation.TimeAnimator;
 import android.animation.TimeAnimator.TimeListener;
@@ -73,7 +77,93 @@
 
     private TimeAnimator mTimeAnimator;
     private ObjectAnimator mPeekAnimator;
-    private VelocityTracker mVelocityTracker;
+    private FlingTracker mVelocityTracker;
+
+    /**
+     * A very simple low-pass velocity filter for motion events; not nearly as sophisticated as
+     * VelocityTracker but optimized for the kinds of gestures we expect to see in status bar
+     * panels.
+     */
+    private static class FlingTracker {
+        static final boolean DEBUG = false;
+        final int MAX_EVENTS = 8;
+        final float DECAY = 0.75f;
+        ArrayDeque<MotionEventCopy> mEventBuf = new ArrayDeque<MotionEventCopy>(MAX_EVENTS);
+        float mVX, mVY = 0;
+        private static class MotionEventCopy {
+            public MotionEventCopy(float x2, float y2, long eventTime) {
+                this.x = x2;
+                this.y = y2;
+                this.t = eventTime;
+            }
+            public float x, y;
+            public long t;
+        }
+        public FlingTracker() {
+        }
+        public void addMovement(MotionEvent event) {
+            if (mEventBuf.size() == MAX_EVENTS) {
+                mEventBuf.remove();
+            }
+            mEventBuf.add(new MotionEventCopy(event.getX(), event.getY(), event.getEventTime()));
+        }
+        public void computeCurrentVelocity(long timebase) {
+            if (FlingTracker.DEBUG) {
+                Slog.v("FlingTracker", "computing velocities for " + mEventBuf.size() + " events");
+            }
+            mVX = mVY = 0;
+            MotionEventCopy last = null;
+            int i = 0;
+            float totalweight = 0f;
+            float weight = 10f;
+            for (final Iterator<MotionEventCopy> iter = mEventBuf.descendingIterator();
+                    iter.hasNext();) {
+                final MotionEventCopy event = iter.next();
+                if (last != null) {
+                    final float dt = (float) (event.t - last.t) / timebase;
+                    final float dx = (event.x - last.x);
+                    final float dy = (event.y - last.y);
+                    if (FlingTracker.DEBUG) {
+                        Slog.v("FlingTracker", String.format("   [%d] dx=%.1f dy=%.1f dt=%.0f vx=%.1f vy=%.1f",
+                                i,
+                                dx, dy, dt,
+                                (dx/dt),
+                                (dy/dt)
+                                ));
+                    }
+                    mVX += weight * dx / dt;
+                    mVY += weight * dy / dt;
+                    totalweight += weight;
+                    weight *= DECAY;
+                }
+                last = event;
+                i++;
+            }
+            mVX /= totalweight;
+            mVY /= totalweight;
+
+            if (FlingTracker.DEBUG) {
+                Slog.v("FlingTracker", "computed: vx=" + mVX + " vy=" + mVY);
+            }
+        }
+        public float getXVelocity() {
+            return mVX;
+        }
+        public float getYVelocity() {
+            return mVY;
+        }
+        public void recycle() {
+            mEventBuf.clear();
+        }
+
+        static FlingTracker sTracker;
+        static FlingTracker obtain() {
+            if (sTracker == null) {
+                sTracker = new FlingTracker();
+            }
+            return sTracker;
+        }
+    }
 
     private int[] mAbsPos = new int[2];
     PanelBar mBar;
@@ -268,7 +358,7 @@
                             mHandleView.setPressed(true);
                             postInvalidate(); // catch the press state change
                             mInitialTouchY = y;
-                            mVelocityTracker = VelocityTracker.obtain();
+                            mVelocityTracker = FlingTracker.obtain();
                             trackMovement(event);
                             mTimeAnimator.cancel(); // end any outstanding animations
                             mBar.onTrackingStarted(PanelView.this);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 7371ce2..30af333 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -298,7 +298,7 @@
             if (MULTIUSER_DEBUG) Slog.d(TAG, String.format("User setup changed: " +
                     "selfChange=%s userSetup=%s mUserSetup=%s",
                     selfChange, userSetup, mUserSetup));
-            if (mSettingsButton != null && !mHasSettingsPanel) {
+            if (mSettingsButton != null && mHasFlipSettings) {
                 mSettingsButton.setVisibility(userSetup ? View.VISIBLE : View.INVISIBLE);
             }
             if (mSettingsPanel != null) {
@@ -1488,6 +1488,9 @@
             return;
         }
 
+        // Settings are not available in setup
+        if (!mUserSetup) return;
+
         if (mHasFlipSettings) {
             mNotificationPanel.expand();
             if (mFlipSettingsView.getVisibility() != View.VISIBLE) {
@@ -1501,6 +1504,9 @@
     }
 
     public void switchToSettings() {
+        // Settings are not available in setup
+        if (!mUserSetup) return;
+
         mFlipSettingsView.setScaleX(1f);
         mFlipSettingsView.setVisibility(View.VISIBLE);
         mSettingsButton.setVisibility(View.GONE);
@@ -1512,6 +1518,9 @@
     }
 
     public void flipToSettings() {
+        // Settings are not available in setup
+        if (!mUserSetup) return;
+
         if (mFlipSettingsViewAnim != null) mFlipSettingsViewAnim.cancel();
         if (mScrollViewAnim != null) mScrollViewAnim.cancel();
         if (mSettingsButtonAnim != null) mSettingsButtonAnim.cancel();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
index cc9c601..9b0a320 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
@@ -55,6 +55,7 @@
 import android.graphics.drawable.LevelListDrawable;
 import android.hardware.display.DisplayManager;
 import android.hardware.display.WifiDisplayStatus;
+import android.net.wifi.WifiManager;
 import android.os.AsyncTask;
 import android.os.Handler;
 import android.os.RemoteException;
@@ -85,6 +86,8 @@
     private static final String TAG = "QuickSettings";
     public static final boolean SHOW_IME_TILE = false;
 
+    public static final boolean LONG_PRESS_TOGGLES = true;
+
     private Context mContext;
     private PanelBar mBar;
     private QuickSettingsModel mModel;
@@ -94,6 +97,8 @@
     private WifiDisplayStatus mWifiDisplayStatus;
     private PhoneStatusBar mStatusBarService;
     private BluetoothState mBluetoothState;
+    private BluetoothAdapter mBluetoothAdapter;
+    private WifiManager mWifiManager;
 
     private BrightnessController mBrightnessController;
     private BluetoothController mBluetoothController;
@@ -131,6 +136,9 @@
         mModel = new QuickSettingsModel(context);
         mWifiDisplayStatus = new WifiDisplayStatus();
         mBluetoothState = new QuickSettingsModel.BluetoothState();
+        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
+        mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
+
         mHandler = new Handler();
 
         Resources r = mContext.getResources();
@@ -297,8 +305,7 @@
                         (UserManager) mContext.getSystemService(Context.USER_SERVICE);
                 if (um.getUsers(true).size() > 1) {
                     try {
-                        WindowManagerGlobal.getWindowManagerService().lockNow(
-                                LockPatternUtils.USER_SWITCH_LOCK_OPTIONS);
+                        WindowManagerGlobal.getWindowManagerService().lockNow(null);
                     } catch (RemoteException e) {
                         Log.e(TAG, "Couldn't show user switcher", e);
                     }
@@ -391,7 +398,7 @@
 
     private void addSystemTiles(ViewGroup parent, LayoutInflater inflater) {
         // Wi-fi
-        QuickSettingsTileView wifiTile = (QuickSettingsTileView)
+        final QuickSettingsTileView wifiTile = (QuickSettingsTileView)
                 inflater.inflate(R.layout.quick_settings_tile, parent, false);
         wifiTile.setContent(R.layout.quick_settings_tile_wifi, inflater);
         wifiTile.setOnClickListener(new View.OnClickListener() {
@@ -400,6 +407,30 @@
                 startSettingsActivity(android.provider.Settings.ACTION_WIFI_SETTINGS);
             }
         });
+        if (LONG_PRESS_TOGGLES) {
+            wifiTile.setOnLongClickListener(new View.OnLongClickListener() {
+                @Override
+                public boolean onLongClick(View v) {
+                    final boolean enable =
+                            (mWifiManager.getWifiState() != WifiManager.WIFI_STATE_ENABLED);
+                    new AsyncTask<Void, Void, Void>() {
+                        @Override
+                        protected Void doInBackground(Void... args) {
+                            // Disable tethering if enabling Wifi
+                            final int wifiApState = mWifiManager.getWifiApState();
+                            if (enable && ((wifiApState == WifiManager.WIFI_AP_STATE_ENABLING) ||
+                                           (wifiApState == WifiManager.WIFI_AP_STATE_ENABLED))) {
+                                mWifiManager.setWifiApEnabled(null, false);
+                            }
+
+                            mWifiManager.setWifiEnabled(enable);
+                            return null;
+                        }
+                    }.execute();
+                    wifiTile.setPressed(false);
+                    return true;
+                }} );
+        }
         mModel.addWifiTile(wifiTile, new QuickSettingsModel.RefreshCallback() {
             @Override
             public void refreshView(QuickSettingsTileView view, State state) {
@@ -415,7 +446,7 @@
         });
         parent.addView(wifiTile);
 
-        if (mModel.deviceSupportsTelephony()) {
+        if (mModel.deviceHasMobileData()) {
             // RSSI
             QuickSettingsTileView rssiTile = (QuickSettingsTileView)
                     inflater.inflate(R.layout.quick_settings_tile, parent, false);
@@ -538,7 +569,7 @@
 
         // Bluetooth
         if (mModel.deviceSupportsBluetooth()) {
-            QuickSettingsTileView bluetoothTile = (QuickSettingsTileView)
+            final QuickSettingsTileView bluetoothTile = (QuickSettingsTileView)
                     inflater.inflate(R.layout.quick_settings_tile, parent, false);
             bluetoothTile.setContent(R.layout.quick_settings_tile_bluetooth, inflater);
             bluetoothTile.setOnClickListener(new View.OnClickListener() {
@@ -547,6 +578,19 @@
                     startSettingsActivity(android.provider.Settings.ACTION_BLUETOOTH_SETTINGS);
                 }
             });
+            if (LONG_PRESS_TOGGLES) {
+                bluetoothTile.setOnLongClickListener(new View.OnLongClickListener() {
+                    @Override
+                    public boolean onLongClick(View v) {
+                        if (mBluetoothAdapter.isEnabled()) {
+                            mBluetoothAdapter.disable();
+                        } else {
+                            mBluetoothAdapter.enable();
+                        }
+                        bluetoothTile.setPressed(false);
+                        return true;
+                    }});
+            }
             mModel.addBluetoothTile(bluetoothTile, new QuickSettingsModel.RefreshCallback() {
                 @Override
                 public void refreshView(QuickSettingsTileView view, State state) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java
index 4513dcb..00991c1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java
@@ -29,6 +29,7 @@
 import android.database.ContentObserver;
 import android.graphics.drawable.Drawable;
 import android.hardware.display.WifiDisplayStatus;
+import android.net.ConnectivityManager;
 import android.os.Handler;
 import android.os.UserHandle;
 import android.provider.Settings;
@@ -120,7 +121,8 @@
         public void startObserving() {
             final ContentResolver cr = mContext.getContentResolver();
             cr.registerContentObserver(
-                    Settings.System.getUriFor(Settings.System.NEXT_ALARM_FORMATTED), false, this);
+                    Settings.System.getUriFor(Settings.System.NEXT_ALARM_FORMATTED), false, this,
+                    UserHandle.USER_ALL);
         }
     }
 
@@ -171,6 +173,8 @@
     private final BugreportObserver mBugreportObserver;
     private final BrightnessObserver mBrightnessObserver;
 
+    private final boolean mHasMobileData;
+
     private QuickSettingsTileView mUserTile;
     private RefreshCallback mUserCallback;
     private UserState mUserState = new UserState();
@@ -249,6 +253,10 @@
         mBrightnessObserver = new BrightnessObserver(mHandler);
         mBrightnessObserver.startObserving();
 
+        ConnectivityManager cm = (ConnectivityManager)
+                context.getSystemService(Context.CONNECTIVITY_SERVICE);
+        mHasMobileData = cm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE);
+
         IntentFilter alarmIntentFilter = new IntentFilter();
         alarmIntentFilter.addAction(Intent.ACTION_ALARM_CHANGED);
         context.registerReceiver(mAlarmIntentReceiver, alarmIntentFilter);
@@ -304,8 +312,15 @@
         mAlarmCallback.refreshView(mAlarmTile, mAlarmState);
     }
     void onNextAlarmChanged() {
-        mAlarmState.label = Settings.System.getString(mContext.getContentResolver(),
-                Settings.System.NEXT_ALARM_FORMATTED);
+        final String alarmText = Settings.System.getStringForUser(mContext.getContentResolver(),
+                Settings.System.NEXT_ALARM_FORMATTED,
+                UserHandle.USER_CURRENT);
+        mAlarmState.label = alarmText;
+
+        // When switching users, this is the only clue we're going to get about whether the
+        // alarm is actually set, since we won't get the ACTION_ALARM_CHANGED broadcast
+        mAlarmState.enabled = ! TextUtils.isEmpty(alarmText);
+
         mAlarmCallback.refreshView(mAlarmTile, mAlarmState);
     }
 
@@ -403,22 +418,22 @@
         mWifiCallback.refreshView(mWifiTile, mWifiState);
     }
 
+    boolean deviceHasMobileData() {
+        return mHasMobileData;
+    }
+
     // RSSI
     void addRSSITile(QuickSettingsTileView view, RefreshCallback cb) {
         mRSSITile = view;
         mRSSICallback = cb;
         mRSSICallback.refreshView(mRSSITile, mRSSIState);
     }
-    boolean deviceSupportsTelephony() {
-        PackageManager pm = mContext.getPackageManager();
-        return pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY);
-    }
     // NetworkSignalChanged callback
     @Override
     public void onMobileDataSignalChanged(
             boolean enabled, int mobileSignalIconId, String signalContentDescription,
             int dataTypeIconId, String dataContentDescription, String enabledDesc) {
-        if (deviceSupportsTelephony()) {
+        if (deviceHasMobileData()) {
             // TODO: If view is in awaiting state, disable
             Resources r = mContext.getResources();
             mRSSIState.signalIconId = enabled && (mobileSignalIconId > 0)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsPanelView.java
index a58eb22..bbb8455 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsPanelView.java
@@ -41,7 +41,7 @@
     private QuickSettingsContainerView mQSContainer;
 
     Drawable mHandleBar;
-    float mHandleBarHeight;
+    int mHandleBarHeight;
     View mHandleView;
 
     public SettingsPanelView(Context context, AttributeSet attrs) {
@@ -56,7 +56,7 @@
 
         Resources resources = getContext().getResources();
         mHandleBar = resources.getDrawable(R.drawable.status_bar_close);
-        mHandleBarHeight = resources.getDimension(R.dimen.close_handle_height);
+        mHandleBarHeight = resources.getDimensionPixelSize(R.dimen.close_handle_height);
         mHandleView = findViewById(R.id.handle);
 
         setContentDescription(resources.getString(R.string.accessibility_desc_quick_settings));
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
index 7f9bcac..716341f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
@@ -68,9 +68,20 @@
         final String action = intent.getAction();
         if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
             final int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);
-            final boolean plugged = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) != 0;
-            final int icon = plugged ? R.drawable.stat_sys_battery_charge 
+            final int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS,
+                    BatteryManager.BATTERY_STATUS_UNKNOWN);
+
+            boolean plugged = false;
+            switch (status) {
+                case BatteryManager.BATTERY_STATUS_CHARGING: 
+                case BatteryManager.BATTERY_STATUS_FULL:
+                    plugged = true;
+                    break;
+            }
+
+            final int icon = plugged ? R.drawable.stat_sys_battery_charge
                                      : R.drawable.stat_sys_battery;
+
             int N = mIconViews.size();
             for (int i=0; i<N; i++) {
                 ImageView v = mIconViews.get(i);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
index ffc18c7..e41de47 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
@@ -40,19 +40,20 @@
 
 import java.text.SimpleDateFormat;
 import java.util.Calendar;
+import java.util.Locale;
 import java.util.TimeZone;
 
 import com.android.internal.R;
 
 /**
- * This widget display an analogic clock with two hands for hours and
- * minutes.
+ * Digital clock for the status bar.
  */
 public class Clock extends TextView {
     private boolean mAttached;
     private Calendar mCalendar;
     private String mClockFormatString;
     private SimpleDateFormat mClockFormat;
+    private Locale mLocale;
 
     private static final int AM_PM_STYLE_NORMAL  = 0;
     private static final int AM_PM_STYLE_SMALL   = 1;
@@ -84,6 +85,7 @@
             filter.addAction(Intent.ACTION_TIME_CHANGED);
             filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
             filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
+            filter.addAction(Intent.ACTION_USER_SWITCHED);
 
             getContext().registerReceiver(mIntentReceiver, filter, null, getHandler());
         }
@@ -117,6 +119,12 @@
                 if (mClockFormat != null) {
                     mClockFormat.setTimeZone(mCalendar.getTimeZone());
                 }
+            } else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) {
+                final Locale newLocale = getResources().getConfiguration().locale;
+                if (! newLocale.equals(mLocale)) {
+                    mLocale = newLocale;
+                    mClockFormatString = ""; // force refresh
+                }
             }
             updateClock();
         }
diff --git a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
index 91fc67a..06696fe 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
@@ -33,6 +33,7 @@
 
 public class StorageNotification extends StorageEventListener {
     private static final String TAG = "StorageNotification";
+    private static final boolean DEBUG = false;
 
     private static final boolean POP_UMS_ACTIVITY_ON_CONNECT = true;
 
@@ -70,8 +71,8 @@
 
         mStorageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
         final boolean connected = mStorageManager.isUsbMassStorageConnected();
-        Slog.d(TAG, String.format( "Startup with UMS connection %s (media state %s)", mUmsAvailable,
-                Environment.getExternalStorageState()));
+        if (DEBUG) Slog.d(TAG, String.format( "Startup with UMS connection %s (media state %s)",
+                mUmsAvailable, Environment.getExternalStorageState()));
         
         HandlerThread thr = new HandlerThread("SystemUI StorageNotification");
         thr.start();
@@ -101,7 +102,8 @@
          */
         String st = Environment.getExternalStorageState();
 
-        Slog.i(TAG, String.format("UMS connection changed to %s (media state %s)", connected, st));
+        if (DEBUG) Slog.i(TAG, String.format("UMS connection changed to %s (media state %s)",
+                connected, st));
 
         if (connected && (st.equals(
                 Environment.MEDIA_REMOVED) || st.equals(Environment.MEDIA_CHECKING))) {
@@ -127,7 +129,7 @@
     }
 
     private void onStorageStateChangedAsync(String path, String oldState, String newState) {
-        Slog.i(TAG, String.format(
+        if (DEBUG) Slog.i(TAG, String.format(
                 "Media {%s} state changed from {%s} -> {%s}", path, oldState, newState));
         if (newState.equals(Environment.MEDIA_SHARED)) {
             /*
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index d9c07f8..fb515ac 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -412,6 +412,8 @@
     boolean mForceStatusBar;
     boolean mForceStatusBarFromKeyguard;
     boolean mHideLockScreen;
+    boolean mForcingShowNavBar;
+    int mForcingShowNavBarLayer;
 
     // States of keyguard dismiss.
     private static final int DISMISS_KEYGUARD_NONE = 0; // Keyguard not being dismissed.
@@ -2936,6 +2938,8 @@
         mTopFullscreenOpaqueWindowState = null;
         mForceStatusBar = false;
         mForceStatusBarFromKeyguard = false;
+        mForcingShowNavBar = false;
+        mForcingShowNavBarLayer = -1;
         
         mHideLockScreen = false;
         mAllowLockscreenWhenOn = false;
@@ -2950,6 +2954,13 @@
                                 WindowManager.LayoutParams attrs) {
         if (DEBUG_LAYOUT) Slog.i(TAG, "Win " + win + ": isVisibleOrBehindKeyguardLw="
                 + win.isVisibleOrBehindKeyguardLw());
+        if (mTopFullscreenOpaqueWindowState == null && (win.getAttrs().privateFlags
+                &WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_SHOW_NAV_BAR) != 0) {
+            if (mForcingShowNavBarLayer < 0) {
+                mForcingShowNavBar = true;
+                mForcingShowNavBarLayer = win.getSurfaceLayer();
+            }
+        }
         if (mTopFullscreenOpaqueWindowState == null &&
                 win.isVisibleOrBehindKeyguardLw() && !win.isGoneForLayoutLw()) {
             if ((attrs.flags & FLAG_FORCE_NOT_FULLSCREEN) != 0) {
@@ -3756,6 +3767,14 @@
                 // and then updates our own bookkeeping based on the now-
                 // current user.
                 mSettingsObserver.onChange(false);
+
+                // force a re-application of focused window sysui visibility.
+                // the window may never have been shown for this user
+                // e.g. the keyguard when going through the new-user setup flow
+                synchronized(mLock) {
+                    mLastSystemUiFlags = 0;
+                    updateSystemUiVisibilityLw();
+                }
             }
         }
     };
@@ -4470,9 +4489,13 @@
             // will quickly lose focus once it correctly gets hidden.
             return 0;
         }
-        final int visibility = mFocusedWindow.getSystemUiVisibility()
+        int tmpVisibility = mFocusedWindow.getSystemUiVisibility()
                 & ~mResettingSystemUiFlags
                 & ~mForceClearedSystemUiFlags;
+        if (mForcingShowNavBar && mFocusedWindow.getSurfaceLayer() < mForcingShowNavBarLayer) {
+            tmpVisibility &= ~View.SYSTEM_UI_CLEARABLE_FLAGS;
+        }
+        final int visibility = tmpVisibility;
         int diff = visibility ^ mLastSystemUiFlags;
         final boolean needsMenu = mFocusedWindow.getNeedsMenuLw(mTopFullscreenOpaqueWindowState);
         if (diff == 0 && mLastFocusNeedsMenu == needsMenu
@@ -4659,6 +4682,11 @@
             pw.print(prefix); pw.print("mTopFullscreenOpaqueWindowState=");
                     pw.println(mTopFullscreenOpaqueWindowState);
         }
+        if (mForcingShowNavBar) {
+            pw.print(prefix); pw.print("mForcingShowNavBar=");
+                    pw.println(mForcingShowNavBar); pw.print( "mForcingShowNavBarLayer=");
+                    pw.println(mForcingShowNavBarLayer);
+        }
         pw.print(prefix); pw.print("mTopIsFullscreen="); pw.print(mTopIsFullscreen);
                 pw.print(" mHideLockScreen="); pw.println(mHideLockScreen);
         pw.print(prefix); pw.print("mForceStatusBar="); pw.print(mForceStatusBar);
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/CameraWidgetFrame.java b/policy/src/com/android/internal/policy/impl/keyguard/CameraWidgetFrame.java
index dbd9999..762711d 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/CameraWidgetFrame.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/CameraWidgetFrame.java
@@ -18,10 +18,9 @@
 
 import android.content.Context;
 import android.content.pm.PackageManager.NameNotFoundException;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.Point;
+import android.graphics.Rect;
 import android.os.Handler;
 import android.os.SystemClock;
 import android.util.Log;
@@ -53,17 +52,20 @@
     private final Handler mHandler = new Handler();
     private final KeyguardActivityLauncher mActivityLauncher;
     private final Callbacks mCallbacks;
+    private final CameraWidgetInfo mWidgetInfo;
     private final WindowManager mWindowManager;
     private final Point mRenderedSize = new Point();
-    private final int[] mScreenLocation = new int[2];
+    private final int[] mTmpLoc = new int[2];
+    private final Rect mTmpRect = new Rect();
 
-    private View mWidgetView;
     private long mLaunchCameraStart;
     private boolean mActive;
     private boolean mTransitioning;
-    private boolean mRecovering;
     private boolean mDown;
 
+    private FixedSizeFrameLayout mPreview;
+    private View mFullscreenPreview;
+
     private final Runnable mTransitionToCameraRunnable = new Runnable() {
         @Override
         public void run() {
@@ -81,21 +83,18 @@
             mActivityLauncher.launchCamera(worker, mSecureCameraActivityStartedRunnable);
         }};
 
+    private final Runnable mPostTransitionToCameraEndAction = new Runnable() {
+        @Override
+        public void run() {
+            mHandler.post(mTransitionToCameraEndAction);
+        }};
+
     private final Runnable mRecoverRunnable = new Runnable() {
         @Override
         public void run() {
             recover();
         }};
 
-    private final Runnable mRecoverEndAction = new Runnable() {
-        @Override
-        public void run() {
-            if (!mRecovering)
-                return;
-            mCallbacks.onCameraLaunchedUnsuccessfully();
-            reset();
-        }};
-
     private final Runnable mRenderRunnable = new Runnable() {
         @Override
         public void run() {
@@ -119,13 +118,43 @@
         };
     };
 
+    private static final class FixedSizeFrameLayout extends FrameLayout {
+        int width;
+        int height;
+
+        FixedSizeFrameLayout(Context context) {
+            super(context);
+        }
+
+        @Override
+        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+            measureChildren(
+                    MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
+                    MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
+            setMeasuredDimension(width, height);
+        }
+    }
+
     private CameraWidgetFrame(Context context, Callbacks callbacks,
-            KeyguardActivityLauncher activityLauncher) {
+            KeyguardActivityLauncher activityLauncher,
+            CameraWidgetInfo widgetInfo, View previewWidget) {
         super(context);
         mCallbacks = callbacks;
         mActivityLauncher = activityLauncher;
+        mWidgetInfo = widgetInfo;
         mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
         KeyguardUpdateMonitor.getInstance(context).registerCallback(mCallback);
+
+        mPreview = new FixedSizeFrameLayout(context);
+        mPreview.addView(previewWidget);
+        addView(mPreview);
+
+        View clickBlocker = new View(context);
+        clickBlocker.setBackgroundColor(Color.TRANSPARENT);
+        clickBlocker.setOnClickListener(this);
+        addView(clickBlocker);
+
+        setContentDescription(context.getString(R.string.keyguard_accessibility_camera));
         if (DEBUG) Log.d(TAG, "new CameraWidgetFrame instance " + instanceId());
     }
 
@@ -137,24 +166,17 @@
         CameraWidgetInfo widgetInfo = launcher.getCameraWidgetInfo();
         if (widgetInfo == null)
             return null;
-        View widgetView = widgetInfo.layoutId > 0 ?
-                inflateWidgetView(context, widgetInfo) :
-                inflateGenericWidgetView(context);
-        if (widgetView == null)
+        View previewWidget = getPreviewWidget(context, widgetInfo);
+        if (previewWidget == null)
             return null;
 
-        ImageView preview = new ImageView(context);
-        preview.setLayoutParams(new FrameLayout.LayoutParams(
-                FrameLayout.LayoutParams.MATCH_PARENT,
-                FrameLayout.LayoutParams.MATCH_PARENT));
-        preview.setScaleType(ScaleType.FIT_CENTER);
-        preview.setContentDescription(preview.getContext().getString(
-                R.string.keyguard_accessibility_camera));
-        CameraWidgetFrame cameraWidgetFrame = new CameraWidgetFrame(context, callbacks, launcher);
-        cameraWidgetFrame.addView(preview);
-        cameraWidgetFrame.mWidgetView = widgetView;
-        preview.setOnClickListener(cameraWidgetFrame);
-        return cameraWidgetFrame;
+        return new CameraWidgetFrame(context, callbacks, launcher, widgetInfo, previewWidget);
+    }
+
+    private static View getPreviewWidget(Context context, CameraWidgetInfo widgetInfo) {
+        return widgetInfo.layoutId > 0 ?
+                inflateWidgetView(context, widgetInfo) :
+                inflateGenericWidgetView(context);
     }
 
     private static View inflateWidgetView(Context context, CameraWidgetInfo widgetInfo) {
@@ -188,63 +210,45 @@
         return iv;
     }
 
-    public void render() {
-        final Throwable[] thrown = new Throwable[1];
-        final Bitmap[] offscreen = new Bitmap[1];
-        try {
-            final int width = getRootView().getWidth();
-            final int height = getRootView().getHeight();
-            if (mRenderedSize.x == width && mRenderedSize.y == height) {
-                if (DEBUG) Log.d(TAG, String.format("Already rendered at size=%sx%s",
-                        width, height));
-                return;
-            }
-            if (width == 0 || height == 0) {
-                return;
-            }
-            final long start = SystemClock.uptimeMillis();
-            offscreen[0] = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
-            final Canvas c = new Canvas(offscreen[0]);
-            mWidgetView.measure(
-                    MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
-                    MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
-            mWidgetView.layout(0, 0, width, height);
-            mWidgetView.draw(c);
-
-            final long end = SystemClock.uptimeMillis();
-            if (DEBUG) Log.d(TAG, String.format(
-                    "Rendered camera widget in %sms size=%sx%s instance=%s at %s",
-                    end - start,
-                    width, height,
-                    instanceId(),
-                    end));
-            mRenderedSize.set(width, height);
-        } catch (Throwable t) {
-            thrown[0] = t;
+    private void render() {
+        final View root = getRootView();
+        final int width = root.getWidth();
+        final int height = root.getHeight();
+        if (mRenderedSize.x == width && mRenderedSize.y == height) {
+            if (DEBUG) Log.d(TAG, String.format("Already rendered at size=%sx%s", width, height));
+            return;
+        }
+        if (width == 0 || height == 0) {
+            return;
         }
 
-        mHandler.post(new Runnable() {
-            @Override
-            public void run() {
-                if (thrown[0] == null) {
-                    try {
-                        ((ImageView) getChildAt(0)).setImageBitmap(offscreen[0]);
-                    } catch (Throwable t) {
-                        thrown[0] = t;
-                    }
-                }
-                if (thrown[0] == null)
-                    return;
+        mPreview.width = width;
+        mPreview.height = height;
+        mPreview.requestLayout();
 
-                Log.w(TAG, "Error rendering camera widget", thrown[0]);
-                try {
-                    removeAllViews();
-                    final View genericView = inflateGenericWidgetView(mContext);
-                    addView(genericView);
-                } catch (Throwable t) {
-                    Log.w(TAG, "Error inflating generic camera widget", t);
-                }
-            }});
+        final int thisWidth = getWidth() - getPaddingLeft() - getPaddingRight();
+        final int thisHeight = getHeight() - getPaddingTop() - getPaddingBottom();
+
+        final float pvScaleX = (float) thisWidth / width;
+        final float pvScaleY = (float) thisHeight / height;
+        final float pvScale = Math.min(pvScaleX, pvScaleY);
+
+        final int pvWidth = (int) (pvScale * width);
+        final int pvHeight = (int) (pvScale * height);
+
+        final float pvTransX = pvWidth < thisWidth ? (thisWidth - pvWidth) / 2 : 0;
+        final float pvTransY = pvHeight < thisHeight ? (thisHeight - pvHeight) / 2 : 0;
+
+        mPreview.setPivotX(0);
+        mPreview.setPivotY(0);
+        mPreview.setScaleX(pvScale);
+        mPreview.setScaleY(pvScale);
+        mPreview.setTranslationX(pvTransX);
+        mPreview.setTranslationY(pvTransY);
+
+        mRenderedSize.set(width, height);
+        if (DEBUG) Log.d(TAG, String.format("Rendered camera widget size=%sx%s instance=%s",
+                width, height, instanceId()));
     }
 
     private void transitionToCamera() {
@@ -252,55 +256,53 @@
 
         mTransitioning = true;
 
-        final View child = getChildAt(0);
-        final View root = getRootView();
-
-        final int startWidth = child.getWidth();
-        final int startHeight = child.getHeight();
-
-        final int finishWidth = root.getWidth();
-        final int finishHeight = root.getHeight();
-
-        final float scaleX = (float) finishWidth / startWidth;
-        final float scaleY = (float) finishHeight / startHeight;
-        final float scale = Math.round( Math.max(scaleX, scaleY) * 100) / 100f;
-
-        final int[] loc = new int[2];
-        root.getLocationInWindow(loc);
-        final int finishCenter = loc[1] + finishHeight / 2;
-
-        child.getLocationInWindow(loc);
-        final int startCenter = loc[1] + startHeight / 2;
-
-        if (DEBUG) Log.d(TAG, String.format("Transitioning to camera. " +
-                "(start=%sx%s, finish=%sx%s, scale=%s,%s, startCenter=%s, finishCenter=%s)",
-                startWidth, startHeight,
-                finishWidth, finishHeight,
-                scaleX, scaleY,
-                startCenter, finishCenter));
-
         enableWindowExitAnimation(false);
-        animate()
-            .scaleX(scale)
-            .scaleY(scale)
-            .translationY(finishCenter - startCenter)
-            .setDuration(WIDGET_ANIMATION_DURATION)
-            .withEndAction(mTransitionToCameraEndAction)
-            .start();
 
+        mPreview.getLocationInWindow(mTmpLoc);
+        final float pvHeight = mPreview.getHeight() * mPreview.getScaleY();
+        final float pvCenter = mTmpLoc[1] + pvHeight / 2f;
+
+        final ViewGroup root = (ViewGroup) getRootView();
+        if (mFullscreenPreview == null) {
+            mFullscreenPreview = getPreviewWidget(mContext, mWidgetInfo);
+            mFullscreenPreview.setClickable(false);
+            root.addView(mFullscreenPreview);
+        }
+
+        root.getWindowVisibleDisplayFrame(mTmpRect);
+        final float fsHeight = mTmpRect.height();
+        final float fsCenter = mTmpRect.top + fsHeight / 2;
+
+        final float fsScaleY = pvHeight / fsHeight;
+        final float fsTransY = pvCenter - fsCenter;
+        final float fsScaleX = mPreview.getScaleX();
+
+        mPreview.setVisibility(View.GONE);
+        mFullscreenPreview.setVisibility(View.VISIBLE);
+        mFullscreenPreview.setTranslationY(fsTransY);
+        mFullscreenPreview.setScaleX(fsScaleX);
+        mFullscreenPreview.setScaleY(fsScaleY);
+        mFullscreenPreview
+            .animate()
+            .scaleX(1)
+            .scaleY(1)
+            .translationX(0)
+            .translationY(0)
+            .setDuration(WIDGET_ANIMATION_DURATION)
+            .withEndAction(mPostTransitionToCameraEndAction)
+            .start();
         mCallbacks.onLaunchingCamera();
     }
 
     private void recover() {
         if (DEBUG) Log.d(TAG, "recovering at " + SystemClock.uptimeMillis());
-        mRecovering = true;
-        animate()
-            .scaleX(1)
-            .scaleY(1)
-            .translationY(0)
-            .setDuration(WIDGET_ANIMATION_DURATION)
-            .withEndAction(mRecoverEndAction)
-            .start();
+        mCallbacks.onCameraLaunchedUnsuccessfully();
+        reset();
+    }
+
+    @Override
+    public void setOnLongClickListener(OnLongClickListener l) {
+        // ignore
     }
 
     @Override
@@ -340,8 +342,8 @@
             return true;
         }
 
-        getLocationOnScreen(mScreenLocation);
-        int rawBottom = mScreenLocation[1] + getHeight();
+        getLocationOnScreen(mTmpLoc);
+        int rawBottom = mTmpLoc[1] + getHeight();
         if (event.getRawY() > rawBottom) {
             if (DEBUG) Log.d(TAG, "onUserInteraction eaten: below widget");
             return true;
@@ -388,14 +390,14 @@
         if (DEBUG) Log.d(TAG, "reset at " + SystemClock.uptimeMillis());
         mLaunchCameraStart = 0;
         mTransitioning = false;
-        mRecovering = false;
         mDown = false;
         cancelTransitionToCamera();
         mHandler.removeCallbacks(mRecoverRunnable);
-        animate().cancel();
-        setScaleX(1);
-        setScaleY(1);
-        setTranslationY(0);
+        mPreview.setVisibility(View.VISIBLE);
+        if (mFullscreenPreview != null) {
+            mFullscreenPreview.animate().cancel();
+            mFullscreenPreview.setVisibility(View.GONE);
+        }
         enableWindowExitAnimation(true);
     }
 
@@ -403,11 +405,18 @@
     protected void onSizeChanged(int w, int h, int oldw, int oldh) {
         if (DEBUG) Log.d(TAG, String.format("onSizeChanged new=%sx%s old=%sx%s at %s",
                 w, h, oldw, oldh, SystemClock.uptimeMillis()));
-        final Handler worker =  getWorkerHandler();
-        (worker != null ? worker : mHandler).post(mRenderRunnable);
+        mHandler.post(mRenderRunnable);
         super.onSizeChanged(w, h, oldw, oldh);
     }
 
+    @Override
+    public void onBouncerShowing(boolean showing) {
+        if (showing) {
+            mTransitioning = false;
+            mHandler.post(mRecoverRunnable);
+        }
+    }
+
     private void enableWindowExitAnimation(boolean isEnabled) {
         View root = getRootView();
         ViewGroup.LayoutParams lp = root.getLayoutParams();
@@ -427,15 +436,14 @@
         if (DEBUG) Log.d(TAG, "onKeyguardVisibilityChanged " + showing
                 + " at " + SystemClock.uptimeMillis());
         if (mTransitioning && !showing) {
-          mTransitioning = false;
-          mRecovering = false;
-          mHandler.removeCallbacks(mRecoverRunnable);
-          if (mLaunchCameraStart > 0) {
-              long launchTime = SystemClock.uptimeMillis() - mLaunchCameraStart;
-              if (DEBUG) Log.d(TAG, String.format("Camera took %sms to launch", launchTime));
-              mLaunchCameraStart = 0;
-              onCameraLaunched();
-          }
+            mTransitioning = false;
+            mHandler.removeCallbacks(mRecoverRunnable);
+            if (mLaunchCameraStart > 0) {
+                long launchTime = SystemClock.uptimeMillis() - mLaunchCameraStart;
+                if (DEBUG) Log.d(TAG, String.format("Camera took %sms to launch", launchTime));
+                mLaunchCameraStart = 0;
+                onCameraLaunched();
+            }
         }
     }
 
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/FaceUnlock.java b/policy/src/com/android/internal/policy/impl/keyguard/FaceUnlock.java
index 259f1e4..830471a 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/FaceUnlock.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/FaceUnlock.java
@@ -31,6 +31,7 @@
 import android.os.Message;
 import android.os.PowerManager;
 import android.os.RemoteException;
+import android.os.UserHandle;
 import android.util.Log;
 import android.view.View;
 
@@ -214,7 +215,7 @@
                 handleServiceDisconnected();
                 break;
             case MSG_UNLOCK:
-                handleUnlock();
+                handleUnlock(msg.arg1);
                 break;
             case MSG_CANCEL:
                 handleCancel();
@@ -297,11 +298,18 @@
     /**
      * Stops the Face Unlock service and tells the device to grant access to the user.
      */
-    void handleUnlock() {
+    void handleUnlock(int authenticatedUserId) {
         if (DEBUG) Log.d(TAG, "handleUnlock()");
         stop();
-        mKeyguardScreenCallback.reportSuccessfulUnlockAttempt();
-        mKeyguardScreenCallback.dismiss(true);
+        int currentUserId = mLockPatternUtils.getCurrentUser();
+        if (authenticatedUserId == currentUserId) {
+            if (DEBUG) Log.d(TAG, "Unlocking for user " + authenticatedUserId);
+            mKeyguardScreenCallback.reportSuccessfulUnlockAttempt();
+            mKeyguardScreenCallback.dismiss(true);
+        } else {
+            Log.d(TAG, "Ignoring unlock for authenticated user (" + authenticatedUserId +
+                    ") because the current user is " + currentUserId);
+        }
     }
 
     /**
@@ -420,7 +428,8 @@
          */
         public void unlock() {
             if (DEBUG) Log.d(TAG, "unlock()");
-            mHandler.sendEmptyMessage(MSG_UNLOCK);
+            Message message = mHandler.obtainMessage(MSG_UNLOCK, UserHandle.getCallingUserId(), -1);
+            mHandler.sendMessage(message);
         }
 
         /**
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardCircleFramedDrawable.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardCircleFramedDrawable.java
index 29124c4..79b66f4 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardCircleFramedDrawable.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardCircleFramedDrawable.java
@@ -134,7 +134,6 @@
     }
 
     public void setScale(float scale) {
-        Log.i("KFD", "scale: " + scale);
         mScale = scale;
     }
 
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java
index de19bd5..b05d111 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java
@@ -26,7 +26,6 @@
 import android.appwidget.AppWidgetHostView;
 import android.appwidget.AppWidgetManager;
 import android.appwidget.AppWidgetProviderInfo;
-import android.content.ActivityNotFoundException;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -41,6 +40,7 @@
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.provider.Settings;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.util.Slog;
@@ -82,6 +82,7 @@
     private int mAppWidgetToShow;
 
     private boolean mCheckAppWidgetConsistencyOnBootCompleted = false;
+    private boolean mCleanupAppWidgetsOnBootCompleted = false;
 
     protected OnDismissAction mDismissAction;
 
@@ -91,8 +92,6 @@
     private KeyguardSecurityModel mSecurityModel;
     private KeyguardViewStateManager mViewStateManager;
 
-    boolean mPersitentStickyWidgetLoaded = false;
-
     private Rect mTempRect = new Rect();
 
     private int mDisabledFeatures;
@@ -101,6 +100,10 @@
 
     private boolean mSafeModeEnabled;
 
+    private boolean mUserSetupCompleted;
+    // User for whom this host view was created
+    private int mUserId;
+
     /*package*/ interface TransportCallback {
         void onListenerDetached();
         void onListenerAttached();
@@ -126,8 +129,12 @@
     public KeyguardHostView(Context context, AttributeSet attrs) {
         super(context, attrs);
         mLockPatternUtils = new LockPatternUtils(context);
+        mUserId = mLockPatternUtils.getCurrentUser();
         mAppWidgetHost = new AppWidgetHost(
                 context, APPWIDGET_HOST_ID, mOnClickHandler, Looper.myLooper());
+        mAppWidgetHost.setUserId(mUserId);
+        cleanupAppWidgetIds();
+
         mAppWidgetManager = AppWidgetManager.getInstance(mContext);
         mSecurityModel = new KeyguardSecurityModel(context);
 
@@ -141,6 +148,8 @@
         }
 
         mSafeModeEnabled = LockPatternUtils.isSafeModeEnabled();
+        mUserSetupCompleted = Settings.Secure.getIntForUser(mContext.getContentResolver(),
+                Settings.Secure.USER_SETUP_COMPLETE, 0, UserHandle.USER_CURRENT) != 0;
 
         if (mSafeModeEnabled) {
             Log.v(TAG, "Keyguard widgets disabled by safe mode");
@@ -153,6 +162,39 @@
         }
     }
 
+    private void cleanupAppWidgetIds() {
+        // Since this method may delete a widget (which we can't do until boot completed) we
+        // may have to defer it until after boot complete.
+        if (!KeyguardUpdateMonitor.getInstance(mContext).hasBootCompleted()) {
+            mCleanupAppWidgetsOnBootCompleted = true;
+            return;
+        }
+        // Clean up appWidgetIds that are bound to lockscreen, but not actually used
+        // This is only to clean up after another bug: we used to not call
+        // deleteAppWidgetId when a user manually deleted a widget in keyguard. This code
+        // shouldn't have to run more than once per user. AppWidgetProviders rely on callbacks
+        // that are triggered by deleteAppWidgetId, which is why we're doing this
+        int[] appWidgetIdsInKeyguardSettings = mLockPatternUtils.getAppWidgets();
+        int[] appWidgetIdsBoundToHost = mAppWidgetHost.getAppWidgetIds();
+        for (int i = 0; i < appWidgetIdsBoundToHost.length; i++) {
+            int appWidgetId = appWidgetIdsBoundToHost[i];
+            if (!contains(appWidgetIdsInKeyguardSettings, appWidgetId)) {
+                Log.d(TAG, "Found a appWidgetId that's not being used by keyguard, deleting id "
+                        + appWidgetId);
+                mAppWidgetHost.deleteAppWidgetId(appWidgetId);
+            }
+        }
+    }
+
+    private static boolean contains(int[] array, int target) {
+        for (int value : array) {
+            if (value == target) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     private KeyguardUpdateMonitorCallback mUpdateMonitorCallbacks =
             new KeyguardUpdateMonitorCallback() {
         @Override
@@ -162,6 +204,10 @@
                 mSwitchPageRunnable.run();
                 mCheckAppWidgetConsistencyOnBootCompleted = false;
             }
+            if (mCleanupAppWidgetsOnBootCompleted) {
+                cleanupAppWidgetIds();
+                mCleanupAppWidgetsOnBootCompleted = false;
+            }
         }
     };
 
@@ -231,8 +277,8 @@
         addDefaultWidgets();
 
         addWidgetsFromSettings();
-        if (numWidgets() >= MAX_WIDGETS) {
-            setAddWidgetEnabled(false);
+        if (!shouldEnableAddWidget()) {
+            mAppWidgetContainer.setAddWidgetEnabled(false);
         }
         checkAppWidgetConsistency();
         mSwitchPageRunnable.run();
@@ -243,6 +289,10 @@
         updateSecurityViews();
     }
 
+    private boolean shouldEnableAddWidget() {
+        return numWidgets() < MAX_WIDGETS && mUserSetupCompleted;
+    }
+
     private int getDisabledFeatures(DevicePolicyManager dpm) {
         int disabledFeatures = DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_NONE;
         if (dpm != null) {
@@ -292,14 +342,14 @@
     @Override
     protected void onAttachedToWindow() {
         super.onAttachedToWindow();
-        mAppWidgetHost.startListening();
+        mAppWidgetHost.startListeningAsUser(mUserId);
         KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mUpdateMonitorCallbacks);
     }
 
     @Override
     protected void onDetachedFromWindow() {
         super.onDetachedFromWindow();
-        mAppWidgetHost.stopListening();
+        mAppWidgetHost.stopListeningAsUser(mUserId);
         KeyguardUpdateMonitor.getInstance(mContext).removeCallback(mUpdateMonitorCallbacks);
     }
 
@@ -325,15 +375,26 @@
 
         @Override
         public void onAddView(View v) {
-            if (numWidgets() >= MAX_WIDGETS) {
-                setAddWidgetEnabled(false);
+            if (!shouldEnableAddWidget()) {
+                mAppWidgetContainer.setAddWidgetEnabled(false);
             }
-        };
+        }
 
         @Override
-        public void onRemoveView(View v) {
-            if (numWidgets() < MAX_WIDGETS) {
-                setAddWidgetEnabled(true);
+        public void onRemoveView(View v, boolean deletePermanently) {
+            if (deletePermanently) {
+                final int appWidgetId = ((KeyguardWidgetFrame) v).getContentAppWidgetId();
+                if (appWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID &&
+                        appWidgetId != LockPatternUtils.ID_DEFAULT_STATUS_WIDGET) {
+                    mAppWidgetHost.deleteAppWidgetId(appWidgetId);
+                }
+            }
+        }
+
+        @Override
+        public void onRemoveViewAnimationCompleted() {
+            if (shouldEnableAddWidget()) {
+                mAppWidgetContainer.setAddWidgetEnabled(true);
             }
         }
     };
@@ -821,6 +882,7 @@
         if (mViewStateManager != null) {
             mViewStateManager.showUsabilityHints();
         }
+        requestFocus();
     }
 
     @Override
@@ -840,6 +902,7 @@
         if (cameraPage != null) {
             cameraPage.onScreenTurnedOff();
         }
+        clearFocus();
     }
 
     public void clearAppWidgetToShow() {
@@ -1009,15 +1072,6 @@
         return widgetCount;
     }
 
-
-    private void setAddWidgetEnabled(boolean clickable) {
-        View addWidget = mAppWidgetContainer.findViewById(R.id.keyguard_add_widget);
-        if (addWidget != null) {
-            View addWidgetButton = addWidget.findViewById(R.id.keyguard_add_widget_view);
-            addWidgetButton.setEnabled(clickable);
-        }
-    }
-
     private void addDefaultWidgets() {
         LayoutInflater inflater = LayoutInflater.from(mContext);
         inflater.inflate(R.layout.keyguard_transport_control_view, this, true);
@@ -1038,7 +1092,7 @@
         // We currently disable cameras in safe mode because we support loading 3rd party
         // cameras we can't trust.  TODO: plumb safe mode into camera creation code and only
         // inflate system-provided camera?
-        if (!mSafeModeEnabled && !cameraDisabledByDpm()
+        if (!mSafeModeEnabled && !cameraDisabledByDpm() && mUserSetupCompleted
                 && mContext.getResources().getBoolean(R.bool.kg_enable_camera_default_widget)) {
             View cameraWidget =
                     CameraWidgetFrame.create(mContext, mCameraWidgetCallbacks, mActivityLauncher);
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardMessageArea.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardMessageArea.java
index ee5c4a6..210312a 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardMessageArea.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardMessageArea.java
@@ -21,6 +21,7 @@
 import android.animation.ObjectAnimator;
 import android.content.ContentResolver;
 import android.content.Context;
+import android.os.BatteryManager;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.UserHandle;
@@ -51,7 +52,7 @@
     boolean mShowingBouncer = false;
 
     // last known plugged in state
-    boolean mPluggedIn = false;
+    boolean mCharging = false;
 
     // last known battery level
     int mBatteryLevel = 100;
@@ -134,7 +135,8 @@
         @Override
         public void onRefreshBatteryInfo(KeyguardUpdateMonitor.BatteryStatus status) {
             mShowingBatteryInfo = status.isPluggedIn() || status.isBatteryLow();
-            mPluggedIn = status.isPluggedIn();
+            mCharging = status.status == BatteryManager.BATTERY_STATUS_CHARGING
+                     || status.status == BatteryManager.BATTERY_STATUS_FULL;
             mBatteryLevel = status.level;
             mBatteryCharged = status.isCharged();
             mBatteryIsLow = status.isBatteryLow();
@@ -223,11 +225,11 @@
         CharSequence string = null;
         if (mShowingBatteryInfo && !mShowingMessage) {
             // Battery status
-            if (mPluggedIn) {
+            if (mCharging) {
                 // Charging, charged or waiting to charge.
-                string = getContext().getString(mBatteryCharged ?
-                        com.android.internal.R.string.lockscreen_charged
-                        :com.android.internal.R.string.lockscreen_plugged_in, mBatteryLevel);
+                string = getContext().getString(mBatteryCharged
+                        ? com.android.internal.R.string.lockscreen_charged
+                        : com.android.internal.R.string.lockscreen_plugged_in, mBatteryLevel);
                 icon.value = CHARGING_ICON;
             } else if (mBatteryIsLow) {
                 // Battery is low
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardTransportControlView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardTransportControlView.java
index d284602..ffa88d5 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardTransportControlView.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardTransportControlView.java
@@ -189,7 +189,7 @@
 
     public KeyguardTransportControlView(Context context, AttributeSet attrs) {
         super(context, attrs);
-        Log.v(TAG, "Create TCV " + this);
+        if (DEBUG) Log.v(TAG, "Create TCV " + this);
         mAudioManager = new AudioManager(mContext);
         mCurrentPlayState = RemoteControlClient.PLAYSTATE_NONE; // until we get a callback
         mIRCD = new IRemoteControlDisplayWeak(mHandler);
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardUpdateMonitor.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardUpdateMonitor.java
index 1968ecd..ad6f55c 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardUpdateMonitor.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardUpdateMonitor.java
@@ -37,6 +37,7 @@
 import android.os.IRemoteCallback;
 import android.os.Message;
 import android.os.RemoteException;
+import android.os.UserHandle;
 import android.provider.Settings;
 
 import com.android.internal.telephony.IccCardConstants;
@@ -113,7 +114,7 @@
 
     private final ArrayList<WeakReference<KeyguardUpdateMonitorCallback>>
             mCallbacks = Lists.newArrayList();
-    private ContentObserver mContentObserver;
+    private ContentObserver mDeviceProvisionedObserver;
 
     private final Handler mHandler = new Handler() {
         @Override
@@ -322,9 +323,7 @@
     private KeyguardUpdateMonitor(Context context) {
         mContext = context;
 
-        mDeviceProvisioned = Settings.Global.getInt(
-                mContext.getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 0) != 0;
-
+        mDeviceProvisioned = isDeviceProvisionedInSettingsDb();
         // Since device can't be un-provisioned, we only need to register a content observer
         // to update mDeviceProvisioned when we are...
         if (!mDeviceProvisioned) {
@@ -373,13 +372,17 @@
         }
     }
 
+    private boolean isDeviceProvisionedInSettingsDb() {
+        return Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.DEVICE_PROVISIONED, 0) != 0;
+    }
+
     private void watchForDeviceProvisioning() {
-        mContentObserver = new ContentObserver(mHandler) {
+        mDeviceProvisionedObserver = new ContentObserver(mHandler) {
             @Override
             public void onChange(boolean selfChange) {
                 super.onChange(selfChange);
-                mDeviceProvisioned = Settings.Global.getInt(mContext.getContentResolver(),
-                    Settings.Global.DEVICE_PROVISIONED, 0) != 0;
+                mDeviceProvisioned = isDeviceProvisionedInSettingsDb();
                 if (mDeviceProvisioned) {
                     mHandler.sendMessage(mHandler.obtainMessage(MSG_DEVICE_PROVISIONED));
                 }
@@ -389,12 +392,11 @@
 
         mContext.getContentResolver().registerContentObserver(
                 Settings.Global.getUriFor(Settings.Global.DEVICE_PROVISIONED),
-                false, mContentObserver);
+                false, mDeviceProvisionedObserver);
 
         // prevent a race condition between where we check the flag and where we register the
         // observer by grabbing the value once again...
-        boolean provisioned = Settings.Global.getInt(mContext.getContentResolver(),
-            Settings.Global.DEVICE_PROVISIONED, 0) != 0;
+        boolean provisioned = isDeviceProvisionedInSettingsDb();
         if (provisioned != mDeviceProvisioned) {
             mDeviceProvisioned = provisioned;
             if (mDeviceProvisioned) {
@@ -475,10 +477,10 @@
                 cb.onDeviceProvisioned();
             }
         }
-        if (mContentObserver != null) {
+        if (mDeviceProvisionedObserver != null) {
             // We don't need the observer anymore...
-            mContext.getContentResolver().unregisterContentObserver(mContentObserver);
-            mContentObserver = null;
+            mContext.getContentResolver().unregisterContentObserver(mDeviceProvisionedObserver);
+            mDeviceProvisionedObserver = null;
         }
     }
 
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewManager.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewManager.java
index 76ba811..b6cf4da 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewManager.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewManager.java
@@ -24,6 +24,7 @@
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.graphics.PixelFormat;
+import android.graphics.Rect;
 import android.os.Bundle;
 import android.os.IBinder;
 import android.os.Parcelable;
@@ -127,23 +128,43 @@
         }
 
         @Override
+        protected boolean fitSystemWindows(Rect insets) {
+            Log.v("TAG", "bug 7643792: fitSystemWindows(" + insets.toShortString() + ")");
+            return super.fitSystemWindows(insets);
+        }
+
+        @Override
         protected void onConfigurationChanged(Configuration newConfig) {
             super.onConfigurationChanged(newConfig);
-            if (mKeyguardHost.getVisibility() == View.VISIBLE) {
-                // only propagate configuration messages if we're currently showing
-                maybeCreateKeyguardLocked(shouldEnableScreenRotation(), true, null);
-            } else {
-                if (DEBUG) Log.v(TAG, "onConfigurationChanged: view not visible");
-            }
+            post(new Runnable() {
+                @Override
+                public void run() {
+                    synchronized (KeyguardViewManager.this) {
+                        if (mKeyguardHost.getVisibility() == View.VISIBLE) {
+                            // only propagate configuration messages if we're currently showing
+                            maybeCreateKeyguardLocked(shouldEnableScreenRotation(), true, null);
+                        } else {
+                            if (DEBUG) Log.v(TAG, "onConfigurationChanged: view not visible");
+                        }
+                    }
+                }
+            });
         }
 
         @Override
         public boolean dispatchKeyEvent(KeyEvent event) {
-            if (event.getAction() == KeyEvent.ACTION_DOWN && mKeyguardView != null) {
-                int keyCode = event.getKeyCode();
-                if (keyCode == KeyEvent.KEYCODE_BACK && mKeyguardView.handleBackKey()) {
-                    return true;
-                } else if (keyCode == KeyEvent.KEYCODE_MENU && mKeyguardView.handleMenuKey()) {
+            if (mKeyguardView != null) {
+                // Always process back and menu keys, regardless of focus
+                if (event.getAction() == KeyEvent.ACTION_DOWN) {
+                    int keyCode = event.getKeyCode();
+                    if (keyCode == KeyEvent.KEYCODE_BACK && mKeyguardView.handleBackKey()) {
+                        return true;
+                    } else if (keyCode == KeyEvent.KEYCODE_MENU && mKeyguardView.handleMenuKey()) {
+                        return true;
+                    }
+                }
+                // Always process media keys, regardless of focus
+                if (mKeyguardView.dispatchKeyEvent(event)) {
                     return true;
                 }
             }
@@ -202,6 +223,7 @@
 
         if (force || mKeyguardView == null) {
             inflateKeyguardView(options);
+            mKeyguardView.requestFocus();
         }
         updateUserActivityTimeoutInWindowLayoutParams();
         mViewManager.updateViewLayout(mKeyguardHost, mWindowLayoutParams);
@@ -236,12 +258,6 @@
         }
 
         if (options != null) {
-            if (options.getBoolean(LockPatternUtils.KEYGUARD_SHOW_USER_SWITCHER)) {
-                mKeyguardView.goToUserSwitcher();
-            }
-            if (options.getBoolean(LockPatternUtils.KEYGUARD_SHOW_SECURITY_CHALLENGE)) {
-                mKeyguardView.showNextSecurityScreenIfPresent();
-            }
             int widgetToShow = options.getInt(LockPatternUtils.KEYGUARD_SHOW_APPWIDGET,
                     AppWidgetManager.INVALID_APPWIDGET_ID);
             if (widgetToShow != AppWidgetManager.INVALID_APPWIDGET_ID) {
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java
index df4c661..7d757ff 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java
@@ -22,6 +22,7 @@
 import android.app.ActivityManagerNative;
 import android.app.AlarmManager;
 import android.app.PendingIntent;
+import android.app.SearchManager;
 import android.app.StatusBarManager;
 import android.content.BroadcastReceiver;
 import android.content.ContentResolver;
@@ -166,6 +167,9 @@
     /** UserManager for querying number of users */
     private UserManager mUserManager;
 
+    /** SearchManager for determining whether or not search assistant is available */
+    private SearchManager mSearchManager;
+
     /**
      * Used to keep the device awake while to ensure the keyguard finishes opening before
      * we sleep.
@@ -311,10 +315,7 @@
             // We need to force a reset of the views, since lockNow (called by
             // ActivityManagerService) will not reconstruct the keyguard if it is already showing.
             synchronized (KeyguardViewMediator.this) {
-                Bundle options = new Bundle();
-                options.putBoolean(LockPatternUtils.KEYGUARD_SHOW_USER_SWITCHER, true);
-                options.putBoolean(LockPatternUtils.KEYGUARD_SHOW_SECURITY_CHALLENGE, true);
-                resetStateLocked(options);
+                resetStateLocked(null);
                 adjustStatusBarLocked();
                 // Disable face unlock when the user switches.
                 KeyguardUpdateMonitor.getInstance(mContext).setAlternateUnlockEnabled(false);
@@ -527,6 +528,7 @@
      * Let us know that the system is ready after startup.
      */
     public void onSystemReady() {
+        mSearchManager = (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE);
         synchronized (this) {
             if (DEBUG) Log.d(TAG, "onSystemReady");
             mSystemReady = true;
@@ -1313,6 +1315,9 @@
                     // showing secure lockscreen; disable ticker.
                     flags |= StatusBarManager.DISABLE_NOTIFICATION_TICKER;
                 }
+                if (!isAssistantAvailable()) {
+                    flags |= StatusBarManager.DISABLE_SEARCH;
+                }
             }
 
             if (DEBUG) {
@@ -1410,4 +1415,8 @@
         mKeyguardViewManager.showAssistant();
     }
 
+    private boolean isAssistantAvailable() {
+        return mSearchManager != null
+                && mSearchManager.getAssistIntent(mContext, UserHandle.USER_CURRENT) != null;
+    }
 }
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetCarousel.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetCarousel.java
index debf765..257fd27 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetCarousel.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetCarousel.java
@@ -16,7 +16,6 @@
 package com.android.internal.policy.impl.keyguard;
 
 import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
 import android.animation.AnimatorSet;
 import android.animation.ObjectAnimator;
 import android.animation.PropertyValuesHolder;
@@ -27,10 +26,10 @@
 import android.view.animation.DecelerateInterpolator;
 import android.view.animation.Interpolator;
 
-import java.util.ArrayList;
-
 import com.android.internal.R;
 
+import java.util.ArrayList;
+
 public class KeyguardWidgetCarousel extends KeyguardWidgetPager {
 
     private float mAdjacentPagesAngle;
@@ -56,17 +55,30 @@
         return MAX_SCROLL_PROGRESS;
     }
 
-    public float getAlphaForPage(int screenCenter, int index) {
+    public float getAlphaForPage(int screenCenter, int index, boolean showSidePages) {
         View child = getChildAt(index);
         if (child == null) return 0f;
 
+        boolean inVisibleRange = index >= getNextPage() - 1 && index <= getNextPage() + 1;
         float scrollProgress = getScrollProgress(screenCenter, child, index);
-        if (!isOverScrollChild(index, scrollProgress)) {
+
+        if (isOverScrollChild(index, scrollProgress)) {
+            return 1.0f;
+        } else if ((showSidePages && inVisibleRange) || index == getNextPage()) {
             scrollProgress = getBoundedScrollProgress(screenCenter, child, index);
             float alpha = 1.0f - 1.0f * Math.abs(scrollProgress / MAX_SCROLL_PROGRESS);
             return alpha;
         } else {
-            return 1.0f;
+            return 0f;
+        }
+    }
+
+    public float getOutlineAlphaForPage(int screenCenter, int index, boolean showSidePages) {
+        boolean inVisibleRange = index >= getNextPage() - 1 && index <= getNextPage() + 1;
+        if (inVisibleRange) {
+            return super.getOutlineAlphaForPage(screenCenter, index, showSidePages);
+        } else {
+            return 0f;
         }
     }
 
@@ -75,24 +87,32 @@
             mChildrenOutlineFadeAnimation.cancel();
             mChildrenOutlineFadeAnimation = null;
         }
+        boolean showSidePages = mShowingInitialHints || isPageMoving();
         if (!isReordering(false)) {
             for (int i = 0; i < getChildCount(); i++) {
                 KeyguardWidgetFrame child = getWidgetPageAt(i);
                 if (child != null) {
-                    child.setBackgroundAlpha(getOutlineAlphaForPage(screenCenter, i));
-                    child.setContentAlpha(getAlphaForPage(screenCenter, i));
+                    float outlineAlpha = getOutlineAlphaForPage(screenCenter, i, showSidePages);
+                    float contentAlpha = getAlphaForPage(screenCenter, i,showSidePages);
+                    child.setBackgroundAlpha(outlineAlpha);
+                    child.setContentAlpha(contentAlpha);
                 }
             }
         }
     }
 
     public void showInitialPageHints() {
+        mShowingInitialHints = true;
         int count = getChildCount();
         for (int i = 0; i < count; i++) {
+            boolean inVisibleRange = i >= getNextPage() - 1 && i <= getNextPage() + 1;
             KeyguardWidgetFrame child = getWidgetPageAt(i);
-            if (i >= mCurrentPage - 1 && i <= mCurrentPage + 1) {
-                child.fadeFrame(this, true, KeyguardWidgetFrame.OUTLINE_ALPHA_MULTIPLIER,
-                        CHILDREN_OUTLINE_FADE_IN_DURATION);
+            if (inVisibleRange) {
+                child.setBackgroundAlpha(KeyguardWidgetFrame.OUTLINE_ALPHA_MULTIPLIER);
+                child.setContentAlpha(1f);
+            } else {
+                child.setBackgroundAlpha(0f);
+                child.setContentAlpha(0f);
             }
         }
     }
@@ -220,8 +240,8 @@
 
         for (int i = 0; i < count; i++) {
             KeyguardWidgetFrame child = getWidgetPageAt(i);
-            float finalAlpha = getAlphaForPage(mScreenCenter, i);
-            float finalOutlineAlpha = getOutlineAlphaForPage(mScreenCenter, i);
+            float finalAlpha = getAlphaForPage(mScreenCenter, i, true);
+            float finalOutlineAlpha = getOutlineAlphaForPage(mScreenCenter, i, true);
             getTransformForPage(mScreenCenter, i, mTmpTransform);
 
             boolean inVisibleRange = (i >= mCurrentPage - 1 && i <= mCurrentPage + 1);
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetFrame.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetFrame.java
index 3c79206..babb9cb 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetFrame.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetFrame.java
@@ -424,7 +424,9 @@
             mBgAlphaController = caller;
         }
 
-        if (mBgAlphaController != caller) return;
+        if (mBgAlphaController != caller && mBgAlphaController != null) {
+            return;
+        }
 
         if (mFrameFade != null) {
             mFrameFade.cancel();
@@ -512,6 +514,10 @@
         return false;
     }
 
+    public void onBouncerShowing(boolean showing) {
+        // hook for subclasses
+    }
+
     public void setWorkerHandler(Handler workerHandler) {
         mWorkerHandler = workerHandler;
     }
@@ -519,4 +525,5 @@
     public Handler getWorkerHandler() {
         return mWorkerHandler;
     }
+
 }
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java
index 25e2781..b4fe0c7 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java
@@ -70,6 +70,12 @@
     private Callbacks mCallbacks;
 
     private int mWidgetToResetAfterFadeOut;
+    protected boolean mShowingInitialHints = false;
+
+    // A temporary handle to the Add-Widget view
+    private View mAddWidgetView;
+    private int mLastWidthMeasureSpec;
+    private int mLastHeightMeasureSpec;
 
     // Bouncer
     private int mBouncerZoomInOutDuration = 250;
@@ -237,18 +243,18 @@
         public void userActivity();
         public void onUserActivityTimeoutChanged();
         public void onAddView(View v);
-        public void onRemoveView(View v);
+        public void onRemoveView(View v, boolean deletePermanently);
+        public void onRemoveViewAnimationCompleted();
     }
 
     public void addWidget(View widget) {
         addWidget(widget, -1);
     }
 
-
-    public void onRemoveView(View v) {
+    public void onRemoveView(View v, final boolean deletePermanently) {
         final int appWidgetId = ((KeyguardWidgetFrame) v).getContentAppWidgetId();
         if (mCallbacks != null) {
-            mCallbacks.onRemoveView(v);
+            mCallbacks.onRemoveView(v, deletePermanently);
         }
         mBackgroundWorkerHandler.post(new Runnable() {
             @Override
@@ -258,6 +264,13 @@
         });
     }
 
+    @Override
+    public void onRemoveViewAnimationCompleted() {
+        if (mCallbacks != null) {
+            mCallbacks.onRemoveViewAnimationCompleted();
+        }
+    }
+
     public void onAddView(View v, final int index) {
         final int appWidgetId = ((KeyguardWidgetFrame) v).getContentAppWidgetId();
         final int[] pagesRange = new int[mTempVisiblePagesRange.length];
@@ -458,12 +471,21 @@
     private void updatePageAlphaValues(int screenCenter) {
     }
 
-    public float getAlphaForPage(int screenCenter, int index) {
-        return 1f;
+    public float getAlphaForPage(int screenCenter, int index, boolean showSidePages) {
+        if (showSidePages) {
+            return 1f;
+        } else {
+            return index == mCurrentPage ? 1.0f : 0f;
+        }
     }
 
-    public float getOutlineAlphaForPage(int screenCenter, int index) {
-        return getAlphaForPage(screenCenter, index) * KeyguardWidgetFrame.OUTLINE_ALPHA_MULTIPLIER;
+    public float getOutlineAlphaForPage(int screenCenter, int index, boolean showSidePages) {
+        if (showSidePages) {
+            return getAlphaForPage(screenCenter, index, showSidePages)
+                    * KeyguardWidgetFrame.OUTLINE_ALPHA_MULTIPLIER;
+        } else {
+            return 0f;
+        }
     }
 
     protected boolean isOverScrollChild(int index, float scrollProgress) {
@@ -562,12 +584,12 @@
     }
 
     public void showInitialPageHints() {
+        mShowingInitialHints = true;
         int count = getChildCount();
         for (int i = 0; i < count; i++) {
             KeyguardWidgetFrame child = getWidgetPageAt(i);
             if (i != mCurrentPage) {
-                child.fadeFrame(this, true, KeyguardWidgetFrame.OUTLINE_ALPHA_MULTIPLIER,
-                        CHILDREN_OUTLINE_FADE_IN_DURATION);
+                child.setBackgroundAlpha(KeyguardWidgetFrame.OUTLINE_ALPHA_MULTIPLIER);
                 child.setContentAlpha(0f);
             } else {
                 child.setBackgroundAlpha(0f);
@@ -576,10 +598,6 @@
         }
     }
 
-    public void showSidePageHints() {
-        animateOutlinesAndSidePages(true, -1);
-    }
-
     @Override
     void setCurrentPage(int currentPage) {
         super.setCurrentPage(currentPage);
@@ -592,12 +610,10 @@
         mHasMeasure = false;
     }
 
-    @Override
-    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
-        super.onLayout(changed, left, top, right, bottom);
-    }
-
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        mLastWidthMeasureSpec = widthMeasureSpec;
+        mLastHeightMeasureSpec = heightMeasureSpec;
+
         int maxChallengeTop = -1;
         View parent = (View) getParent();
         boolean challengeShowing = false;
@@ -658,7 +674,7 @@
         for (int i = 0; i < count; i++) {
             float finalContentAlpha;
             if (show) {
-                finalContentAlpha = getAlphaForPage(mScreenCenter, i);
+                finalContentAlpha = getAlphaForPage(mScreenCenter, i, true);
             } else if (!show && i == curPage) {
                 finalContentAlpha = 1f;
             } else {
@@ -670,7 +686,7 @@
             ObjectAnimator a = ObjectAnimator.ofPropertyValuesHolder(child, alpha);
             anims.add(a);
 
-            float finalOutlineAlpha = show ? getOutlineAlphaForPage(mScreenCenter, i) : 0f;
+            float finalOutlineAlpha = show ? getOutlineAlphaForPage(mScreenCenter, i, true) : 0f;
             child.fadeFrame(this, show, finalOutlineAlpha, duration);
         }
 
@@ -696,6 +712,7 @@
                         frame.resetSize();
                     }
                     mWidgetToResetAfterFadeOut = -1;
+                    mShowingInitialHints = false;
                 }
                 updateWidgetFramesImportantForAccessibility();
             }
@@ -775,6 +792,9 @@
             mZoomInOutAnim.setInterpolator(new DecelerateInterpolator(1.5f));
             mZoomInOutAnim.start();
         }
+        if (currentPage instanceof KeyguardWidgetFrame) {
+            ((KeyguardWidgetFrame)currentPage).onBouncerShowing(false);
+        }
     }
 
     // Zoom out after the bouncer is initiated
@@ -800,6 +820,27 @@
             mZoomInOutAnim.setInterpolator(new DecelerateInterpolator(1.5f));
             mZoomInOutAnim.start();
         }
+        if (currentPage instanceof KeyguardWidgetFrame) {
+            ((KeyguardWidgetFrame)currentPage).onBouncerShowing(true);
+        }
+    }
+
+    void setAddWidgetEnabled(boolean enabled) {
+        if (mAddWidgetView != null && enabled) {
+            addView(mAddWidgetView, 0);
+            // We need to force measure the PagedView so that the calls to update the scroll
+            // position below work
+            measure(mLastWidthMeasureSpec, mLastHeightMeasureSpec);
+            // Bump up the current page to account for the addition of the new page
+            setCurrentPage(mCurrentPage + 1);
+            mAddWidgetView = null;
+        } else if (mAddWidgetView == null && !enabled) {
+            View addWidget = findViewById(com.android.internal.R.id.keyguard_add_widget);
+            if (addWidget != null) {
+                mAddWidgetView = addWidget;
+                removeView(addWidget);
+            }
+        }
     }
 
     boolean isAddPage(int pageIndex) {
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/PagedView.java b/policy/src/com/android/internal/policy/impl/keyguard/PagedView.java
index 3900ab4..539ec1a 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/PagedView.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/PagedView.java
@@ -1019,15 +1019,22 @@
         return  (x > (getViewportOffsetX() + getViewportWidth() - getRelativeChildOffset(mCurrentPage) + mPageSpacing));
     }
 
-    /** Returns whether x and y originated within the buffered/unbuffered viewport */
-    private boolean isTouchPointInViewport(int x, int y, boolean buffer) {
-        if (buffer) {
-            mTmpRect.set(mViewport.left - mViewport.width() / 2, mViewport.top,
-                    mViewport.right + mViewport.width() / 2, mViewport.bottom);
+    /** Returns whether x and y originated within the buffered viewport */
+    private boolean isTouchPointInViewportWithBuffer(int x, int y) {
+        mTmpRect.set(mViewport.left - mViewport.width() / 2, mViewport.top,
+                mViewport.right + mViewport.width() / 2, mViewport.bottom);
+        return mTmpRect.contains(x, y);
+    }
+
+    /** Returns whether x and y originated within the current page view bounds */
+    private boolean isTouchPointInCurrentPage(int x, int y) {
+        View v = getPageAt(getCurrentPage());
+        if (v != null) {
+            mTmpRect.set((v.getLeft() - getScrollX()), 0, (v.getRight() - getScrollX()),
+                    v.getBottom());
             return mTmpRect.contains(x, y);
-        } else {
-            return mViewport.contains(x, y);
         }
+        return false;
     }
 
     @Override
@@ -1108,7 +1115,7 @@
                     mTouchState = TOUCH_STATE_REST;
                     mScroller.abortAnimation();
                 } else {
-                    if (isTouchPointInViewport((int) mDownMotionX, (int) mDownMotionY, true)) {
+                    if (isTouchPointInViewportWithBuffer((int) mDownMotionX, (int) mDownMotionY)) {
                         mTouchState = TOUCH_STATE_SCROLLING;
                     } else {
                         mTouchState = TOUCH_STATE_REST;
@@ -1135,7 +1142,7 @@
             case MotionEvent.ACTION_CANCEL:
                 resetTouchState();
                 // Just intercept the touch event on up if we tap outside the strict viewport
-                if (!isTouchPointInViewport((int) mLastMotionX, (int) mLastMotionY, false)) {
+                if (!isTouchPointInCurrentPage((int) mLastMotionX, (int) mLastMotionY)) {
                     return true;
                 }
                 break;
@@ -1169,7 +1176,7 @@
         // Disallow scrolling if we started the gesture from outside the viewport
         final float x = ev.getX(pointerIndex);
         final float y = ev.getY(pointerIndex);
-        if (!isTouchPointInViewport((int) x, (int) y, true)) return;
+        if (!isTouchPointInViewportWithBuffer((int) x, (int) y)) return;
 
         // If we're only allowing edge swipes, we break out early if the down event wasn't
         // at the edge.
@@ -1457,7 +1464,7 @@
                                 }
 
                                 removeView(mDragView);
-                                onRemoveView(mDragView);
+                                onRemoveView(mDragView, false);
                                 addView(mDragView, pageUnderPointIndex);
                                 onAddView(mDragView, pageUnderPointIndex);
                                 mSidePageHoverIndex = -1;
@@ -1587,7 +1594,8 @@
     }
 
     //public abstract void onFlingToDelete(View v);
-    public abstract void onRemoveView(View v);
+    public abstract void onRemoveView(View v, boolean deletePermanently);
+    public abstract void onRemoveViewAnimationCompleted();
     public abstract void onAddView(View v, int index);
 
     private void resetTouchState() {
@@ -2383,6 +2391,7 @@
                             public void run() {
                                 mDeferringForDelete = false;
                                 onEndReordering();
+                                onRemoveViewAnimationCompleted();
                             }
                         };
                         zoomIn(onCompleteRunnable);
@@ -2391,7 +2400,7 @@
                 slideAnimations.start();
 
                 removeView(dragView);
-                onRemoveView(dragView);
+                onRemoveView(dragView, true);
             }
         };
     }
diff --git a/services/java/com/android/server/AlarmManagerService.java b/services/java/com/android/server/AlarmManagerService.java
index 440f8e1..cbd00f3 100644
--- a/services/java/com/android/server/AlarmManagerService.java
+++ b/services/java/com/android/server/AlarmManagerService.java
@@ -22,6 +22,7 @@
 import android.app.IAlarmManager;
 import android.app.PendingIntent;
 import android.content.BroadcastReceiver;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
@@ -38,6 +39,7 @@
 import android.os.WorkSource;
 import android.text.TextUtils;
 import android.text.format.Time;
+import android.util.Pair;
 import android.util.Slog;
 import android.util.TimeUtils;
 
@@ -45,16 +47,18 @@
 import java.io.PrintWriter;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Calendar;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.Iterator;
-import java.util.LinkedList;
 import java.util.Map;
 import java.util.TimeZone;
 
+import com.android.internal.util.LocalLog;
+
 class AlarmManagerService extends IAlarmManager.Stub {
     // The threshold for how long an alarm can be late before we print a
     // warning message.  The time duration is in milliseconds.
@@ -79,7 +83,9 @@
             = new Intent().addFlags(Intent.FLAG_FROM_BACKGROUND);
     
     private final Context mContext;
-    
+
+    private final LocalLog mLog = new LocalLog(TAG);
+
     private Object mLock = new Object();
     
     private final ArrayList<Alarm> mRtcWakeupAlarms = new ArrayList<Alarm>();
@@ -91,7 +97,7 @@
     private int mDescriptor;
     private int mBroadcastRefCount = 0;
     private PowerManager.WakeLock mWakeLock;
-    private LinkedList<PendingIntent> mInFlight = new LinkedList<PendingIntent>();
+    private ArrayList<InFlight> mInFlight = new ArrayList<InFlight>();
     private final AlarmThread mWaitThread = new AlarmThread();
     private final AlarmHandler mHandler = new AlarmHandler();
     private ClockReceiver mClockReceiver;
@@ -99,18 +105,59 @@
     private final ResultReceiver mResultReceiver = new ResultReceiver();
     private final PendingIntent mTimeTickSender;
     private final PendingIntent mDateChangeSender;
-    
-    private static final class FilterStats {
-        int count;
+
+    private static final class InFlight extends Intent {
+        final PendingIntent mPendingIntent;
+        final Pair<String, ComponentName> mTarget;
+        final BroadcastStats mBroadcastStats;
+        final FilterStats mFilterStats;
+
+        InFlight(AlarmManagerService service, PendingIntent pendingIntent) {
+            mPendingIntent = pendingIntent;
+            Intent intent = pendingIntent.getIntent();
+            mTarget = intent != null
+                    ? new Pair<String, ComponentName>(intent.getAction(), intent.getComponent())
+                    : null;
+            mBroadcastStats = service.getStatsLocked(pendingIntent);
+            FilterStats fs = mBroadcastStats.filterStats.get(mTarget);
+            if (fs == null) {
+                fs = new FilterStats(mBroadcastStats, mTarget);
+                mBroadcastStats.filterStats.put(mTarget, fs);
+            }
+            mFilterStats = fs;
+        }
     }
-    
-    private static final class BroadcastStats {
+
+    private static final class FilterStats {
+        final BroadcastStats mBroadcastStats;
+        final Pair<String, ComponentName> mTarget;
+
         long aggregateTime;
+        int count;
         int numWakeup;
         long startTime;
         int nesting;
-        HashMap<Intent.FilterComparison, FilterStats> filterStats
-                = new HashMap<Intent.FilterComparison, FilterStats>();
+
+        FilterStats(BroadcastStats broadcastStats, Pair<String, ComponentName> target) {
+            mBroadcastStats = broadcastStats;
+            mTarget = target;
+        }
+    }
+    
+    private static final class BroadcastStats {
+        final String mPackageName;
+
+        long aggregateTime;
+        int count;
+        int numWakeup;
+        long startTime;
+        int nesting;
+        final HashMap<Pair<String, ComponentName>, FilterStats> filterStats
+                = new HashMap<Pair<String, ComponentName>, FilterStats>();
+
+        BroadcastStats(String packageName) {
+            mPackageName = packageName;
+        }
     }
     
     private final HashMap<String, BroadcastStats> mBroadcastStats
@@ -496,24 +543,104 @@
                     dumpAlarmList(pw, mElapsedRealtimeAlarms, "  ", "ELAPSED", now);
                 }
             }
-            
-            pw.println(" ");
+
+            pw.println();
             pw.print("  Broadcast ref count: "); pw.println(mBroadcastRefCount);
-            
-            pw.println(" ");
-            pw.println("  Alarm Stats:");
+            pw.println();
+
+            if (mLog.dump(pw, "  Recent problems", "    ")) {
+                pw.println();
+            }
+
+            final FilterStats[] topFilters = new FilterStats[10];
+            final Comparator<FilterStats> comparator = new Comparator<FilterStats>() {
+                @Override
+                public int compare(FilterStats lhs, FilterStats rhs) {
+                    if (lhs.aggregateTime < rhs.aggregateTime) {
+                        return 1;
+                    } else if (lhs.aggregateTime > rhs.aggregateTime) {
+                        return -1;
+                    }
+                    return 0;
+                }
+            };
+            int len = 0;
             for (Map.Entry<String, BroadcastStats> be : mBroadcastStats.entrySet()) {
                 BroadcastStats bs = be.getValue();
-                pw.print("  "); pw.println(be.getKey());
-                pw.print("    "); pw.print(bs.aggregateTime);
-                        pw.print("ms running, "); pw.print(bs.numWakeup);
-                        pw.println(" wakeups");
-                for (Map.Entry<Intent.FilterComparison, FilterStats> fe
+                for (Map.Entry<Pair<String, ComponentName>, FilterStats> fe
                         : bs.filterStats.entrySet()) {
-                    pw.print("    "); pw.print(fe.getValue().count);
-                            pw.print(" alarms: ");
-                            pw.println(fe.getKey().getIntent().toShortString(
-                                    false, true, false, true));
+                    FilterStats fs = fe.getValue();
+                    int pos = len > 0
+                            ? Arrays.binarySearch(topFilters, 0, len, fs, comparator) : 0;
+                    if (pos < 0) {
+                        pos = -pos - 1;
+                    }
+                    if (pos < topFilters.length) {
+                        int copylen = topFilters.length - pos - 1;
+                        if (copylen > 0) {
+                            System.arraycopy(topFilters, pos, topFilters, pos+1, copylen);
+                        }
+                        topFilters[pos] = fs;
+                        if (len < topFilters.length) {
+                            len++;
+                        }
+                    }
+                }
+            }
+            if (len > 0) {
+                pw.println("  Top Alarms:");
+                for (int i=0; i<len; i++) {
+                    FilterStats fs = topFilters[i];
+                    pw.print("    ");
+                    if (fs.nesting > 0) pw.print("*ACTIVE* ");
+                    TimeUtils.formatDuration(fs.aggregateTime, pw);
+                    pw.print(" running, "); pw.print(fs.numWakeup);
+                    pw.print(" wakeups, "); pw.print(fs.count);
+                    pw.print(" alarms: "); pw.print(fs.mBroadcastStats.mPackageName);
+                    pw.println();
+                    pw.print("      ");
+                    if (fs.mTarget.first != null) {
+                        pw.print(" act="); pw.print(fs.mTarget.first);
+                    }
+                    if (fs.mTarget.second != null) {
+                        pw.print(" cmp="); pw.print(fs.mTarget.second.toShortString());
+                    }
+                    pw.println();
+                }
+            }
+
+            pw.println(" ");
+            pw.println("  Alarm Stats:");
+            final ArrayList<FilterStats> tmpFilters = new ArrayList<FilterStats>();
+            for (Map.Entry<String, BroadcastStats> be : mBroadcastStats.entrySet()) {
+                BroadcastStats bs = be.getValue();
+                pw.print("  ");
+                if (bs.nesting > 0) pw.print("*ACTIVE* ");
+                pw.print(be.getKey());
+                pw.print(" "); TimeUtils.formatDuration(bs.aggregateTime, pw);
+                        pw.print(" running, "); pw.print(bs.numWakeup);
+                        pw.println(" wakeups:");
+                tmpFilters.clear();
+                for (Map.Entry<Pair<String, ComponentName>, FilterStats> fe
+                        : bs.filterStats.entrySet()) {
+                    tmpFilters.add(fe.getValue());
+                }
+                Collections.sort(tmpFilters, comparator);
+                for (int i=0; i<tmpFilters.size(); i++) {
+                    FilterStats fs = tmpFilters.get(i);
+                    pw.print("    ");
+                            if (fs.nesting > 0) pw.print("*ACTIVE* ");
+                            TimeUtils.formatDuration(fs.aggregateTime, pw);
+                            pw.print(" "); pw.print(fs.numWakeup);
+                            pw.print(" wakes " ); pw.print(fs.count);
+                            pw.print(" alarms:");
+                            if (fs.mTarget.first != null) {
+                                pw.print(" act="); pw.print(fs.mTarget.first);
+                            }
+                            if (fs.mTarget.second != null) {
+                                pw.print(" cmp="); pw.print(fs.mTarget.second.toShortString());
+                            }
+                            pw.println();
                 }
             }
         }
@@ -708,18 +835,31 @@
                                 setWakelockWorkSource(alarm.operation);
                                 mWakeLock.acquire();
                             }
-                            mInFlight.add(alarm.operation);
+                            final InFlight inflight = new InFlight(AlarmManagerService.this,
+                                    alarm.operation);
+                            mInFlight.add(inflight);
                             mBroadcastRefCount++;
-                            
-                            BroadcastStats bs = getStatsLocked(alarm.operation);
+
+                            final BroadcastStats bs = inflight.mBroadcastStats;
+                            bs.count++;
                             if (bs.nesting == 0) {
+                                bs.nesting = 1;
                                 bs.startTime = nowELAPSED;
                             } else {
                                 bs.nesting++;
                             }
+                            final FilterStats fs = inflight.mFilterStats;
+                            fs.count++;
+                            if (fs.nesting == 0) {
+                                fs.nesting = 1;
+                                fs.startTime = nowELAPSED;
+                            } else {
+                                fs.nesting++;
+                            }
                             if (alarm.type == AlarmManager.ELAPSED_REALTIME_WAKEUP
                                     || alarm.type == AlarmManager.RTC_WAKEUP) {
                                 bs.numWakeup++;
+                                fs.numWakeup++;
                                 ActivityManagerNative.noteWakeupAlarm(
                                         alarm.operation);
                             }
@@ -908,44 +1048,58 @@
         String pkg = pi.getTargetPackage();
         BroadcastStats bs = mBroadcastStats.get(pkg);
         if (bs == null) {
-            bs = new BroadcastStats();
+            bs = new BroadcastStats(pkg);
             mBroadcastStats.put(pkg, bs);
         }
         return bs;
     }
-    
+
     class ResultReceiver implements PendingIntent.OnFinished {
         public void onSendFinished(PendingIntent pi, Intent intent, int resultCode,
                 String resultData, Bundle resultExtras) {
             synchronized (mLock) {
-                BroadcastStats bs = getStatsLocked(pi);
-                if (bs != null) {
+                InFlight inflight = null;
+                for (int i=0; i<mInFlight.size(); i++) {
+                    if (mInFlight.get(i).mPendingIntent == pi) {
+                        inflight = mInFlight.remove(i);
+                        break;
+                    }
+                }
+                if (inflight != null) {
+                    final long nowELAPSED = SystemClock.elapsedRealtime();
+                    BroadcastStats bs = inflight.mBroadcastStats;
                     bs.nesting--;
                     if (bs.nesting <= 0) {
                         bs.nesting = 0;
-                        bs.aggregateTime += SystemClock.elapsedRealtime()
-                                - bs.startTime;
-                        Intent.FilterComparison fc = new Intent.FilterComparison(intent);
-                        FilterStats fs = bs.filterStats.get(fc);
-                        if (fs == null) {
-                            fs = new FilterStats();
-                            bs.filterStats.put(fc, fs);
-                        }
-                        fs.count++;
+                        bs.aggregateTime += nowELAPSED - bs.startTime;
                     }
+                    FilterStats fs = inflight.mFilterStats;
+                    fs.nesting--;
+                    if (fs.nesting <= 0) {
+                        fs.nesting = 0;
+                        fs.aggregateTime += nowELAPSED - fs.startTime;
+                    }
+                } else {
+                    mLog.w("No in-flight alarm for " + pi + " " + intent);
                 }
-                mInFlight.removeFirst();
                 mBroadcastRefCount--;
                 if (mBroadcastRefCount == 0) {
                     mWakeLock.release();
+                    if (mInFlight.size() > 0) {
+                        mLog.w("Finished all broadcasts with " + mInFlight.size()
+                                + " remaining inflights");
+                        for (int i=0; i<mInFlight.size(); i++) {
+                            mLog.w("  Remaining #" + i + ": " + mInFlight.get(i));
+                        }
+                        mInFlight.clear();
+                    }
                 } else {
                     // the next of our alarms is now in flight.  reattribute the wakelock.
-                    final PendingIntent nowInFlight = mInFlight.peekFirst();
-                    if (nowInFlight != null) {
-                        setWakelockWorkSource(nowInFlight);
+                    if (mInFlight.size() > 0) {
+                        setWakelockWorkSource(mInFlight.get(0).mPendingIntent);
                     } else {
                         // should never happen
-                        Slog.e(TAG, "Alarm wakelock still held but sent queue empty");
+                        mLog.w("Alarm wakelock still held but sent queue empty");
                         mWakeLock.setWorkSource(null);
                     }
                 }
diff --git a/services/java/com/android/server/AppWidgetService.java b/services/java/com/android/server/AppWidgetService.java
index 06d37dc..06aeb29 100644
--- a/services/java/com/android/server/AppWidgetService.java
+++ b/services/java/com/android/server/AppWidgetService.java
@@ -26,6 +26,8 @@
 import android.content.pm.PackageManager;
 import android.os.Binder;
 import android.os.Bundle;
+import android.os.Handler;
+import android.os.HandlerThread;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.UserHandle;
@@ -54,13 +56,19 @@
     Locale mLocale;
     PackageManager mPackageManager;
     boolean mSafeMode;
+    private final Handler mSaveStateHandler;
 
     private final SparseArray<AppWidgetServiceImpl> mAppWidgetServices;
 
     AppWidgetService(Context context) {
         mContext = context;
+
+        HandlerThread handlerThread = new HandlerThread("AppWidgetService -- Save state");
+        handlerThread.start();
+        mSaveStateHandler = new Handler(handlerThread.getLooper());
+
         mAppWidgetServices = new SparseArray<AppWidgetServiceImpl>(5);
-        AppWidgetServiceImpl primary = new AppWidgetServiceImpl(context, 0);
+        AppWidgetServiceImpl primary = new AppWidgetServiceImpl(context, 0, mSaveStateHandler);
         mAppWidgetServices.append(0, primary);
     }
 
@@ -138,6 +146,11 @@
         return getImplForUser(getCallingOrCurrentUserId()).allocateAppWidgetId(
                 packageName, hostId);
     }
+
+    @Override
+    public int[] getAppWidgetIdsForHost(int hostId) throws RemoteException {
+        return getImplForUser(getCallingOrCurrentUserId()).getAppWidgetIdsForHost(hostId);
+    }
     
     @Override
     public void deleteAppWidgetId(int appWidgetId) throws RemoteException {
@@ -183,9 +196,14 @@
     }
 
     @Override
-    public void bindRemoteViewsService(int appWidgetId, Intent intent, IBinder connection)
-            throws RemoteException {
-        getImplForUser(getCallingOrCurrentUserId()).bindRemoteViewsService(
+    public void bindRemoteViewsService(int appWidgetId, Intent intent, IBinder connection,
+            int userId) throws RemoteException {
+        if (Binder.getCallingPid() != android.os.Process.myPid()
+                && userId != UserHandle.getCallingUserId()) {
+            throw new SecurityException("Call from non-system process. Calling uid = "
+                    + Binder.getCallingUid());
+        }
+        getImplForUser(userId).bindRemoteViewsService(
                 appWidgetId, intent, connection);
     }
 
@@ -196,6 +214,17 @@
                 packageName, hostId, updatedViews);
     }
 
+    @Override
+    public int[] startListeningAsUser(IAppWidgetHost host, String packageName, int hostId,
+            List<RemoteViews> updatedViews, int userId) throws RemoteException {
+        if (Binder.getCallingPid() != android.os.Process.myPid()
+                && userId != UserHandle.getCallingUserId()) {
+            throw new SecurityException("Call from non-system process. Calling uid = "
+                    + Binder.getCallingUid());
+        }
+        return getImplForUser(userId).startListening(host, packageName, hostId, updatedViews);
+    }
+
     public void onUserRemoved(int userId) {
         if (userId < 1) return;
         synchronized (mAppWidgetServices) {
@@ -229,7 +258,7 @@
             if (service == null) {
                 Slog.i(TAG, "Unable to find AppWidgetServiceImpl for user " + userId + ", adding");
                 // TODO: Verify that it's a valid user
-                service = new AppWidgetServiceImpl(mContext, userId);
+                service = new AppWidgetServiceImpl(mContext, userId, mSaveStateHandler);
                 service.systemReady(mSafeMode);
                 // Assume that BOOT_COMPLETED was received, as this is a non-primary user.
                 mAppWidgetServices.append(userId, service);
@@ -268,8 +297,9 @@
     }
 
     @Override
-    public List<AppWidgetProviderInfo> getInstalledProviders() throws RemoteException {
-        return getImplForUser(getCallingOrCurrentUserId()).getInstalledProviders();
+    public List<AppWidgetProviderInfo> getInstalledProviders(int categoryFilter)
+            throws RemoteException {
+        return getImplForUser(getCallingOrCurrentUserId()).getInstalledProviders(categoryFilter);
     }
 
     @Override
@@ -292,8 +322,24 @@
     }
 
     @Override
-    public void unbindRemoteViewsService(int appWidgetId, Intent intent) throws RemoteException {
-        getImplForUser(getCallingOrCurrentUserId()).unbindRemoteViewsService(
+    public void stopListeningAsUser(int hostId, int userId) throws RemoteException {
+        if (Binder.getCallingPid() != android.os.Process.myPid()
+                && userId != UserHandle.getCallingUserId()) {
+            throw new SecurityException("Call from non-system process. Calling uid = "
+                    + Binder.getCallingUid());
+        }
+        getImplForUser(userId).stopListening(hostId);
+    }
+
+    @Override
+    public void unbindRemoteViewsService(int appWidgetId, Intent intent, int userId)
+            throws RemoteException {
+        if (Binder.getCallingPid() != android.os.Process.myPid()
+                && userId != UserHandle.getCallingUserId()) {
+            throw new SecurityException("Call from non-system process. Calling uid = "
+                    + Binder.getCallingUid());
+        }
+        getImplForUser(userId).unbindRemoteViewsService(
                 appWidgetId, intent);
     }
 
diff --git a/services/java/com/android/server/AppWidgetServiceImpl.java b/services/java/com/android/server/AppWidgetServiceImpl.java
index daa82f2..e1e9eaf 100644
--- a/services/java/com/android/server/AppWidgetServiceImpl.java
+++ b/services/java/com/android/server/AppWidgetServiceImpl.java
@@ -41,7 +41,10 @@
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.Environment;
+import android.os.Handler;
+import android.os.HandlerThread;
 import android.os.IBinder;
+import android.os.Looper;
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.SystemClock;
@@ -113,6 +116,15 @@
         boolean zombie; // if we're in safe mode, don't prune this just because nobody references it
 
         int tag; // for use while saving state (the index)
+
+        boolean uidMatches(int callingUid) {
+            if (UserHandle.getAppId(callingUid) == Process.myUid()) {
+                // For a host that's in the system process, ignore the user id
+                return UserHandle.isSameApp(this.uid, callingUid);
+            } else {
+                return this.uid == callingUid;
+            }
+        }
     }
 
     static class AppWidgetId {
@@ -180,15 +192,18 @@
     boolean mStateLoaded;
     int mMaxWidgetBitmapMemory;
 
+    private final Handler mSaveStateHandler;
+
     // These are for debugging only -- widgets are going missing in some rare instances
     ArrayList<Provider> mDeletedProviders = new ArrayList<Provider>();
     ArrayList<Host> mDeletedHosts = new ArrayList<Host>();
 
-    AppWidgetServiceImpl(Context context, int userId) {
+    AppWidgetServiceImpl(Context context, int userId, Handler saveStateHandler) {
         mContext = context;
         mPm = AppGlobals.getPackageManager();
         mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
         mUserId = userId;
+        mSaveStateHandler = saveStateHandler;
         computeMaximumWidgetBitmapMemory();
     }
 
@@ -236,7 +251,7 @@
                         updateProvidersForPackageLocked(cn.getPackageName(), removedProviders);
                     }
                 }
-                saveStateLocked();
+                saveStateAsync();
             }
         }
     }
@@ -286,7 +301,7 @@
                         providersModified |= addProvidersForPackageLocked(pkgName);
                     }
                 }
-                saveStateLocked();
+                saveStateAsync();
             }
         } else {
             Bundle extras = intent.getExtras();
@@ -297,7 +312,7 @@
                     ensureStateLoadedLocked();
                     for (String pkgName : pkgList) {
                         providersModified |= removeProvidersForPackageLocked(pkgName);
-                        saveStateLocked();
+                        saveStateAsync();
                     }
                 }
             }
@@ -330,6 +345,7 @@
                 pw.print(info.autoAdvanceViewId);
                 pw.print(" initialLayout=#");
                 pw.print(Integer.toHexString(info.initialLayout));
+                pw.print(" uid="); pw.print(p.uid);
                 pw.print(" zombie="); pw.println(p.zombie);
     }
 
@@ -410,7 +426,7 @@
 
     private void ensureStateLoadedLocked() {
         if (!mStateLoaded) {
-            loadAppWidgetList();
+            loadAppWidgetListLocked();
             loadStateLocked();
             mStateLoaded = true;
         }
@@ -431,7 +447,7 @@
             host.instances.add(id);
             mAppWidgetIds.add(id);
 
-            saveStateLocked();
+            saveStateAsync();
             if (DBG) log("Allocating AppWidgetId for " + packageName + " host=" + hostId
                     + " id=" + appWidgetId);
             return appWidgetId;
@@ -444,7 +460,7 @@
             AppWidgetId id = lookupAppWidgetIdLocked(appWidgetId);
             if (id != null) {
                 deleteAppWidgetLocked(id);
-                saveStateLocked();
+                saveStateAsync();
             }
         }
     }
@@ -456,7 +472,7 @@
             Host host = lookupHostLocked(callingUid, hostId);
             if (host != null) {
                 deleteHostLocked(host);
-                saveStateLocked();
+                saveStateAsync();
             }
         }
     }
@@ -469,13 +485,13 @@
             boolean changed = false;
             for (int i = N - 1; i >= 0; i--) {
                 Host host = mHosts.get(i);
-                if (host.uid == callingUid) {
+                if (host.uidMatches(callingUid)) {
                     deleteHostLocked(host);
                     changed = true;
                 }
             }
             if (changed) {
-                saveStateLocked();
+                saveStateAsync();
             }
         }
     }
@@ -591,7 +607,7 @@
 
                 // schedule the future updates
                 registerForBroadcastsLocked(p, getAppWidgetIds(p));
-                saveStateLocked();
+                saveStateAsync();
             }
         } finally {
             Binder.restoreCallingIdentity(ident);
@@ -655,8 +671,8 @@
             } else {
                 mPackagesWithBindWidgetPermission.remove(packageName);
             }
+            saveStateAsync();
         }
-        saveStateLocked();
     }
 
     // Binds to a specific RemoteViewsService
@@ -693,6 +709,10 @@
             }
 
             int userId = UserHandle.getUserId(id.provider.uid);
+            if (userId != mUserId) {
+                Slog.w(TAG, "AppWidgetServiceImpl of user " + mUserId
+                        + " binding to provider on user " + userId);
+            }
             // Bind to the RemoteViewsService (which will trigger a callback to the
             // RemoteViewsAdapter.onServiceConnected())
             final long token = Binder.clearCallingIdentity();
@@ -733,8 +753,6 @@
                 conn.disconnect();
                 mContext.unbindService(conn);
                 mBoundRemoteViewsServices.remove(key);
-            } else {
-                Log.e("AppWidgetService", "Error (unbindRemoteViewsService): Connection not bound");
             }
         }
     }
@@ -848,14 +866,14 @@
         }
     }
 
-    public List<AppWidgetProviderInfo> getInstalledProviders() {
+    public List<AppWidgetProviderInfo> getInstalledProviders(int categoryFilter) {
         synchronized (mAppWidgetIds) {
             ensureStateLoadedLocked();
             final int N = mInstalledProviders.size();
             ArrayList<AppWidgetProviderInfo> result = new ArrayList<AppWidgetProviderInfo>(N);
             for (int i = 0; i < N; i++) {
                 Provider p = mInstalledProviders.get(i);
-                if (!p.zombie) {
+                if (!p.zombie && (p.info.widgetCategory & categoryFilter) != 0) {
                     result.add(cloneIfLocalBinder(p.info));
                 }
             }
@@ -893,6 +911,20 @@
         }
     }
 
+    private void saveStateAsync() {
+        mSaveStateHandler.post(mSaveStateRunnable);
+    }
+
+    private final Runnable mSaveStateRunnable = new Runnable() {
+        @Override
+        public void run() {
+            synchronized (mAppWidgetIds) {
+                ensureStateLoadedLocked();
+                saveStateLocked();
+            }
+        }
+    };
+
     public void updateAppWidgetOptions(int appWidgetId, Bundle options) {
         synchronized (mAppWidgetIds) {
             options = cloneIfLocalBinder(options);
@@ -913,7 +945,7 @@
             intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, id.appWidgetId);
             intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS, id.options);
             mContext.sendBroadcastAsUser(intent, new UserHandle(mUserId));
-            saveStateLocked();
+            saveStateAsync();
         }
     }
 
@@ -942,7 +974,9 @@
             ensureStateLoadedLocked();
             for (int i = 0; i < N; i++) {
                 AppWidgetId id = lookupAppWidgetIdLocked(appWidgetIds[i]);
-                if (id.views != null) {
+                if (id == null) {
+                    Slog.w(TAG, "widget id " + appWidgetIds[i] + " not found!");
+                } else if (id.views != null) {
                     // Only trigger a partial update for a widget if it has received a full update
                     updateAppWidgetInstanceLocked(id, views, true);
                 }
@@ -1142,7 +1176,7 @@
     }
 
     boolean canAccessAppWidgetId(AppWidgetId id, int callingUid) {
-        if (id.host.uid == callingUid) {
+        if (id.host.uidMatches(callingUid)) {
             // Apps hosting the AppWidget have access to it.
             return true;
         }
@@ -1185,7 +1219,7 @@
         final int N = mHosts.size();
         for (int i = 0; i < N; i++) {
             Host h = mHosts.get(i);
-            if (h.uid == uid && h.hostId == hostId) {
+            if (h.uidMatches(uid) && h.hostId == hostId) {
                 return h;
             }
         }
@@ -1214,7 +1248,7 @@
         }
     }
 
-    void loadAppWidgetList() {
+    void loadAppWidgetListLocked() {
         Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
         try {
             List<ResolveInfo> broadcastReceivers = mPm.queryIntentReceivers(intent,
@@ -1334,6 +1368,28 @@
         }
     }
 
+    static int[] getAppWidgetIds(Host h) {
+        int instancesSize = h.instances.size();
+        int appWidgetIds[] = new int[instancesSize];
+        for (int i = 0; i < instancesSize; i++) {
+            appWidgetIds[i] = h.instances.get(i).appWidgetId;
+        }
+        return appWidgetIds;
+    }
+
+    public int[] getAppWidgetIdsForHost(int hostId) {
+        synchronized (mAppWidgetIds) {
+            ensureStateLoadedLocked();
+            int callingUid = Binder.getCallingUid();
+            Host host = lookupHostLocked(callingUid, hostId);
+            if (host != null) {
+                return getAppWidgetIds(host);
+            } else {
+                return new int[0];
+            }
+        }
+    }
+
     private Provider parseProviderInfoXml(ComponentName component, ResolveInfo ri) {
         Provider p = null;
 
diff --git a/services/java/com/android/server/AttributeCache.java b/services/java/com/android/server/AttributeCache.java
index 81378dc..81613c6 100644
--- a/services/java/com/android/server/AttributeCache.java
+++ b/services/java/com/android/server/AttributeCache.java
@@ -23,6 +23,7 @@
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
+import android.os.UserHandle;
 import android.util.SparseArray;
 
 import java.util.HashMap;
@@ -34,52 +35,54 @@
  */
 public final class AttributeCache {
     private static AttributeCache sInstance = null;
-    
+
     private final Context mContext;
-    private final WeakHashMap<String, Package> mPackages =
-            new WeakHashMap<String, Package>();
+    private final SparseArray<WeakHashMap<String, Package>> mPackages =
+            new SparseArray<WeakHashMap<String, Package>>();
     private final Configuration mConfiguration = new Configuration();
-    
+
     public final static class Package {
         public final Context context;
         private final SparseArray<HashMap<int[], Entry>> mMap
                 = new SparseArray<HashMap<int[], Entry>>();
-        
+
         public Package(Context c) {
             context = c;
         }
     }
-    
+
     public final static class Entry {
         public final Context context;
         public final TypedArray array;
-        
+
         public Entry(Context c, TypedArray ta) {
             context = c;
             array = ta;
         }
     }
-    
+
     public static void init(Context context) {
         if (sInstance == null) {
             sInstance = new AttributeCache(context);
         }
     }
-    
+
     public static AttributeCache instance() {
         return sInstance;
     }
-    
+
     public AttributeCache(Context context) {
         mContext = context;
     }
-    
+
     public void removePackage(String packageName) {
         synchronized (this) {
-            mPackages.remove(packageName);
+            for (int i=0; i<mPackages.size(); i++) {
+                mPackages.valueAt(i).remove(packageName);
+            }
         }
     }
-    
+
     public void updateConfiguration(Configuration config) {
         synchronized (this) {
             int changes = mConfiguration.updateFrom(config);
@@ -93,10 +96,21 @@
             }
         }
     }
-    
-    public Entry get(String packageName, int resId, int[] styleable) {
+
+    public void removeUser(int userId) {
         synchronized (this) {
-            Package pkg = mPackages.get(packageName);
+            mPackages.remove(userId);
+        }
+    }
+
+    public Entry get(int userId, String packageName, int resId, int[] styleable) {
+        synchronized (this) {
+            WeakHashMap<String, Package> packages = mPackages.get(userId);
+            if (packages == null) {
+                packages = new WeakHashMap<String, Package>();
+                mPackages.put(userId, packages);
+            }
+            Package pkg = packages.get(packageName);
             HashMap<int[], Entry> map = null;
             Entry ent = null;
             if (pkg != null) {
@@ -110,7 +124,8 @@
             } else {
                 Context context;
                 try {
-                    context = mContext.createPackageContext(packageName, 0);
+                    context = mContext.createPackageContextAsUser(packageName, 0,
+                            new UserHandle(userId));
                     if (context == null) {
                         return null;
                     }
@@ -118,7 +133,7 @@
                     return null;
                 }
                 pkg = new Package(context);
-                mPackages.put(packageName, pkg);
+                packages.put(packageName, pkg);
             }
             
             if (map == null) {
diff --git a/services/java/com/android/server/BluetoothManagerService.java b/services/java/com/android/server/BluetoothManagerService.java
index 69ccbc7..5a2088c 100755
--- a/services/java/com/android/server/BluetoothManagerService.java
+++ b/services/java/com/android/server/BluetoothManagerService.java
@@ -43,8 +43,6 @@
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.util.Log;
-import java.util.ArrayList;
-import java.util.List;
 class BluetoothManagerService extends IBluetoothManager.Stub {
     private static final String TAG = "BluetoothManagerService";
     private static final boolean DBG = true;
@@ -79,6 +77,15 @@
     private static final int MESSAGE_SAVE_NAME_AND_ADDRESS=201;
     private static final int MESSAGE_USER_SWITCHED = 300;
     private static final int MAX_SAVE_RETRIES=3;
+    // Bluetooth persisted setting is off
+    private static final int BLUETOOTH_OFF=0;
+    // Bluetooth persisted setting is on
+    // and Airplane mode won't affect Bluetooth state at start up
+    private static final int BLUETOOTH_ON_BLUETOOTH=1;
+    // Bluetooth persisted setting is on
+    // but Airplane mode will affect Bluetooth state at start up
+    // and Airplane mode will have higher priority.
+    private static final int BLUETOOTH_ON_AIRPLANE=2;
 
     private final Context mContext;
 
@@ -92,7 +99,15 @@
     private IBluetooth mBluetooth;
     private boolean mBinding;
     private boolean mUnbinding;
+    // used inside handler thread
     private boolean mQuietEnable = false;
+    // configuarion from external IBinder call which is used to
+    // synchronize with broadcast receiver.
+    private boolean mQuietEnableExternal;
+    // configuarion from external IBinder call which is used to
+    // synchronize with broadcast receiver.
+    private boolean mEnableExternal;
+    // used inside handler thread
     private boolean mEnable;
     private int mState;
     private HandlerThread mThread;
@@ -130,18 +145,39 @@
                     storeNameAndAddress(newName, null);
                 }
             } else if (Intent.ACTION_AIRPLANE_MODE_CHANGED.equals(action)) {
-                if (isAirplaneModeOn()) {
-                    // disable without persisting the setting
-                    mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_DISABLE,
-                           0, 0));
-                } else if (isBluetoothPersistedStateOn()) {
-                    // enable without persisting the setting
-                    mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_ENABLE,
-                           0, 0));
+                synchronized(mReceiver) {
+                    if (isBluetoothPersistedStateOn()) {
+                        if (isAirplaneModeOn()) {
+                            persistBluetoothSetting(BLUETOOTH_ON_AIRPLANE);
+                        } else {
+                            persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH);
+                        }
+                    }
+                    if (isAirplaneModeOn()) {
+                        // disable without persisting the setting
+                        sendDisableMsg();
+                    } else if (mEnableExternal) {
+                        // enable without persisting the setting
+                        sendEnableMsg(mQuietEnableExternal);
+                    }
                 }
             } else if (Intent.ACTION_USER_SWITCHED.equals(action)) {
                 mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_USER_SWITCHED,
                        intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0), 0));
+            } else if (Intent.ACTION_BOOT_COMPLETED.equals(action)) {
+                synchronized(mReceiver) {
+                    if (mEnableExternal && isBluetoothPersistedStateOnBluetooth()) {
+                        //Enable
+                        if (DBG) Log.d(TAG, "Auto-enabling Bluetooth.");
+                        sendEnableMsg(mQuietEnableExternal);
+                    }
+                }
+
+                if (!isNameAndAddressSet()) {
+                    //Sync the Bluetooth name and address from the Bluetooth Adapter
+                    if (DBG) Log.d(TAG,"Retrieving Bluetooth Adapter name and address...");
+                    getNameAndAddress();
+                }
             }
         }
     };
@@ -157,30 +193,21 @@
         mUnbinding = false;
         mEnable = false;
         mState = BluetoothAdapter.STATE_OFF;
+        mQuietEnableExternal = false;
+        mEnableExternal = false;
         mAddress = null;
         mName = null;
         mContentResolver = context.getContentResolver();
         mCallbacks = new RemoteCallbackList<IBluetoothManagerCallback>();
         mStateChangeCallbacks = new RemoteCallbackList<IBluetoothStateChangeCallback>();
-        IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
+        IntentFilter filter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
         filter.addAction(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED);
         filter.addAction(Intent.ACTION_USER_SWITCHED);
         registerForAirplaneMode(filter);
         mContext.registerReceiver(mReceiver, filter);
-        boolean airplaneModeOn = isAirplaneModeOn();
-        boolean bluetoothOn = isBluetoothPersistedStateOn();
         loadStoredNameAndAddress();
-        if (DBG) Log.d(TAG, "airplaneModeOn: " + airplaneModeOn + " bluetoothOn: " + bluetoothOn);
-        if (bluetoothOn) {
-            //Enable
-            if (DBG) Log.d(TAG, "Auto-enabling Bluetooth.");
-            enableHelper();
-        }
-
-        if (!isNameAndAddressSet()) {
-            //Sync the Bluetooth name and address from the Bluetooth Adapter
-            if (DBG) Log.d(TAG,"Retrieving Bluetooth Adapter name and address...");
-            getNameAndAddress();
+        if (isBluetoothPersistedStateOn()) {
+            mEnableExternal = true;
         }
     }
 
@@ -197,17 +224,25 @@
      */
     private final boolean isBluetoothPersistedStateOn() {
         return Settings.Global.getInt(mContentResolver,
-                Settings.Global.BLUETOOTH_ON, 0) ==1;
+                Settings.Global.BLUETOOTH_ON, 0) != BLUETOOTH_OFF;
+    }
+
+    /**
+     *  Returns true if the Bluetooth saved state is BLUETOOTH_ON_BLUETOOTH
+     */
+    private final boolean isBluetoothPersistedStateOnBluetooth() {
+        return Settings.Global.getInt(mContentResolver,
+                Settings.Global.BLUETOOTH_ON, 0) == BLUETOOTH_ON_BLUETOOTH;
     }
 
     /**
      *  Save the Bluetooth on/off state
      *
      */
-    private void persistBluetoothSetting(boolean setOn) {
+    private void persistBluetoothSetting(int value) {
         Settings.Global.putInt(mContext.getContentResolver(),
                                Settings.Global.BLUETOOTH_ON,
-                               setOn ? 1 : 0);
+                               value);
     }
 
     /**
@@ -297,8 +332,9 @@
     }
 
     public boolean isEnabled() {
-        if (!checkIfCallerIsForegroundUser()) {
-            Log.w(TAG,"isEnabled(): not allowed for non-active user");
+        if ((Binder.getCallingUid() != Process.SYSTEM_UID) &&
+            (!checkIfCallerIsForegroundUser())) {
+            Log.w(TAG,"isEnabled(): not allowed for non-active and non system user");
             return false;
         }
 
@@ -325,40 +361,57 @@
         mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
                                                 "Need BLUETOOTH ADMIN permission");
 
-        if (!checkIfCallerIsForegroundUser()) {
-            Log.w(TAG,"enableNoAutoConnect(): not allowed for non-active user");
-            return false;
-        }
-
         if (DBG) {
             Log.d(TAG,"enableNoAutoConnect():  mBluetooth =" + mBluetooth +
                     " mBinding = " + mBinding);
         }
-        if (Binder.getCallingUid() != Process.NFC_UID) {
+        int callingAppId = UserHandle.getAppId(Binder.getCallingUid());
+
+        if (callingAppId != Process.NFC_UID) {
             throw new SecurityException("no permission to enable Bluetooth quietly");
         }
-        Message msg = mHandler.obtainMessage(MESSAGE_ENABLE);
-        msg.arg1=0; //No persist
-        msg.arg2=1; //Quiet mode
-        mHandler.sendMessage(msg);
+
+        synchronized(mReceiver) {
+            mQuietEnableExternal = true;
+            mEnableExternal = true;
+            sendEnableMsg(true);
+        }
         return true;
 
     }
     public boolean enable() {
-        if (!checkIfCallerIsForegroundUser()) {
-            Log.w(TAG,"enable(): not allowed for non-active user");
+        if ((Binder.getCallingUid() != Process.SYSTEM_UID) &&
+            (!checkIfCallerIsForegroundUser())) {
+            Log.w(TAG,"enable(): not allowed for non-active and non system user");
             return false;
         }
 
-        return enableHelper();
+        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
+                                                "Need BLUETOOTH ADMIN permission");
+        if (DBG) {
+            Log.d(TAG,"enable():  mBluetooth =" + mBluetooth +
+                    " mBinding = " + mBinding);
+        }
+
+        synchronized(mReceiver) {
+            mQuietEnableExternal = false;
+            mEnableExternal = true;
+            // waive WRITE_SECURE_SETTINGS permission check
+            long callingIdentity = Binder.clearCallingIdentity();
+            persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH);
+            Binder.restoreCallingIdentity(callingIdentity);
+            sendEnableMsg(false);
+        }
+        return true;
     }
 
     public boolean disable(boolean persist) {
         mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
                                                 "Need BLUETOOTH ADMIN permissicacheNameAndAddresson");
 
-        if (!checkIfCallerIsForegroundUser()) {
-            Log.w(TAG,"disable(): not allowed for non-active user");
+        if ((Binder.getCallingUid() != Process.SYSTEM_UID) &&
+            (!checkIfCallerIsForegroundUser())) {
+            Log.w(TAG,"disable(): not allowed for non-active and non system user");
             return false;
         }
 
@@ -367,9 +420,16 @@
                 " mBinding = " + mBinding);
         }
 
-        Message msg = mHandler.obtainMessage(MESSAGE_DISABLE);
-        msg.arg1=(persist?1:0);
-        mHandler.sendMessage(msg);
+        synchronized(mReceiver) {
+            if (persist) {
+                // waive WRITE_SECURE_SETTINGS permission check
+                long callingIdentity = Binder.clearCallingIdentity();
+                persistBluetoothSetting(BLUETOOTH_OFF);
+                Binder.restoreCallingIdentity(callingIdentity);
+            }
+            mEnableExternal = false;
+            sendDisableMsg();
+        }
         return true;
     }
 
@@ -453,12 +513,13 @@
         }
     }
     public String getAddress() {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
-                                                "Need BLUETOOTH ADMIN permission");
+        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
+                                                "Need BLUETOOTH permission");
 
-        if (!checkIfCallerIsForegroundUser()) {
-            Log.w(TAG,"getAddress(): not allowed for non-active user");
-            return mAddress;
+        if ((Binder.getCallingUid() != Process.SYSTEM_UID) &&
+            (!checkIfCallerIsForegroundUser())) {
+            Log.w(TAG,"getAddress(): not allowed for non-active and non system user");
+            return null;
         }
 
         synchronized(mConnection) {
@@ -477,12 +538,13 @@
     }
 
     public String getName() {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
-                                                "Need BLUETOOTH ADMIN permission");
+        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
+                                                "Need BLUETOOTH permission");
 
-        if (!checkIfCallerIsForegroundUser()) {
-            Log.w(TAG,"getName(): not allowed for non-active user");
-            return mName;
+        if ((Binder.getCallingUid() != Process.SYSTEM_UID) &&
+            (!checkIfCallerIsForegroundUser())) {
+            Log.w(TAG,"getName(): not allowed for non-active and non system user");
+            return null;
         }
 
         synchronized(mConnection) {
@@ -640,7 +702,7 @@
                     }
                     mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE);
                     mEnable = true;
-                    handleEnable(msg.arg1 == 1, msg.arg2 ==1);
+                    handleEnable(msg.arg1 == 1);
                     break;
 
                 case MESSAGE_DISABLE:
@@ -648,11 +710,11 @@
                     if (mEnable && mBluetooth != null) {
                         waitForOnOff(true, false);
                         mEnable = false;
-                        handleDisable(msg.arg1 == 1);
+                        handleDisable();
                         waitForOnOff(false, false);
                     } else {
                         mEnable = false;
-                        handleDisable(msg.arg1 == 1);
+                        handleDisable();
                     }
                     break;
 
@@ -731,7 +793,7 @@
 
                     if (!mEnable) {
                         waitForOnOff(true, false);
-                        handleDisable(false);
+                        handleDisable();
                         waitForOnOff(false, false);
                     }
                     break;
@@ -775,8 +837,18 @@
 
                         // Send BT state broadcast to update
                         // the BT icon correctly
-                        bluetoothStateChangeHandler(BluetoothAdapter.STATE_ON,
-                                                    BluetoothAdapter.STATE_TURNING_OFF);
+                        if ((mState == BluetoothAdapter.STATE_TURNING_ON) ||
+                            (mState == BluetoothAdapter.STATE_ON)) {
+                            bluetoothStateChangeHandler(BluetoothAdapter.STATE_ON,
+                                                        BluetoothAdapter.STATE_TURNING_OFF);
+                            mState = BluetoothAdapter.STATE_TURNING_OFF;
+                        }
+                        if (mState == BluetoothAdapter.STATE_TURNING_OFF) {
+                            bluetoothStateChangeHandler(BluetoothAdapter.STATE_TURNING_OFF,
+                                                        BluetoothAdapter.STATE_OFF);
+                        }
+
+                        mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE);
                         mState = BluetoothAdapter.STATE_OFF;
                     }
                     break;
@@ -789,7 +861,7 @@
                      it doesnt change when IBluetooth
                      service restarts */
                     mEnable = true;
-                    handleEnable(false, mQuietEnable);
+                    handleEnable(mQuietEnable);
                     break;
                 }
 
@@ -820,20 +892,33 @@
                                 }
                             }
                         }
-                        mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE);
+
+                        if (mState == BluetoothAdapter.STATE_TURNING_OFF) {
+                            // MESSAGE_USER_SWITCHED happened right after MESSAGE_ENABLE
+                            bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_OFF);
+                            mState = BluetoothAdapter.STATE_OFF;
+                        }
+                        if (mState == BluetoothAdapter.STATE_OFF) {
+                            bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_TURNING_ON);
+                            mState = BluetoothAdapter.STATE_TURNING_ON;
+                        }
 
                         waitForOnOff(true, false);
 
-                        bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_ON);
+                        if (mState == BluetoothAdapter.STATE_TURNING_ON) {
+                            bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_ON);
+                        }
 
                         // disable
-                        handleDisable(false);
+                        handleDisable();
+                        // Pbap service need receive STATE_TURNING_OFF intent to close
+                        bluetoothStateChangeHandler(BluetoothAdapter.STATE_ON,
+                                                    BluetoothAdapter.STATE_TURNING_OFF);
 
                         waitForOnOff(false, true);
 
-                        bluetoothStateChangeHandler(BluetoothAdapter.STATE_ON,
+                        bluetoothStateChangeHandler(BluetoothAdapter.STATE_TURNING_OFF,
                                                     BluetoothAdapter.STATE_OFF);
-                        mState = BluetoothAdapter.STATE_OFF;
                         sendBluetoothServiceDownCallback();
                         synchronized (mConnection) {
                             if (mBluetooth != null) {
@@ -844,8 +929,10 @@
                         }
                         SystemClock.sleep(100);
 
+                        mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE);
+                        mState = BluetoothAdapter.STATE_OFF;
                         // enable
-                        handleEnable(false, mQuietEnable);
+                        handleEnable(mQuietEnable);
 		    } else if (mBinding || mBluetooth != null) {
                         Message userMsg = mHandler.obtainMessage(MESSAGE_USER_SWITCHED);
                         userMsg.arg2 = 1 + msg.arg2;
@@ -862,11 +949,7 @@
         }
     }
 
-    private void handleEnable(boolean persist, boolean quietMode) {
-        if (persist) {
-            persistBluetoothSetting(true);
-        }
-
+    private void handleEnable(boolean quietMode) {
         mQuietEnable = quietMode;
 
         synchronized(mConnection) {
@@ -918,11 +1001,7 @@
         }
     }
 
-    private void handleDisable(boolean persist) {
-        if (persist) {
-            persistBluetoothSetting(false);
-        }
-
+    private void handleDisable() {
         synchronized(mConnection) {
             // don't need to disable if GetNameAddressOnly is set,
             // service will be unbinded after Name and Address are saved
@@ -943,11 +1022,14 @@
     private boolean checkIfCallerIsForegroundUser() {
         int foregroundUser;
         int callingUser = UserHandle.getCallingUserId();
+        int callingUid = Binder.getCallingUid();
         long callingIdentity = Binder.clearCallingIdentity();
+        int callingAppId = UserHandle.getAppId(callingUid);
         boolean valid = false;
         try {
             foregroundUser = ActivityManager.getCurrentUser();
-            valid = (callingUser == foregroundUser);
+            valid = (callingUser == foregroundUser) ||
+                    callingAppId == Process.NFC_UID;
             if (DBG) {
                 Log.d(TAG, "checkIfCallerIsForegroundUser: valid=" + valid
                     + " callingUser=" + callingUser
@@ -959,21 +1041,6 @@
         return valid;
     }
 
-    private boolean enableHelper() {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
-                                                "Need BLUETOOTH ADMIN permission");
-        if (DBG) {
-            Log.d(TAG,"enable():  mBluetooth =" + mBluetooth +
-                    " mBinding = " + mBinding);
-        }
-
-        Message msg = mHandler.obtainMessage(MESSAGE_ENABLE);
-        msg.arg1=1; //persist
-        msg.arg2=0; //No Quiet Mode
-        mHandler.sendMessage(msg);
-        return true;
-    }
-
     private void bluetoothStateChangeHandler(int prevState, int newState) {
         if (prevState != newState) {
             //Notify all proxy objects first of adapter state change
@@ -982,14 +1049,9 @@
                 sendBluetoothStateCallback(isUp);
 
                 //If Bluetooth is off, send service down event to proxy objects, and unbind
-                if (!isUp) {
-                    //Only unbind with mEnable flag not set
-                    //For race condition: disable and enable back-to-back
-                    //Avoid unbind right after enable due to callback from disable
-                    if ((!mEnable) && (mBluetooth != null)) {
-                        sendBluetoothServiceDownCallback();
-                        unbindAndFinish();
-                    }
+                if (!isUp && canUnbindBluetoothService()) {
+                    sendBluetoothServiceDownCallback();
+                    unbindAndFinish();
                 }
             }
 
@@ -1037,4 +1099,31 @@
         Log.e(TAG,"waitForOnOff time out");
         return false;
     }
+
+    private void sendDisableMsg() {
+        mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_DISABLE));
+    }
+
+    private void sendEnableMsg(boolean quietMode) {
+        mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_ENABLE,
+                             quietMode ? 1 : 0, 0));
+    }
+
+    private boolean canUnbindBluetoothService() {
+        synchronized(mConnection) {
+            //Only unbind with mEnable flag not set
+            //For race condition: disable and enable back-to-back
+            //Avoid unbind right after enable due to callback from disable
+            //Only unbind with Bluetooth at OFF state
+            //Only unbind without any MESSAGE_BLUETOOTH_STATE_CHANGE message
+            try {
+                if (mEnable || (mBluetooth == null)) return false;
+                if (mHandler.hasMessages(MESSAGE_BLUETOOTH_STATE_CHANGE)) return false;
+                return (mBluetooth.getState() == BluetoothAdapter.STATE_OFF);
+            } catch (RemoteException e) {
+                Log.e(TAG, "getState()", e);
+            }
+        }
+        return false;
+    }
 }
diff --git a/services/java/com/android/server/BootReceiver.java b/services/java/com/android/server/BootReceiver.java
index 7e1de5a..235c662 100644
--- a/services/java/com/android/server/BootReceiver.java
+++ b/services/java/com/android/server/BootReceiver.java
@@ -20,11 +20,14 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.SharedPreferences;
+import android.content.pm.IPackageManager;
 import android.os.Build;
 import android.os.DropBoxManager;
 import android.os.FileObserver;
 import android.os.FileUtils;
 import android.os.RecoverySystem;
+import android.os.RemoteException;
+import android.os.ServiceManager;
 import android.os.SystemProperties;
 import android.provider.Downloads;
 import android.util.Slog;
@@ -69,7 +72,15 @@
                     Slog.e(TAG, "Can't log boot events", e);
                 }
                 try {
-                    removeOldUpdatePackages(context);
+                    boolean onlyCore = false;
+                    try {
+                        onlyCore = IPackageManager.Stub.asInterface(ServiceManager.getService(
+                                "package")).isOnlyCoreApps();
+                    } catch (RemoteException e) {
+                    }
+                    if (!onlyCore) {
+                        removeOldUpdatePackages(context);
+                    }
                 } catch (Exception e) {
                     Slog.e(TAG, "Can't remove old update packages", e);
                 }
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index ad1dfb2..a7c4d73 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -2686,18 +2686,8 @@
                             state + "/" + info.getDetailedState());
                     }
 
-                    // Connectivity state changed:
-                    // [31-14] Reserved for future use
-                    // [13-10] Network subtype (for mobile network, as defined
-                    //         by TelephonyManager)
-                    // [9-4] Detailed state ordinal (as defined by
-                    //         NetworkInfo.DetailedState)
-                    // [3-0] Network type (as defined by ConnectivityManager)
-                    int eventLogParam = (info.getType() & 0xf) |
-                            ((info.getDetailedState().ordinal() & 0x3f) << 4) |
-                            (info.getSubtype() << 10);
-                    EventLog.writeEvent(EventLogTags.CONNECTIVITY_STATE_CHANGED,
-                            eventLogParam);
+                    EventLogTags.writeConnectivityStateChanged(
+                            info.getType(), info.getSubtype(), info.getDetailedState().ordinal());
 
                     if (info.getDetailedState() ==
                             NetworkInfo.DetailedState.FAILED) {
diff --git a/services/java/com/android/server/DevicePolicyManagerService.java b/services/java/com/android/server/DevicePolicyManagerService.java
index a5e26a8..6a62809 100644
--- a/services/java/com/android/server/DevicePolicyManagerService.java
+++ b/services/java/com/android/server/DevicePolicyManagerService.java
@@ -146,8 +146,8 @@
                     getSendingUserId());
             if (Intent.ACTION_BOOT_COMPLETED.equals(action)
                     || ACTION_EXPIRED_PASSWORD_NOTIFICATION.equals(action)) {
-                Slog.v(TAG, "Sending password expiration notifications for action " + action
-                        + " for user " + userHandle);
+                if (DBG) Slog.v(TAG, "Sending password expiration notifications for action "
+                        + action + " for user " + userHandle);
                 mHandler.post(new Runnable() {
                     public void run() {
                         handlePasswordExpirationNotification(getUserData(userHandle));
@@ -468,7 +468,7 @@
 
     private void handlePackagesChanged(int userHandle) {
         boolean removed = false;
-        Slog.d(TAG, "Handling package changes for user " + userHandle);
+        if (DBG) Slog.d(TAG, "Handling package changes for user " + userHandle);
         DevicePolicyData policy = getUserData(userHandle);
         IPackageManager pm = AppGlobals.getPackageManager();
         for (int i = policy.mAdminList.size() - 1; i >= 0; i--) {
@@ -982,7 +982,7 @@
             long token = Binder.clearCallingIdentity();
             try {
                 String value = cameraDisabled ? "1" : "0";
-                Slog.v(TAG, "Change in camera state ["
+                if (DBG) Slog.v(TAG, "Change in camera state ["
                         + SYSTEM_PROP_DISABLE_CAMERA + "] = " + value);
                 SystemProperties.set(SYSTEM_PROP_DISABLE_CAMERA, value);
             } finally {
@@ -1682,10 +1682,9 @@
                 }
                 int neededNumbers = getPasswordMinimumNumeric(null, userHandle);
                 if (numbers < neededNumbers) {
-                    Slog
-                            .w(TAG, "resetPassword: number of numerical digits " + numbers
-                                    + " does not meet required number of numerical digits "
-                                    + neededNumbers);
+                    Slog.w(TAG, "resetPassword: number of numerical digits " + numbers
+                            + " does not meet required number of numerical digits "
+                            + neededNumbers);
                     return false;
                 }
                 int neededLowerCase = getPasswordMinimumLowerCase(null, userHandle);
@@ -1875,28 +1874,32 @@
                     DeviceAdminInfo.USES_POLICY_WIPE_DATA);
             long ident = Binder.clearCallingIdentity();
             try {
-                if (userHandle == UserHandle.USER_OWNER) {
-                    wipeDataLocked(flags);
-                } else {
-                    lockNowUnchecked();
-                    mHandler.post(new Runnable() {
-                        public void run() {
-                            try {
-                                ActivityManagerNative.getDefault().switchUser(0);
-                                ((UserManager) mContext.getSystemService(Context.USER_SERVICE))
-                                        .removeUser(userHandle);
-                            } catch (RemoteException re) {
-                                // Shouldn't happen
-                            }
-                        }
-                    });
-                }
+                wipeDeviceOrUserLocked(flags, userHandle);
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
         }
     }
 
+    private void wipeDeviceOrUserLocked(int flags, final int userHandle) {
+        if (userHandle == UserHandle.USER_OWNER) {
+            wipeDataLocked(flags);
+        } else {
+            lockNowUnchecked();
+            mHandler.post(new Runnable() {
+                public void run() {
+                    try {
+                        ActivityManagerNative.getDefault().switchUser(0);
+                        ((UserManager) mContext.getSystemService(Context.USER_SERVICE))
+                                .removeUser(userHandle);
+                    } catch (RemoteException re) {
+                        // Shouldn't happen
+                    }
+                }
+            });
+        }
+    }
+
     public void getRemoveWarning(ComponentName comp, final RemoteCallback result, int userHandle) {
         enforceCrossUserPermission(userHandle);
         mContext.enforceCallingOrSelfPermission(
@@ -1996,7 +1999,7 @@
                 saveSettingsLocked(userHandle);
                 int max = getMaximumFailedPasswordsForWipe(null, userHandle);
                 if (max > 0 && policy.mFailedPasswordAttempts >= max) {
-                    wipeDataLocked(0);
+                    wipeDeviceOrUserLocked(0, userHandle);
                 }
                 sendAdminCommandLocked(DeviceAdminReceiver.ACTION_PASSWORD_FAILED,
                         DeviceAdminInfo.USES_POLICY_WATCH_LOGIN, userHandle);
diff --git a/services/java/com/android/server/EntropyMixer.java b/services/java/com/android/server/EntropyMixer.java
index b63a70e..4632374 100644
--- a/services/java/com/android/server/EntropyMixer.java
+++ b/services/java/com/android/server/EntropyMixer.java
@@ -17,6 +17,7 @@
 package com.android.server;
 
 import java.io.File;
+import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.OutputStream;
@@ -97,8 +98,10 @@
     private void loadInitialEntropy() {
         try {
             RandomBlock.fromFile(entropyFile).toFile(randomDevice, false);
+        } catch (FileNotFoundException e) {
+            Slog.w(TAG, "No existing entropy file -- first boot?");
         } catch (IOException e) {
-            Slog.w(TAG, "unable to load initial entropy (first boot?)", e);
+            Slog.w(TAG, "Failure loading existing entropy file", e);
         }
     }
 
@@ -106,7 +109,7 @@
         try {
             RandomBlock.fromFile(randomDevice).toFile(entropyFile, true);
         } catch (IOException e) {
-            Slog.w(TAG, "unable to write entropy", e);
+            Slog.w(TAG, "Unable to write entropy", e);
         }
     }
 
diff --git a/services/java/com/android/server/EventLogTags.logtags b/services/java/com/android/server/EventLogTags.logtags
index 0fe66fc..8bc2da2 100644
--- a/services/java/com/android/server/EventLogTags.logtags
+++ b/services/java/com/android/server/EventLogTags.logtags
@@ -135,12 +135,8 @@
 # ---------------------------
 # ConnectivityService.java
 # ---------------------------
-# Connectivity state changed:
-# [31-14] Reserved for future use
-# [13-10] Network subtype (for mobile network, as defined by TelephonyManager)
-# [ 9- 4] Detailed state ordinal (as defined by NetworkInfo.DetailedState)
-# [ 3- 0] Network type (as defined by ConnectivityManager)
-50020 connectivity_state_changed (custom|1|5)
+# Connectivity state changed
+50020 connectivity_state_changed (type|1),(subtype|1),(state|1)
 
 
 # ---------------------------
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index c9ff595..94e0bd4 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -386,6 +386,7 @@
     private Locale mLastSystemLocale;
     private final MyPackageMonitor mMyPackageMonitor = new MyPackageMonitor();
     private final IPackageManager mIPackageManager;
+    private boolean mInputBoundToKeyguard;
 
     class SettingsObserver extends ContentObserver {
         SettingsObserver(Handler handler) {
@@ -443,7 +444,9 @@
             final int userId = getChangingUserId();
             final boolean retval = userId == mSettings.getCurrentUserId();
             if (DEBUG) {
-                Slog.d(TAG, "--- ignore this call back from a background user: " + userId);
+                if (!retval) {
+                    Slog.d(TAG, "--- ignore this call back from a background user: " + userId);
+                }
             }
             return retval;
         }
@@ -657,7 +660,7 @@
         } catch (RemoteException e) {
             Slog.w(TAG, "Couldn't get current user ID; guessing it's 0", e);
         }
-        mMyPackageMonitor.register(mContext, null, true);
+        mMyPackageMonitor.register(mContext, null, UserHandle.ALL, true);
 
         // mSettings should be created before buildInputMethodListLocked
         mSettings = new InputMethodSettings(
@@ -877,10 +880,12 @@
         final boolean hardKeyShown = haveHardKeyboard
                 && conf.hardKeyboardHidden
                         != Configuration.HARDKEYBOARDHIDDEN_YES;
-        final boolean isScreenLocked = mKeyguardManager != null
-                && mKeyguardManager.isKeyguardLocked()
-                && mKeyguardManager.isKeyguardSecure();
-        mImeWindowVis = (!isScreenLocked && (mInputShown || hardKeyShown)) ?
+        final boolean isScreenLocked =
+                mKeyguardManager != null && mKeyguardManager.isKeyguardLocked();
+        final boolean isScreenSecurelyLocked =
+                isScreenLocked && mKeyguardManager.isKeyguardSecure();
+        final boolean inputShown = mInputShown && (!isScreenLocked || mInputBoundToKeyguard);
+        mImeWindowVis = (!isScreenSecurelyLocked && (inputShown || hardKeyShown)) ?
                 (InputMethodService.IME_ACTIVE | InputMethodService.IME_VISIBLE) : 0;
         updateImeWindowStatusLocked();
     }
@@ -1124,6 +1129,13 @@
             return mNoBinding;
         }
 
+        if (mCurClient == null) {
+            mInputBoundToKeyguard = mKeyguardManager != null && mKeyguardManager.isKeyguardLocked();
+            if (DEBUG) {
+                Slog.v(TAG, "New bind. keyguard = " +  mInputBoundToKeyguard);
+            }
+        }
+
         if (mCurClient != cs) {
             // If the client is changing, we need to switch over to the new
             // one.
@@ -1814,9 +1826,9 @@
     public InputBindResult windowGainedFocus(IInputMethodClient client, IBinder windowToken,
             int controlFlags, int softInputMode, int windowFlags,
             EditorInfo attribute, IInputContext inputContext) {
-        if (!calledFromValidUser()) {
-            return null;
-        }
+        // Needs to check the validity before clearing calling identity
+        final boolean calledFromValidUser = calledFromValidUser();
+
         InputBindResult res = null;
         long ident = Binder.clearCallingIdentity();
         try {
@@ -1846,6 +1858,14 @@
                 } catch (RemoteException e) {
                 }
 
+                if (!calledFromValidUser) {
+                    Slog.w(TAG, "A background user is requesting window. Hiding IME.");
+                    Slog.w(TAG, "If you want to interect with IME, you need "
+                            + "android.permission.INTERACT_ACROSS_USERS_FULL");
+                    hideCurrentInputLocked(0, null);
+                    return null;
+                }
+
                 if (mCurFocusedWindow == windowToken) {
                     Slog.w(TAG, "Window already focused, ignoring focus gain of: " + client
                             + " attribute=" + attribute + ", token = " + windowToken);
@@ -2486,10 +2506,8 @@
                 map.put(id, p);
 
                 // Valid system default IMEs and IMEs that have English subtypes are enabled
-                // by default, unless there's a hard keyboard and the system IME was explicitly
-                // disabled
-                if ((isValidSystemDefaultIme(p, mContext) || isSystemImeThatHasEnglishSubtype(p))
-                        && (!haveHardKeyboard || disabledSysImes.indexOf(id) < 0)) {
+                // by default
+                if ((isValidSystemDefaultIme(p, mContext) || isSystemImeThatHasEnglishSubtype(p))) {
                     setInputMethodEnabledLocked(id, true);
                 }
 
diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java
index 89fa6d0..f21f826 100644
--- a/services/java/com/android/server/LocationManagerService.java
+++ b/services/java/com/android/server/LocationManagerService.java
@@ -506,7 +506,7 @@
                 }
             } else {
                 Intent statusChanged = new Intent();
-                statusChanged.putExtras(extras);
+                statusChanged.putExtras(new Bundle(extras));
                 statusChanged.putExtra(LocationManager.KEY_STATUS_CHANGED, status);
                 try {
                     synchronized (this) {
@@ -531,7 +531,7 @@
                     synchronized (this) {
                         // synchronize to ensure incrementPendingBroadcastsLocked()
                         // is called before decrementPendingBroadcasts()
-                        mListener.onLocationChanged(location);
+                        mListener.onLocationChanged(new Location(location));
                         // call this after broadcasting so we do not increment
                         // if we throw an exeption.
                         incrementPendingBroadcastsLocked();
@@ -541,7 +541,7 @@
                 }
             } else {
                 Intent locationChanged = new Intent();
-                locationChanged.putExtra(LocationManager.KEY_LOCATION_CHANGED, location);
+                locationChanged.putExtra(LocationManager.KEY_LOCATION_CHANGED, new Location(location));
                 try {
                     synchronized (this) {
                         // synchronize to ensure incrementPendingBroadcastsLocked()
@@ -1323,10 +1323,10 @@
                 if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
                     Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
                     if (noGPSLocation != null) {
-                        return mLocationFudger.getOrCreate(noGPSLocation);
+                        return new Location(mLocationFudger.getOrCreate(noGPSLocation));
                     }
                 } else {
-                    return location;
+                    return new Location(location);
                 }
             }
             return null;
@@ -1710,6 +1710,7 @@
             for (UpdateRecord r : deadUpdateRecords) {
                 r.disposeLocked(true);
             }
+            applyRequirementsLocked(provider);
         }
     }
 
diff --git a/services/java/com/android/server/MountService.java b/services/java/com/android/server/MountService.java
index c512bc1..2e0c977 100644
--- a/services/java/com/android/server/MountService.java
+++ b/services/java/com/android/server/MountService.java
@@ -57,6 +57,8 @@
 import android.util.Slog;
 import android.util.Xml;
 
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.app.IMediaContainerService;
 import com.android.internal.util.Preconditions;
 import com.android.internal.util.XmlUtils;
@@ -103,9 +105,9 @@
 
     // TODO: listen for user creation/deletion
 
-    private static final boolean LOCAL_LOGD = true;
-    private static final boolean DEBUG_UNMOUNT = true;
-    private static final boolean DEBUG_EVENTS = true;
+    private static final boolean LOCAL_LOGD = false;
+    private static final boolean DEBUG_UNMOUNT = false;
+    private static final boolean DEBUG_EVENTS = false;
     private static final boolean DEBUG_OBB = false;
 
     // Disable this since it messes up long-running cryptfs operations.
@@ -181,13 +183,13 @@
     /** When defined, base template for user-specific {@link StorageVolume}. */
     private StorageVolume mEmulatedTemplate;
 
-    // @GuardedBy("mVolumesLock")
+    @GuardedBy("mVolumesLock")
     private final ArrayList<StorageVolume> mVolumes = Lists.newArrayList();
     /** Map from path to {@link StorageVolume} */
-    // @GuardedBy("mVolumesLock")
+    @GuardedBy("mVolumesLock")
     private final HashMap<String, StorageVolume> mVolumesByPath = Maps.newHashMap();
     /** Map from path to state */
-    // @GuardedBy("mVolumesLock")
+    @GuardedBy("mVolumesLock")
     private final HashMap<String, String> mVolumeStates = Maps.newHashMap();
 
     private volatile boolean mSystemReady = false;
@@ -198,8 +200,8 @@
     // Used as a lock for methods that register/unregister listeners.
     final private ArrayList<MountServiceBinderListener> mListeners =
             new ArrayList<MountServiceBinderListener>();
-    private CountDownLatch                        mConnectedSignal = new CountDownLatch(1);
-    private CountDownLatch                        mAsecsScanned = new CountDownLatch(1);
+    private final CountDownLatch mConnectedSignal = new CountDownLatch(1);
+    private final CountDownLatch mAsecsScanned = new CountDownLatch(1);
     private boolean                               mSendUmsConnectedOnBoot = false;
 
     /**
@@ -495,10 +497,6 @@
     }
 
     private void waitForLatch(CountDownLatch latch) {
-        if (latch == null) {
-            return;
-        }
-
         for (;;) {
             try {
                 if (latch.await(5000, TimeUnit.MILLISECONDS)) {
@@ -738,14 +736,12 @@
                  * the hounds!
                  */
                 mConnectedSignal.countDown();
-                mConnectedSignal = null;
 
                 // Let package manager load internal ASECs.
                 mPms.scanAvailableAsecs();
 
                 // Notify people waiting for ASECs to be scanned that it's done.
                 mAsecsScanned.countDown();
-                mAsecsScanned = null;
             }
         }.start();
     }
@@ -2571,7 +2567,7 @@
         }
     }
 
-    // @VisibleForTesting
+    @VisibleForTesting
     public static String buildObbPath(final String canonicalPath, int userId, boolean forVold) {
         // TODO: allow caller to provide Environment for full testing
 
diff --git a/services/java/com/android/server/NativeDaemonConnector.java b/services/java/com/android/server/NativeDaemonConnector.java
index 92af9a9..5e94a9f 100644
--- a/services/java/com/android/server/NativeDaemonConnector.java
+++ b/services/java/com/android/server/NativeDaemonConnector.java
@@ -25,6 +25,7 @@
 import android.util.LocalLog;
 import android.util.Slog;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.google.android.collect.Lists;
 
 import java.nio.charset.Charsets;
@@ -400,7 +401,7 @@
      * Append the given argument to {@link StringBuilder}, escaping as needed,
      * and surrounding with quotes when it contains spaces.
      */
-    // @VisibleForTesting
+    @VisibleForTesting
     static void appendEscaped(StringBuilder builder, String arg) {
         final boolean hasSpaces = arg.indexOf(' ') >= 0;
         if (hasSpaces) {
diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/java/com/android/server/NotificationManagerService.java
index 70d37bf..37d7ce7 100755
--- a/services/java/com/android/server/NotificationManagerService.java
+++ b/services/java/com/android/server/NotificationManagerService.java
@@ -110,6 +110,11 @@
     private static final int NOTIFICATION_PRIORITY_MULTIPLIER = 10;
     private static final int SCORE_DISPLAY_THRESHOLD = Notification.PRIORITY_MIN * NOTIFICATION_PRIORITY_MULTIPLIER;
 
+    // Notifications with scores below this will not interrupt the user, either via LED or
+    // sound or vibration
+    private static final int SCORE_INTERRUPTION_THRESHOLD =
+            Notification.PRIORITY_LOW * NOTIFICATION_PRIORITY_MULTIPLIER;
+
     private static final boolean ENABLE_BLOCKED_NOTIFICATIONS = true;
     private static final boolean ENABLE_BLOCKED_TOASTS = true;
 
@@ -991,6 +996,9 @@
             return;
         }
 
+        // Should this notification make noise, vibe, or use the LED?
+        final boolean canInterrupt = (score >= SCORE_INTERRUPTION_THRESHOLD);
+
         synchronized (mNotificationList) {
             NotificationRecord r = new NotificationRecord(pkg, tag, id, 
                     callingUid, callingPid, userId,
@@ -1042,7 +1050,8 @@
                     long identity = Binder.clearCallingIdentity();
                     try {
                         r.statusBarKey = mStatusBar.addNotification(n);
-                        if ((n.notification.flags & Notification.FLAG_SHOW_LIGHTS) != 0) {
+                        if ((n.notification.flags & Notification.FLAG_SHOW_LIGHTS) != 0
+                                && canInterrupt) {
                             mAttentionLight.pulse();
                         }
                     }
@@ -1073,20 +1082,32 @@
                         && (notification.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0 ))
                     && (r.userId == UserHandle.USER_ALL ||
                         (r.userId == userId && r.userId == currentUser))
+                    && canInterrupt
                     && mSystemReady) {
 
                 final AudioManager audioManager = (AudioManager) mContext
                 .getSystemService(Context.AUDIO_SERVICE);
+
                 // sound
                 final boolean useDefaultSound =
                     (notification.defaults & Notification.DEFAULT_SOUND) != 0;
-                if (useDefaultSound || notification.sound != null) {
-                    Uri uri;
-                    if (useDefaultSound) {
-                        uri = Settings.System.DEFAULT_NOTIFICATION_URI;
-                    } else {
-                        uri = notification.sound;
-                    }
+
+                Uri soundUri = null;
+                boolean hasValidSound = false;
+
+                if (useDefaultSound) {
+                    soundUri = Settings.System.DEFAULT_NOTIFICATION_URI;
+
+                    // check to see if the default notification sound is silent
+                    ContentResolver resolver = mContext.getContentResolver();
+                    hasValidSound = Settings.System.getString(resolver,
+                           Settings.System.NOTIFICATION_SOUND) != null;
+                } else if (notification.sound != null) {
+                    soundUri = notification.sound;
+                    hasValidSound = (soundUri != null);
+                }
+
+                if (hasValidSound) {
                     boolean looping = (notification.flags & Notification.FLAG_INSISTENT) != 0;
                     int audioStreamType;
                     if (notification.audioStreamType >= 0) {
@@ -1103,7 +1124,7 @@
                         try {
                             final IRingtonePlayer player = mAudioService.getRingtonePlayer();
                             if (player != null) {
-                                player.playAsync(uri, user, looping, audioStreamType);
+                                player.playAsync(soundUri, user, looping, audioStreamType);
                             }
                         } catch (RemoteException e) {
                         } finally {
@@ -1117,13 +1138,13 @@
                 final boolean hasCustomVibrate = notification.vibrate != null;
 
                 // new in 4.2: if there was supposed to be a sound and we're in vibrate mode,
-                // and no other vibration is specified, we apply the default vibration anyway
+                // and no other vibration is specified, we fall back to vibration
                 final boolean convertSoundToVibration =
                            !hasCustomVibrate
-                        && (useDefaultSound || notification.sound != null)
+                        && hasValidSound
                         && (audioManager.getRingerMode() == AudioManager.RINGER_MODE_VIBRATE);
 
-                // The DEFAULT_VIBRATE flag trumps any custom vibration.
+                // The DEFAULT_VIBRATE flag trumps any custom vibration AND the fallback.
                 final boolean useDefaultVibrate =
                         (notification.defaults & Notification.DEFAULT_VIBRATE) != 0;
 
@@ -1136,8 +1157,8 @@
                         // does not have the VIBRATE permission.
                         long identity = Binder.clearCallingIdentity();
                         try {
-                            mVibrator.vibrate(convertSoundToVibration ? mFallbackVibrationPattern
-                                                                      : mDefaultVibrationPattern,
+                            mVibrator.vibrate(useDefaultVibrate ? mDefaultVibrationPattern
+                                                                : mFallbackVibrationPattern,
                                 ((notification.flags & Notification.FLAG_INSISTENT) != 0) ? 0: -1);
                         } finally {
                             Binder.restoreCallingIdentity(identity);
@@ -1160,7 +1181,8 @@
             }
             //Slog.i(TAG, "notification.lights="
             //        + ((old.notification.lights.flags & Notification.FLAG_SHOW_LIGHTS) != 0));
-            if ((notification.flags & Notification.FLAG_SHOW_LIGHTS) != 0) {
+            if ((notification.flags & Notification.FLAG_SHOW_LIGHTS) != 0
+                    && canInterrupt) {
                 mLights.add(r);
                 updateLightsLocked();
             } else {
diff --git a/services/java/com/android/server/RecognitionManagerService.java b/services/java/com/android/server/RecognitionManagerService.java
index 1e0755d..c2e749d 100644
--- a/services/java/com/android/server/RecognitionManagerService.java
+++ b/services/java/com/android/server/RecognitionManagerService.java
@@ -89,17 +89,15 @@
     private void initForUser(int userHandle) {
         if (DEBUG) Slog.i(TAG, "initForUser user=" + userHandle);
         ComponentName comp = getCurRecognizer(userHandle);
+        ServiceInfo info = null;
         if (comp != null) {
-            // See if the current recognizer is no longer available.
+            // See if the current recognizer is still available.
             try {
-                mIPm.getServiceInfo(comp, 0, userHandle);
+                info = mIPm.getServiceInfo(comp, 0, userHandle);
             } catch (RemoteException e) {
-                comp = findAvailRecognizer(null, userHandle);
-                if (comp != null) {
-                    setCurRecognizer(comp, userHandle);
-                }
             }
-        } else {
+        }
+        if (info == null) {
             comp = findAvailRecognizer(null, userHandle);
             if (comp != null) {
                 setCurRecognizer(comp, userHandle);
diff --git a/services/java/com/android/server/ServiceWatcher.java b/services/java/com/android/server/ServiceWatcher.java
index 2e7c6d1..67f926a 100644
--- a/services/java/com/android/server/ServiceWatcher.java
+++ b/services/java/com/android/server/ServiceWatcher.java
@@ -177,7 +177,7 @@
         mVersion = version;
         if (D) Log.d(mTag, "binding " + packageName + " (version " + version + ")");
         mContext.bindService(intent, this, Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND
-                | Context.BIND_ALLOW_OOM_MANAGEMENT | Context.BIND_NOT_VISIBLE, mCurrentUserId);
+                | Context.BIND_NOT_VISIBLE, mCurrentUserId);
     }
 
     public static boolean isSignatureMatch(Signature[] signatures,
diff --git a/services/java/com/android/server/StatusBarManagerService.java b/services/java/com/android/server/StatusBarManagerService.java
index 439eebe..1fe98af 100644
--- a/services/java/com/android/server/StatusBarManagerService.java
+++ b/services/java/com/android/server/StatusBarManagerService.java
@@ -170,7 +170,9 @@
         // so they are paired correctly.  The messages on the handler will be
         // handled in the order they were enqueued, but will be outside the lock.
         manageDisableListLocked(userId, what, token, pkg);
-        final int net = gatherDisableActionsLocked(userId);
+
+        // Ensure state for the current user is applied, even if passed a non-current user.
+        final int net = gatherDisableActionsLocked(mCurrentUserId);
         if (net != mDisabled) {
             mDisabled = net;
             mHandler.post(new Runnable() {
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 894c4d0..55885e6 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -1005,7 +1005,7 @@
         Intent intent = new Intent();
         intent.setComponent(new ComponentName("com.android.systemui",
                     "com.android.systemui.SystemUIService"));
-        Slog.d(TAG, "Starting service: " + intent);
+        //Slog.d(TAG, "Starting service: " + intent);
         context.startServiceAsUser(intent, UserHandle.OWNER);
     }
 }
diff --git a/services/java/com/android/server/TelephonyRegistry.java b/services/java/com/android/server/TelephonyRegistry.java
index 26684de..17260d5 100644
--- a/services/java/com/android/server/TelephonyRegistry.java
+++ b/services/java/com/android/server/TelephonyRegistry.java
@@ -139,7 +139,7 @@
         public void handleMessage(Message msg) {
             switch (msg.what) {
                 case MSG_USER_SWITCHED: {
-                    Slog.d(TAG, "MSG_USER_SWITCHED userId=" + msg.arg1);
+                    if (DBG) Slog.d(TAG, "MSG_USER_SWITCHED userId=" + msg.arg1);
                     TelephonyRegistry.this.notifyCellLocation(mCellLocation);
                     break;
                 }
diff --git a/services/java/com/android/server/WallpaperManagerService.java b/services/java/com/android/server/WallpaperManagerService.java
index 82dbf54..21a1956 100644
--- a/services/java/com/android/server/WallpaperManagerService.java
+++ b/services/java/com/android/server/WallpaperManagerService.java
@@ -1096,6 +1096,8 @@
                 }
             } while (type != XmlPullParser.END_DOCUMENT);
             success = true;
+        } catch (FileNotFoundException e) {
+            Slog.w(TAG, "no current wallpaper -- first boot?");
         } catch (NullPointerException e) {
             Slog.w(TAG, "failed parsing " + file + " " + e);
         } catch (NumberFormatException e) {
diff --git a/services/java/com/android/server/Watchdog.java b/services/java/com/android/server/Watchdog.java
index 8bbf923..b2a8ad8 100644
--- a/services/java/com/android/server/Watchdog.java
+++ b/services/java/com/android/server/Watchdog.java
@@ -39,6 +39,8 @@
 import android.util.Slog;
 
 import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Calendar;
 
@@ -439,6 +441,16 @@
                 dumpKernelStackTraces();
             }
 
+            // Trigger the kernel to dump all blocked threads to the kernel log
+            try {
+                FileWriter sysrq_trigger = new FileWriter("/proc/sysrq-trigger");
+                sysrq_trigger.write("w");
+                sysrq_trigger.close();
+            } catch (IOException e) {
+                Slog.e(TAG, "Failed to write to /proc/sysrq-trigger");
+                Slog.e(TAG, e.getMessage());
+            }
+
             // Try to add the error to the dropbox, but assuming that the ActivityManager
             // itself may be deadlocked.  (which has happened, causing this statement to
             // deadlock and the watchdog as a whole to be ineffective)
diff --git a/services/java/com/android/server/am/ActiveServices.java b/services/java/com/android/server/am/ActiveServices.java
index 35999ea..5c24e67 100644
--- a/services/java/com/android/server/am/ActiveServices.java
+++ b/services/java/com/android/server/am/ActiveServices.java
@@ -1090,11 +1090,8 @@
 
         boolean created = false;
         try {
-            mAm.mStringBuilder.setLength(0);
-            r.intent.getIntent().toShortString(mAm.mStringBuilder, true, false, true, false);
-            EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
-                    r.userId, System.identityHashCode(r), r.shortName,
-                    mAm.mStringBuilder.toString(), r.app.pid);
+            EventLogTags.writeAmCreateService(
+                    r.userId, System.identityHashCode(r), r.shortName, r.app.pid);
             synchronized (r.stats.getBatteryStats()) {
                 r.stats.startLaunchedLocked();
             }
@@ -1242,9 +1239,8 @@
         }
 
         if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down " + r + " " + r.intent);
-        EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
-                r.userId, System.identityHashCode(r), r.shortName,
-                (r.app != null) ? r.app.pid : -1);
+        EventLogTags.writeAmDestroyService(
+                r.userId, System.identityHashCode(r), (r.app != null) ? r.app.pid : -1);
 
         mServiceMap.removeServiceByName(r.name, r.userId);
         mServiceMap.removeServiceByIntent(r.intent, r.userId);
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index d2cd646..1d08d31 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -21,7 +21,6 @@
 import com.android.internal.R;
 import com.android.internal.os.BatteryStatsImpl;
 import com.android.internal.os.ProcessStats;
-import com.android.internal.widget.LockPatternUtils;
 import com.android.server.AttributeCache;
 import com.android.server.IntentResolver;
 import com.android.server.ProcessMap;
@@ -3870,7 +3869,7 @@
         }
 
         boolean didSomething = killPackageProcessesLocked(name, appId, userId,
-                -100, callerWillRestart, false, doit, evenPersistent,
+                -100, callerWillRestart, true, doit, evenPersistent,
                 name == null ? ("force stop user " + userId) : ("force stop " + name));
         
         TaskRecord lastTask = null;
@@ -4764,6 +4763,18 @@
         return false;
     }
 
+    public Intent getIntentForIntentSender(IIntentSender pendingResult) {
+        if (!(pendingResult instanceof PendingIntentRecord)) {
+            return null;
+        }
+        try {
+            PendingIntentRecord res = (PendingIntentRecord)pendingResult;
+            return res.key.requestIntent != null ? new Intent(res.key.requestIntent) : null;
+        } catch (ClassCastException e) {
+        }
+        return null;
+    }
+
     public void setProcessLimit(int max) {
         enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
                 "setProcessLimit()");
@@ -7923,7 +7934,7 @@
                             }
                         }, 0, null, null,
                         android.Manifest.permission.INTERACT_ACROSS_USERS,
-                        false, false, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL);
+                        true, false, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL);
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
@@ -12316,7 +12327,7 @@
                 }
                 newConfig.seq = mConfigurationSeq;
                 mConfiguration = newConfig;
-                Slog.i(TAG, "Config changed: " + newConfig);
+                Slog.i(TAG, "Config changes=" + Integer.toHexString(changes) + " " + newConfig);
 
                 final Configuration configCopy = new Configuration(mConfiguration);
                 
@@ -14120,7 +14131,7 @@
     // Multi-user methods
 
     @Override
-    public boolean switchUser(int userId) {
+    public boolean switchUser(final int userId) {
         if (checkCallingPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
                 != PackageManager.PERMISSION_GRANTED) {
             String msg = "Permission Denial: switchUser() from pid="
@@ -14168,7 +14179,7 @@
 
                 // Once the internal notion of the active user has switched, we lock the device
                 // with the option to show the user switcher on the keyguard.
-                mWindowManager.lockNow(LockPatternUtils.USER_SWITCH_LOCK_OPTIONS);
+                mWindowManager.lockNow(null);
 
                 final UserStartedState uss = mStartedUsers.get(userId);
 
@@ -14214,7 +14225,7 @@
                                     public void performReceive(Intent intent, int resultCode,
                                             String data, Bundle extras, boolean ordered,
                                             boolean sticky, int sendingUser) {
-                                        userInitialized(uss);
+                                        userInitialized(uss, userId);
                                     }
                                 }, 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID,
                                 userId);
@@ -14229,6 +14240,7 @@
                     startHomeActivityLocked(userId);
                 }
 
+                EventLogTags.writeAmSwitchUser(userId);
                 getUserManagerLocked().userForeground(userId);
                 sendUserSwitchBroadcastsLocked(oldUserId, userId);
                 if (needStart) {
@@ -14244,7 +14256,7 @@
                                 }
                             }, 0, null, null,
                             android.Manifest.permission.INTERACT_ACROSS_USERS,
-                            false, false, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL);
+                            true, false, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL);
                 }
             }
         } finally {
@@ -14340,32 +14352,39 @@
                 oldUserId, newUserId, uss));
     }
 
-    void userInitialized(UserStartedState uss) {
-        synchronized (ActivityManagerService.this) {
-            getUserManagerLocked().makeInitialized(uss.mHandle.getIdentifier());
-            uss.initializing = false;
-            completeSwitchAndInitalizeLocked(uss);
-        }
+    void userInitialized(UserStartedState uss, int newUserId) {
+        completeSwitchAndInitalize(uss, newUserId, true, false);
     }
 
     void continueUserSwitch(UserStartedState uss, int oldUserId, int newUserId) {
-        final int N = mUserSwitchObservers.beginBroadcast();
-        for (int i=0; i<N; i++) {
-            try {
-                mUserSwitchObservers.getBroadcastItem(i).onUserSwitchComplete(newUserId);
-            } catch (RemoteException e) {
-            }
-        }
-        mUserSwitchObservers.finishBroadcast();
-        synchronized (this) {
-            uss.switching = false;
-            completeSwitchAndInitalizeLocked(uss);
-        }
+        completeSwitchAndInitalize(uss, newUserId, false, true);
     }
 
-    void completeSwitchAndInitalizeLocked(UserStartedState uss) {
-        if (!uss.switching && !uss.initializing) {
-            mWindowManager.stopFreezingScreen();
+    void completeSwitchAndInitalize(UserStartedState uss, int newUserId,
+            boolean clearInitializing, boolean clearSwitching) {
+        boolean unfrozen = false;
+        synchronized (this) {
+            if (clearInitializing) {
+                uss.initializing = false;
+                getUserManagerLocked().makeInitialized(uss.mHandle.getIdentifier());
+            }
+            if (clearSwitching) {
+                uss.switching = false;
+            }
+            if (!uss.switching && !uss.initializing) {
+                mWindowManager.stopFreezingScreen();
+                unfrozen = true;
+            }
+        }
+        if (unfrozen) {
+            final int N = mUserSwitchObservers.beginBroadcast();
+            for (int i=0; i<N; i++) {
+                try {
+                    mUserSwitchObservers.getBroadcastItem(i).onUserSwitchComplete(newUserId);
+                } catch (RemoteException e) {
+                }
+            }
+            mUserSwitchObservers.finishBroadcast();
         }
     }
 
@@ -14467,7 +14486,7 @@
             long ident = Binder.clearCallingIdentity();
             try {
                 // We are going to broadcast ACTION_USER_STOPPING and then
-                // once that is down send a final ACTION_SHUTDOWN and then
+                // once that is done send a final ACTION_SHUTDOWN and then
                 // stop the user.
                 final Intent stoppingIntent = new Intent(Intent.ACTION_USER_STOPPING);
                 stoppingIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
@@ -14532,6 +14551,10 @@
                 // Clean up all state and processes associated with the user.
                 // Kill all the processes for the user.
                 forceStopUserLocked(userId);
+                AttributeCache ac = AttributeCache.instance();
+                if (ac != null) {
+                    ac.removeUser(userId);
+                }
             }
         }
 
diff --git a/services/java/com/android/server/am/ActivityRecord.java b/services/java/com/android/server/am/ActivityRecord.java
index 749dc66..de0f9ca 100644
--- a/services/java/com/android/server/am/ActivityRecord.java
+++ b/services/java/com/android/server/am/ActivityRecord.java
@@ -407,7 +407,7 @@
             packageName = aInfo.applicationInfo.packageName;
             launchMode = aInfo.launchMode;
             
-            AttributeCache.Entry ent = AttributeCache.instance().get(packageName,
+            AttributeCache.Entry ent = AttributeCache.instance().get(userId, packageName,
                     realTheme, com.android.internal.R.styleable.Window);
             fullscreen = ent != null && !ent.array.getBoolean(
                     com.android.internal.R.styleable.Window_windowIsFloating, false)
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index 4546dc3..27dd732 100755
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -1810,8 +1810,8 @@
                         }
                         mHistory.add(addPos, r);
                         r.putInHistory();
-                        mService.mWindowManager.addAppToken(addPos, r.appToken, r.task.taskId,
-                                r.info.screenOrientation, r.fullscreen,
+                        mService.mWindowManager.addAppToken(addPos, r.userId, r.appToken,
+                                r.task.taskId, r.info.screenOrientation, r.fullscreen,
                                 (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0);
                         if (VALIDATE_TOKENS) {
                             validateAppTokensLocked();
@@ -1875,8 +1875,8 @@
                 mNoAnimActivities.remove(r);
             }
             r.updateOptionsLocked(options);
-            mService.mWindowManager.addAppToken(
-                    addPos, r.appToken, r.task.taskId, r.info.screenOrientation, r.fullscreen,
+            mService.mWindowManager.addAppToken(addPos, r.userId, r.appToken,
+                    r.task.taskId, r.info.screenOrientation, r.fullscreen,
                     (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0);
             boolean doShow = true;
             if (newTask) {
@@ -1914,8 +1914,8 @@
         } else {
             // If this is the first activity, don't do any fancy animations,
             // because there is nothing for it to animate on top of.
-            mService.mWindowManager.addAppToken(addPos, r.appToken, r.task.taskId,
-                    r.info.screenOrientation, r.fullscreen,
+            mService.mWindowManager.addAppToken(addPos, r.userId, r.appToken,
+                    r.task.taskId, r.info.screenOrientation, r.fullscreen,
                     (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0);
             ActivityOptions.abort(options);
         }
diff --git a/services/java/com/android/server/am/BroadcastQueue.java b/services/java/com/android/server/am/BroadcastQueue.java
index f9630ae..bada7f0 100644
--- a/services/java/com/android/server/am/BroadcastQueue.java
+++ b/services/java/com/android/server/am/BroadcastQueue.java
@@ -38,6 +38,7 @@
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.util.EventLog;
+import android.util.Log;
 import android.util.Slog;
 
 /**
@@ -779,6 +780,21 @@
                 } catch (RemoteException e) {
                     Slog.w(TAG, "Exception when sending broadcast to "
                           + r.curComponent, e);
+                } catch (RuntimeException e) {
+                    Log.wtf(TAG, "Failed sending broadcast to "
+                            + r.curComponent + " with " + r.intent, e);
+                    // If some unexpected exception happened, just skip
+                    // this broadcast.  At this point we are not in the call
+                    // from a client, so throwing an exception out from here
+                    // will crash the entire system instead of just whoever
+                    // sent the broadcast.
+                    logBroadcastReceiverDiscardLocked(r);
+                    finishReceiverLocked(r, r.resultCode, r.resultData,
+                            r.resultExtras, r.resultAbort, true);
+                    scheduleBroadcastsLocked();
+                    // We need to reset the state if we failed to start the receiver.
+                    r.state = BroadcastRecord.IDLE;
+                    return;
                 }
 
                 // If a dead object exception was thrown -- fall through to
diff --git a/services/java/com/android/server/am/EventLogTags.logtags b/services/java/com/android/server/am/EventLogTags.logtags
index 6ee7507..f784861 100644
--- a/services/java/com/android/server/am/EventLogTags.logtags
+++ b/services/java/com/android/server/am/EventLogTags.logtags
@@ -63,9 +63,9 @@
 30024 am_broadcast_discard_filter (User|1|5),(Broadcast|1|5),(Action|3),(Receiver Number|1|1),(BroadcastFilter|1|5)
 30025 am_broadcast_discard_app (User|1|5),(Broadcast|1|5),(Action|3),(Receiver Number|1|1),(App|3)
 # A service is being created
-30030 am_create_service (User|1|5),(Service Record|1|5),(Name|3),(Intent|3),(PID|1|5)
+30030 am_create_service (User|1|5),(Service Record|1|5),(Name|3),(PID|1|5)
 # A service is being destroyed
-30031 am_destroy_service (User|1|5),(Service Record|1|5),(Name|3),(PID|1|5)
+30031 am_destroy_service (User|1|5),(Service Record|1|5),(PID|1|5)
 # A process has crashed too many times, it is being cleared
 30032 am_process_crashed_too_much (User|1|5),(Name|3),(PID|1|5)
 # An unknown process is trying to attach to the activity manager
@@ -83,3 +83,6 @@
 30039 am_crash (User|1|5),(PID|1|5),(Process Name|3),(Flags|1|5),(Exception|3),(Message|3),(File|3),(Line|1|5)
 # Log.wtf() called
 30040 am_wtf (User|1|5),(PID|1|5),(Process Name|3),(Flags|1|5),(Tag|3),(Message|3)
+
+# User switched
+30041 am_switch_user (id|1|5)
diff --git a/services/java/com/android/server/display/DisplayManagerService.java b/services/java/com/android/server/display/DisplayManagerService.java
index e58a0a5cb..e09970e 100644
--- a/services/java/com/android/server/display/DisplayManagerService.java
+++ b/services/java/com/android/server/display/DisplayManagerService.java
@@ -41,6 +41,7 @@
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.concurrent.CopyOnWriteArrayList;
 
 /**
  * Manages attached displays.
@@ -152,6 +153,10 @@
             new SparseArray<LogicalDisplay>();
     private int mNextNonDefaultDisplayId = Display.DEFAULT_DISPLAY + 1;
 
+    // List of all display transaction listeners.
+    private final CopyOnWriteArrayList<DisplayTransactionListener> mDisplayTransactionListeners =
+            new CopyOnWriteArrayList<DisplayTransactionListener>();
+
     // Set to true if all displays have been blanked by the power manager.
     private int mAllDisplayBlankStateFromPowerManager;
 
@@ -261,6 +266,36 @@
     }
 
     /**
+     * Registers a display transaction listener to provide the client a chance to
+     * update its surfaces within the same transaction as any display layout updates.
+     *
+     * @param listener The listener to register.
+     */
+    public void registerDisplayTransactionListener(DisplayTransactionListener listener) {
+        if (listener == null) {
+            throw new IllegalArgumentException("listener must not be null");
+        }
+
+        // List is self-synchronized copy-on-write.
+        mDisplayTransactionListeners.add(listener);
+    }
+
+    /**
+     * Unregisters a display transaction listener to provide the client a chance to
+     * update its surfaces within the same transaction as any display layout updates.
+     *
+     * @param listener The listener to unregister.
+     */
+    public void unregisterDisplayTransactionListener(DisplayTransactionListener listener) {
+        if (listener == null) {
+            throw new IllegalArgumentException("listener must not be null");
+        }
+
+        // List is self-synchronized copy-on-write.
+        mDisplayTransactionListeners.remove(listener);
+    }
+
+    /**
      * Overrides the display information of a particular logical display.
      * This is used by the window manager to control the size and characteristics
      * of the default display.  It is expected to apply the requested change
@@ -298,6 +333,11 @@
 
             performTraversalInTransactionLocked();
         }
+
+        // List is self-synchronized copy-on-write.
+        for (DisplayTransactionListener listener : mDisplayTransactionListeners) {
+            listener.onDisplayTransaction();
+        }
     }
 
     /**
diff --git a/services/java/com/android/server/display/DisplayTransactionListener.java b/services/java/com/android/server/display/DisplayTransactionListener.java
new file mode 100644
index 0000000..34eb8f9
--- /dev/null
+++ b/services/java/com/android/server/display/DisplayTransactionListener.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.display;
+
+/**
+ * Called within a Surface transaction whenever the size or orientation of a
+ * display may have changed.  Provides an opportunity for the client to
+ * update the position of its surfaces as part of the same transaction.
+ */
+public interface DisplayTransactionListener {
+    void onDisplayTransaction();
+}
diff --git a/services/java/com/android/server/display/PersistentDataStore.java b/services/java/com/android/server/display/PersistentDataStore.java
index 3a6e1a6..105c253 100644
--- a/services/java/com/android/server/display/PersistentDataStore.java
+++ b/services/java/com/android/server/display/PersistentDataStore.java
@@ -81,6 +81,15 @@
         }
     }
 
+    public WifiDisplay getRememberedWifiDisplay(String deviceAddress) {
+        loadIfNeeded();
+        int index = findRememberedWifiDisplay(deviceAddress);
+        if (index >= 0) {
+            return mRememberedWifiDisplays.get(index);
+        }
+        return null;
+    }
+
     public WifiDisplay[] getRememberedWifiDisplays() {
         loadIfNeeded();
         return mRememberedWifiDisplays.toArray(new WifiDisplay[mRememberedWifiDisplays.size()]);
@@ -137,22 +146,6 @@
         return true;
     }
 
-    public boolean renameWifiDisplay(String deviceAddress, String alias) {
-        int index = findRememberedWifiDisplay(deviceAddress);
-        if (index >= 0) {
-            WifiDisplay display = mRememberedWifiDisplays.get(index);
-            if (Objects.equal(display.getDeviceAlias(), alias)) {
-                return false; // already has this alias
-            }
-            WifiDisplay renamedDisplay = new WifiDisplay(deviceAddress,
-                    display.getDeviceName(), alias);
-            mRememberedWifiDisplays.set(index, renamedDisplay);
-            setDirty();
-            return true;
-        }
-        return false;
-    }
-
     public boolean forgetWifiDisplay(String deviceAddress) {
         int index = findRememberedWifiDisplay(deviceAddress);
         if (index >= 0) {
diff --git a/services/java/com/android/server/display/WifiDisplayAdapter.java b/services/java/com/android/server/display/WifiDisplayAdapter.java
index 45fff30..c8a44d2 100644
--- a/services/java/com/android/server/display/WifiDisplayAdapter.java
+++ b/services/java/com/android/server/display/WifiDisplayAdapter.java
@@ -45,6 +45,8 @@
 import java.io.PrintWriter;
 import java.util.Arrays;
 
+import libcore.util.Objects;
+
 /**
  * Connects to Wifi displays that implement the Miracast protocol.
  * <p>
@@ -224,16 +226,18 @@
             }
         }
 
-        if (mPersistentDataStore.renameWifiDisplay(address, alias)) {
-            mPersistentDataStore.saveIfNeeded();
-            updateRememberedDisplaysLocked();
-            scheduleStatusChangedBroadcastLocked();
+        WifiDisplay display = mPersistentDataStore.getRememberedWifiDisplay(address);
+        if (display != null && !Objects.equal(display.getDeviceAlias(), alias)) {
+            display = new WifiDisplay(address, display.getDeviceName(), alias);
+            if (mPersistentDataStore.rememberWifiDisplay(display)) {
+                mPersistentDataStore.saveIfNeeded();
+                updateRememberedDisplaysLocked();
+                scheduleStatusChangedBroadcastLocked();
+            }
         }
 
-        if (mActiveDisplay != null && mActiveDisplay.getDeviceAddress().equals(address)
-                && mDisplayDevice != null) {
-            mDisplayDevice.setNameLocked(mActiveDisplay.getFriendlyDisplayName());
-            sendDisplayDeviceEventLocked(mDisplayDevice, DISPLAY_DEVICE_EVENT_CHANGED);
+        if (mActiveDisplay != null && mActiveDisplay.getDeviceAddress().equals(address)) {
+            renameDisplayDeviceLocked(mActiveDisplay.getFriendlyDisplayName());
         }
     }
 
@@ -272,9 +276,42 @@
         mAvailableDisplays = mPersistentDataStore.applyWifiDisplayAliases(mAvailableDisplays);
     }
 
-    private void handleConnectLocked(WifiDisplay display,
+    private void fixRememberedDisplayNamesFromAvailableDisplaysLocked() {
+        // It may happen that a display name has changed since it was remembered.
+        // Consult the list of available displays and update the name if needed.
+        // We don't do anything special for the active display here.  The display
+        // controller will send a separate event when it needs to be updates.
+        boolean changed = false;
+        for (int i = 0; i < mRememberedDisplays.length; i++) {
+            WifiDisplay rememberedDisplay = mRememberedDisplays[i];
+            WifiDisplay availableDisplay = findAvailableDisplayLocked(
+                    rememberedDisplay.getDeviceAddress());
+            if (availableDisplay != null && !rememberedDisplay.equals(availableDisplay)) {
+                if (DEBUG) {
+                    Slog.d(TAG, "fixRememberedDisplayNamesFromAvailableDisplaysLocked: "
+                            + "updating remembered display to " + availableDisplay);
+                }
+                mRememberedDisplays[i] = availableDisplay;
+                changed |= mPersistentDataStore.rememberWifiDisplay(availableDisplay);
+            }
+        }
+        if (changed) {
+            mPersistentDataStore.saveIfNeeded();
+        }
+    }
+
+    private WifiDisplay findAvailableDisplayLocked(String address) {
+        for (WifiDisplay display : mAvailableDisplays) {
+            if (display.getDeviceAddress().equals(address)) {
+                return display;
+            }
+        }
+        return null;
+    }
+
+    private void addDisplayDeviceLocked(WifiDisplay display,
             Surface surface, int width, int height, int flags) {
-        handleDisconnectLocked();
+        removeDisplayDeviceLocked();
 
         if (mPersistentDataStore.rememberWifiDisplay(display)) {
             mPersistentDataStore.saveIfNeeded();
@@ -303,7 +340,7 @@
         scheduleUpdateNotificationLocked();
     }
 
-    private void handleDisconnectLocked() {
+    private void removeDisplayDeviceLocked() {
         if (mDisplayDevice != null) {
             mDisplayDevice.clearSurfaceLocked();
             sendDisplayDeviceEventLocked(mDisplayDevice, DISPLAY_DEVICE_EVENT_REMOVED);
@@ -313,6 +350,13 @@
         }
     }
 
+    private void renameDisplayDeviceLocked(String name) {
+        if (mDisplayDevice != null && !mDisplayDevice.getNameLocked().equals(name)) {
+            mDisplayDevice.setNameLocked(name);
+            sendDisplayDeviceEventLocked(mDisplayDevice, DISPLAY_DEVICE_EVENT_CHANGED);
+        }
+    }
+
     private void scheduleStatusChangedBroadcastLocked() {
         mCurrentStatus = null;
         if (!mPendingStatusChangeBroadcast) {
@@ -446,6 +490,7 @@
                         || !Arrays.equals(mAvailableDisplays, availableDisplays)) {
                     mScanState = WifiDisplayStatus.SCAN_STATE_NOT_SCANNING;
                     mAvailableDisplays = availableDisplays;
+                    fixRememberedDisplayNamesFromAvailableDisplaysLocked();
                     scheduleStatusChangedBroadcastLocked();
                 }
             }
@@ -483,7 +528,7 @@
                 int width, int height, int flags) {
             synchronized (getSyncRoot()) {
                 display = mPersistentDataStore.applyWifiDisplayAlias(display);
-                handleConnectLocked(display, surface, width, height, flags);
+                addDisplayDeviceLocked(display, surface, width, height, flags);
 
                 if (mActiveDisplayState != WifiDisplayStatus.DISPLAY_STATE_CONNECTED
                         || mActiveDisplay == null
@@ -496,10 +541,24 @@
         }
 
         @Override
+        public void onDisplayChanged(WifiDisplay display) {
+            synchronized (getSyncRoot()) {
+                display = mPersistentDataStore.applyWifiDisplayAlias(display);
+                if (mActiveDisplay != null
+                        && mActiveDisplay.hasSameAddress(display)
+                        && !mActiveDisplay.equals(display)) {
+                    mActiveDisplay = display;
+                    renameDisplayDeviceLocked(display.getFriendlyDisplayName());
+                    scheduleStatusChangedBroadcastLocked();
+                }
+            }
+        }
+
+        @Override
         public void onDisplayDisconnected() {
             // Stop listening.
             synchronized (getSyncRoot()) {
-                handleDisconnectLocked();
+                removeDisplayDeviceLocked();
 
                 if (mActiveDisplayState != WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED
                         || mActiveDisplay != null) {
diff --git a/services/java/com/android/server/display/WifiDisplayController.java b/services/java/com/android/server/display/WifiDisplayController.java
index 39d042f..a83675e 100644
--- a/services/java/com/android/server/display/WifiDisplayController.java
+++ b/services/java/com/android/server/display/WifiDisplayController.java
@@ -30,6 +30,7 @@
 import android.media.RemoteDisplay;
 import android.net.NetworkInfo;
 import android.net.Uri;
+import android.net.wifi.WpsInfo;
 import android.net.wifi.p2p.WifiP2pConfig;
 import android.net.wifi.p2p.WifiP2pDevice;
 import android.net.wifi.p2p.WifiP2pDeviceList;
@@ -120,6 +121,12 @@
     // or are not trying to connect.
     private WifiP2pDevice mConnectingDevice;
 
+    // The device from which we are currently disconnecting.
+    private WifiP2pDevice mDisconnectingDevice;
+
+    // The device to which we were previously trying to connect and are now canceling.
+    private WifiP2pDevice mCancelingDevice;
+
     // The device to which we are currently connected, which means we have an active P2P group.
     private WifiP2pDevice mConnectedDevice;
 
@@ -186,6 +193,7 @@
         updateWfdEnableState();
     }
 
+    @Override
     public void dump(PrintWriter pw) {
         pw.println("mWifiDisplayOnSetting=" + mWifiDisplayOnSetting);
         pw.println("mWifiP2pEnabled=" + mWifiP2pEnabled);
@@ -196,6 +204,8 @@
         pw.println("mDiscoverPeersRetriesLeft=" + mDiscoverPeersRetriesLeft);
         pw.println("mDesiredDevice=" + describeWifiP2pDevice(mDesiredDevice));
         pw.println("mConnectingDisplay=" + describeWifiP2pDevice(mConnectingDevice));
+        pw.println("mDisconnectingDisplay=" + describeWifiP2pDevice(mDisconnectingDevice));
+        pw.println("mCancelingDisplay=" + describeWifiP2pDevice(mCancelingDevice));
         pw.println("mConnectedDevice=" + describeWifiP2pDevice(mConnectedDevice));
         pw.println("mConnectionRetriesLeft=" + mConnectionRetriesLeft);
         pw.println("mRemoteDisplay=" + mRemoteDisplay);
@@ -384,7 +394,9 @@
         final int count = mAvailableWifiDisplayPeers.size();
         final WifiDisplay[] displays = WifiDisplay.CREATOR.newArray(count);
         for (int i = 0; i < count; i++) {
-            displays[i] = createWifiDisplay(mAvailableWifiDisplayPeers.get(i));
+            WifiP2pDevice device = mAvailableWifiDisplayPeers.get(i);
+            displays[i] = createWifiDisplay(device);
+            updateDesiredDevice(device);
         }
 
         mHandler.post(new Runnable() {
@@ -395,6 +407,23 @@
         });
     }
 
+    private void updateDesiredDevice(WifiP2pDevice device) {
+        // Handle the case where the device to which we are connecting or connected
+        // may have been renamed or reported different properties in the latest scan.
+        final String address = device.deviceAddress;
+        if (mDesiredDevice != null && mDesiredDevice.deviceAddress.equals(address)) {
+            if (DEBUG) {
+                Slog.d(TAG, "updateDesiredDevice: new information "
+                        + describeWifiP2pDevice(device));
+            }
+            mDesiredDevice.update(device);
+            if (mAdvertisedDisplay != null
+                    && mAdvertisedDisplay.getDeviceAddress().equals(address)) {
+                readvertiseDisplay(createWifiDisplay(mDesiredDevice));
+            }
+        }
+    }
+
     private void connect(final WifiP2pDevice device) {
         if (mDesiredDevice != null
                 && !mDesiredDevice.deviceAddress.equals(device.deviceAddress)) {
@@ -459,12 +488,17 @@
         }
 
         // Step 2. Before we try to connect to a new device, disconnect from the old one.
+        if (mDisconnectingDevice != null) {
+            return; // wait for asynchronous callback
+        }
         if (mConnectedDevice != null && mConnectedDevice != mDesiredDevice) {
             Slog.i(TAG, "Disconnecting from Wifi display: " + mConnectedDevice.deviceName);
+            mDisconnectingDevice = mConnectedDevice;
+            mConnectedDevice = null;
 
             unadvertiseDisplay();
 
-            final WifiP2pDevice oldDevice = mConnectedDevice;
+            final WifiP2pDevice oldDevice = mDisconnectingDevice;
             mWifiP2pManager.removeGroup(mWifiP2pChannel, new ActionListener() {
                 @Override
                 public void onSuccess() {
@@ -480,8 +514,8 @@
                 }
 
                 private void next() {
-                    if (mConnectedDevice == oldDevice) {
-                        mConnectedDevice = null;
+                    if (mDisconnectingDevice == oldDevice) {
+                        mDisconnectingDevice = null;
                         updateConnection();
                     }
                 }
@@ -491,13 +525,18 @@
 
         // Step 3. Before we try to connect to a new device, stop trying to connect
         // to the old one.
+        if (mCancelingDevice != null) {
+            return; // wait for asynchronous callback
+        }
         if (mConnectingDevice != null && mConnectingDevice != mDesiredDevice) {
             Slog.i(TAG, "Canceling connection to Wifi display: " + mConnectingDevice.deviceName);
+            mCancelingDevice = mConnectingDevice;
+            mConnectingDevice = null;
 
             unadvertiseDisplay();
             mHandler.removeCallbacks(mConnectionTimeout);
 
-            final WifiP2pDevice oldDevice = mConnectingDevice;
+            final WifiP2pDevice oldDevice = mCancelingDevice;
             mWifiP2pManager.cancelConnect(mWifiP2pChannel, new ActionListener() {
                 @Override
                 public void onSuccess() {
@@ -513,8 +552,8 @@
                 }
 
                 private void next() {
-                    if (mConnectingDevice == oldDevice) {
-                        mConnectingDevice = null;
+                    if (mCancelingDevice == oldDevice) {
+                        mCancelingDevice = null;
                         updateConnection();
                     }
                 }
@@ -534,6 +573,16 @@
 
             mConnectingDevice = mDesiredDevice;
             WifiP2pConfig config = new WifiP2pConfig();
+            WpsInfo wps = new WpsInfo();
+            if (mConnectingDevice.wpsPbcSupported()) {
+                wps.setup = WpsInfo.PBC;
+            } else if (mConnectingDevice.wpsDisplaySupported()) {
+                // We do keypad if peer does display
+                wps.setup = WpsInfo.KEYPAD;
+            } else {
+                wps.setup = WpsInfo.DISPLAY;
+            }
+            config.wps = wps;
             config.deviceAddress = mConnectingDevice.deviceAddress;
             // Helps with STA & P2P concurrency
             config.groupOwnerIntent = WifiP2pConfig.MIN_GROUP_OWNER_INTENT;
@@ -763,13 +812,17 @@
                 public void run() {
                     if (oldSurface != null && surface != oldSurface) {
                         mListener.onDisplayDisconnected();
-                    } else if (oldDisplay != null && !Objects.equal(display, oldDisplay)) {
+                    } else if (oldDisplay != null && !oldDisplay.hasSameAddress(display)) {
                         mListener.onDisplayConnectionFailed();
                     }
 
                     if (display != null) {
-                        if (!Objects.equal(display, oldDisplay)) {
+                        if (!display.hasSameAddress(oldDisplay)) {
                             mListener.onDisplayConnecting(display);
+                        } else if (!display.equals(oldDisplay)) {
+                            // The address is the same but some other property such as the
+                            // name must have changed.
+                            mListener.onDisplayChanged(display);
                         }
                         if (surface != null && surface != oldSurface) {
                             mListener.onDisplayConnected(display, surface, width, height, flags);
@@ -784,6 +837,12 @@
         advertiseDisplay(null, null, 0, 0, 0);
     }
 
+    private void readvertiseDisplay(WifiDisplay display) {
+        advertiseDisplay(display, mAdvertisedDisplaySurface,
+                mAdvertisedDisplayWidth, mAdvertisedDisplayHeight,
+                mAdvertisedDisplayFlags);
+    }
+
     private static Inet4Address getInterfaceAddress(WifiP2pGroup info) {
         NetworkInterface iface;
         try {
@@ -885,6 +944,7 @@
 
         void onDisplayConnecting(WifiDisplay display);
         void onDisplayConnectionFailed();
+        void onDisplayChanged(WifiDisplay display);
         void onDisplayConnected(WifiDisplay display,
                 Surface surface, int width, int height, int flags);
         void onDisplayDisconnected();
diff --git a/services/java/com/android/server/dreams/DreamController.java b/services/java/com/android/server/dreams/DreamController.java
index 1ab6a77..45ae2c5 100644
--- a/services/java/com/android/server/dreams/DreamController.java
+++ b/services/java/com/android/server/dreams/DreamController.java
@@ -44,6 +44,9 @@
 final class DreamController {
     private static final String TAG = "DreamController";
 
+    // How long we wait for a newly bound dream to create the service connection
+    private static final int DREAM_CONNECTION_TIMEOUT = 5 * 1000;
+
     private final Context mContext;
     private final Handler mHandler;
     private final Listener mListener;
@@ -58,6 +61,16 @@
 
     private DreamRecord mCurrentDream;
 
+    private final Runnable mStopUnconnectedDreamRunnable = new Runnable() {
+        @Override
+        public void run() {
+            if (mCurrentDream != null && mCurrentDream.mBound && !mCurrentDream.mConnected) {
+                Slog.w(TAG, "Bound dream did not connect in the time allotted");
+                stopDream();
+            }
+        }
+    };
+
     public DreamController(Context context, Handler handler, Listener listener) {
         mContext = context;
         mHandler = handler;
@@ -116,6 +129,7 @@
         }
 
         mCurrentDream.mBound = true;
+        mHandler.postDelayed(mStopUnconnectedDreamRunnable, DREAM_CONNECTION_TIMEOUT);
     }
 
     public void stopDream() {
@@ -128,6 +142,8 @@
         Slog.i(TAG, "Stopping dream: name=" + oldDream.mName
                 + ", isTest=" + oldDream.mIsTest + ", userId=" + oldDream.mUserId);
 
+        mHandler.removeCallbacks(mStopUnconnectedDreamRunnable);
+
         if (oldDream.mSentStartBroadcast) {
             mContext.sendBroadcastAsUser(mDreamingStoppedIntent, UserHandle.ALL);
         }
@@ -200,6 +216,7 @@
         public final int mUserId;
 
         public boolean mBound;
+        public boolean mConnected;
         public IDreamService mService;
         public boolean mSentStartBroadcast;
 
@@ -231,6 +248,7 @@
             mHandler.post(new Runnable() {
                 @Override
                 public void run() {
+                    mConnected = true;
                     if (mCurrentDream == DreamRecord.this && mService == null) {
                         attach(IDreamService.Stub.asInterface(service));
                     }
diff --git a/services/java/com/android/server/dreams/DreamManagerService.java b/services/java/com/android/server/dreams/DreamManagerService.java
index 1f40176..c9e0da5 100644
--- a/services/java/com/android/server/dreams/DreamManagerService.java
+++ b/services/java/com/android/server/dreams/DreamManagerService.java
@@ -25,6 +25,7 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
 import android.os.Binder;
 import android.os.Handler;
 import android.os.IBinder;
@@ -38,6 +39,8 @@
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
 
 import libcore.util.Objects;
 
@@ -47,7 +50,7 @@
  * @hide
  */
 public final class DreamManagerService extends IDreamManager.Stub {
-    private static final boolean DEBUG = true;
+    private static final boolean DEBUG = false;
     private static final String TAG = "DreamManagerService";
 
     private final Object mLock = new Object();
@@ -279,7 +282,37 @@
         String names = Settings.Secure.getStringForUser(mContext.getContentResolver(),
                 Settings.Secure.SCREENSAVER_COMPONENTS,
                 userId);
-        return names == null ? null : componentsFromString(names);
+        ComponentName[] components = componentsFromString(names);
+
+        // first, ensure components point to valid services
+        List<ComponentName> validComponents = new ArrayList<ComponentName>();
+        if (components != null) {
+            for (ComponentName component : components) {
+                if (serviceExists(component)) {
+                    validComponents.add(component);
+                } else {
+                    Slog.w(TAG, "Dream " + component + " does not exist");
+                }
+            }
+        }
+
+        // fallback to the default dream component if necessary
+        if (validComponents.isEmpty()) {
+            ComponentName defaultDream = getDefaultDreamComponent();
+            if (defaultDream != null) {
+                Slog.w(TAG, "Falling back to default dream " + defaultDream);
+                validComponents.add(defaultDream);
+            }
+        }
+        return validComponents.toArray(new ComponentName[validComponents.size()]);
+    }
+
+    private boolean serviceExists(ComponentName name) {
+        try {
+            return name != null && mContext.getPackageManager().getServiceInfo(name, 0) != null;
+        } catch (NameNotFoundException e) {
+            return false;
+        }
     }
 
     private void startDreamLocked(final ComponentName name,
@@ -292,7 +325,7 @@
 
         stopDreamLocked();
 
-        Slog.i(TAG, "Entering dreamland.");
+        if (DEBUG) Slog.i(TAG, "Entering dreamland.");
 
         final Binder newToken = new Binder();
         mCurrentDreamToken = newToken;
@@ -310,7 +343,7 @@
 
     private void stopDreamLocked() {
         if (mCurrentDreamToken != null) {
-            Slog.i(TAG, "Leaving dreamland.");
+            if (DEBUG) Slog.i(TAG, "Leaving dreamland.");
 
             cleanupDreamLocked();
 
@@ -352,6 +385,9 @@
     }
 
     private static ComponentName[] componentsFromString(String names) {
+        if (names == null) {
+            return null;
+        }
         String[] namesArray = names.split(",");
         ComponentName[] componentNames = new ComponentName[namesArray.length];
         for (int i = 0; i < namesArray.length; i++) {
diff --git a/services/java/com/android/server/net/NetworkPolicyManagerService.java b/services/java/com/android/server/net/NetworkPolicyManagerService.java
index 43ddf8d..b839331 100644
--- a/services/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -131,6 +131,7 @@
 import android.util.Xml;
 
 import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.Objects;
@@ -184,9 +185,11 @@
     private static final int VERSION_SWITCH_UID = 10;
     private static final int VERSION_LATEST = VERSION_SWITCH_UID;
 
-    // @VisibleForTesting
+    @VisibleForTesting
     public static final int TYPE_WARNING = 0x1;
+    @VisibleForTesting
     public static final int TYPE_LIMIT = 0x2;
+    @VisibleForTesting
     public static final int TYPE_LIMIT_SNOOZED = 0x3;
 
     private static final String TAG_POLICY_LIST = "policy-list";
@@ -214,10 +217,9 @@
 
     private static final String TAG_ALLOW_BACKGROUND = TAG + ":allowBackground";
 
-    // @VisibleForTesting
-    public static final String ACTION_ALLOW_BACKGROUND =
+    private static final String ACTION_ALLOW_BACKGROUND =
             "com.android.server.net.action.ALLOW_BACKGROUND";
-    public static final String ACTION_SNOOZE_WARNING =
+    private static final String ACTION_SNOOZE_WARNING =
             "com.android.server.net.action.SNOOZE_WARNING";
 
     private static final long TIME_CACHE_MAX_AGE = DAY_IN_MILLIS;
@@ -2063,7 +2065,7 @@
         return intent;
     }
 
-    // @VisibleForTesting
+    @VisibleForTesting
     public void addIdleHandler(IdleHandler handler) {
         mHandler.getLooper().getQueue().addIdleHandler(handler);
     }
diff --git a/services/java/com/android/server/net/NetworkStatsService.java b/services/java/com/android/server/net/NetworkStatsService.java
index 0efdead..546f2be 100644
--- a/services/java/com/android/server/net/NetworkStatsService.java
+++ b/services/java/com/android/server/net/NetworkStatsService.java
@@ -115,6 +115,7 @@
 import android.util.SparseIntArray;
 import android.util.TrustedTime;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.FileRotator;
 import com.android.internal.util.IndentingPrintWriter;
@@ -165,7 +166,7 @@
 
     private IConnectivityManager mConnManager;
 
-    // @VisibleForTesting
+    @VisibleForTesting
     public static final String ACTION_NETWORK_STATS_POLL =
             "com.android.server.action.NETWORK_STATS_POLL";
     public static final String ACTION_NETWORK_STATS_UPDATED =
@@ -902,7 +903,7 @@
                 ident.add(NetworkIdentity.buildNetworkIdentity(mContext, state));
 
                 // remember any ifaces associated with mobile networks
-                if (isNetworkTypeMobile(state.networkInfo.getType())) {
+                if (isNetworkTypeMobile(state.networkInfo.getType()) && iface != null) {
                     if (!contains(mMobileIfaces, iface)) {
                         mMobileIfaces = appendElement(String.class, mMobileIfaces, iface);
                     }
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index 83672c5..2238f17 100644
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -1020,7 +1020,8 @@
 
             readPermissions();
 
-            mRestoredSettings = mSettings.readLPw(sUserManager.getUsers(false));
+            mRestoredSettings = mSettings.readLPw(sUserManager.getUsers(false),
+                    mSdkVersion, mOnlyCore);
             long startTime = SystemClock.uptimeMillis();
 
             EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,
@@ -1320,6 +1321,10 @@
         return !mRestoredSettings;
     }
 
+    public boolean isOnlyCoreApps() {
+        return mOnlyCore;
+    }
+
     private String getRequiredVerifierLPr() {
         final Intent verification = new Intent(Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
         final List<ResolveInfo> receivers = queryIntentReceivers(verification, PACKAGE_MIME_TYPE,
@@ -4113,7 +4118,7 @@
                         }
                     }
 
-                    Slog.i(TAG, "Linking native library dir for " + path);
+                    if (DEBUG_INSTALL) Slog.i(TAG, "Linking native library dir for " + path);
                     final int[] userIds = sUserManager.getUserIds();
                     synchronized (mInstallLock) {
                         for (int userId : userIds) {
@@ -6301,20 +6306,21 @@
 
                     final File packageFile;
                     if (encryptionParams != null || !"file".equals(mPackageURI.getScheme())) {
-                        ParcelFileDescriptor out = null;
-
                         mTempPackage = createTempPackageFile(mDrmAppPrivateInstallDir);
                         if (mTempPackage != null) {
+                            ParcelFileDescriptor out;
                             try {
                                 out = ParcelFileDescriptor.open(mTempPackage,
                                         ParcelFileDescriptor.MODE_READ_WRITE);
                             } catch (FileNotFoundException e) {
+                                out = null;
                                 Slog.e(TAG, "Failed to create temporary file for : " + mPackageURI);
                             }
 
                             // Make a temporary file for decryption.
                             ret = mContainerService
                                     .copyResource(mPackageURI, encryptionParams, out);
+                            IoUtils.closeQuietly(out);
 
                             packageFile = mTempPackage;
 
@@ -6347,6 +6353,18 @@
                                 pkgLite = mContainerService.getMinimalPackageInfo(packageFilePath,
                                         flags, lowThreshold);
                             }
+                            /*
+                             * The cache free must have deleted the file we
+                             * downloaded to install.
+                             *
+                             * TODO: fix the "freeCache" call to not delete
+                             *       the file we care about.
+                             */
+                            if (pkgLite.recommendedInstallLocation
+                                    == PackageHelper.RECOMMEND_FAILED_INVALID_URI) {
+                                pkgLite.recommendedInstallLocation
+                                    = PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE;
+                            }
                         }
                     }
                 } finally {
@@ -9079,10 +9097,8 @@
                 if (removed.size() > 0) {
                     for (int j=0; j<removed.size(); j++) {
                         PreferredActivity pa = removed.get(i);
-                        RuntimeException here = new RuntimeException("here");
-                        here.fillInStackTrace();
                         Slog.w(TAG, "Removing dangling preferred activity: "
-                                + pa.mPref.mComponent, here);
+                                + pa.mPref.mComponent);
                         pir.removeFilter(pa);
                     }
                     mSettings.writePackageRestrictionsLPr(
diff --git a/services/java/com/android/server/pm/Settings.java b/services/java/com/android/server/pm/Settings.java
index 94494ae..06f11bc 100644
--- a/services/java/com/android/server/pm/Settings.java
+++ b/services/java/com/android/server/pm/Settings.java
@@ -1556,7 +1556,7 @@
         }
     }
 
-    boolean readLPw(List<UserInfo> users) {
+    boolean readLPw(List<UserInfo> users, int sdkVersion, boolean onlyCore) {
         FileInputStream str = null;
         if (mBackupSettingsFilename.exists()) {
             try {
@@ -1586,7 +1586,10 @@
                     mReadMessages.append("No settings file found\n");
                     PackageManagerService.reportSettingsProblem(Log.INFO,
                             "No settings file; creating initial state");
-                    readDefaultPreferredAppsLPw(0);
+                    if (!onlyCore) {
+                        readDefaultPreferredAppsLPw(0);
+                    }
+                    mInternalSdkPlatform = mExternalSdkPlatform = sdkVersion;
                     return false;
                 }
                 str = new FileInputStream(mSettingsFilename);
diff --git a/services/java/com/android/server/pm/UserManagerService.java b/services/java/com/android/server/pm/UserManagerService.java
index e05442b..dbfe34d 100644
--- a/services/java/com/android/server/pm/UserManagerService.java
+++ b/services/java/com/android/server/pm/UserManagerService.java
@@ -16,8 +16,7 @@
 
 package com.android.server.pm;
 
-import com.android.internal.util.ArrayUtils;
-import com.android.internal.util.FastXmlSerializer;
+import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
 
 import android.app.Activity;
 import android.app.ActivityManager;
@@ -26,7 +25,6 @@
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
-import android.content.SharedPreferences;
 import android.content.pm.PackageManager;
 import android.content.pm.UserInfo;
 import android.graphics.Bitmap;
@@ -34,6 +32,7 @@
 import android.os.Binder;
 import android.os.Environment;
 import android.os.FileUtils;
+import android.os.Handler;
 import android.os.IUserManager;
 import android.os.Process;
 import android.os.RemoteException;
@@ -42,9 +41,17 @@
 import android.util.AtomicFile;
 import android.util.Slog;
 import android.util.SparseArray;
+import android.util.SparseBooleanArray;
 import android.util.TimeUtils;
 import android.util.Xml;
 
+import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.FastXmlSerializer;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
 import java.io.BufferedOutputStream;
 import java.io.File;
 import java.io.FileDescriptor;
@@ -54,13 +61,8 @@
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.util.ArrayList;
-import java.util.HashSet;
 import java.util.List;
 
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-import org.xmlpull.v1.XmlSerializer;
-
 public class UserManagerService extends IUserManager.Stub {
 
     private static final String LOG_TAG = "UserManagerService";
@@ -86,7 +88,7 @@
 
     private static final int MIN_USER_ID = 10;
 
-    private static final int USER_VERSION = 1;
+    private static final int USER_VERSION = 2;
 
     private static final long EPOCH_PLUS_30_YEARS = 30L * 365 * 24 * 60 * 60 * 1000L; // ms
 
@@ -95,19 +97,24 @@
     private final Object mInstallLock;
     private final Object mPackagesLock;
 
+    private final Handler mHandler;
+
     private final File mUsersDir;
     private final File mUserListFile;
     private final File mBaseUserPath;
 
-    private SparseArray<UserInfo> mUsers = new SparseArray<UserInfo>();
-    private HashSet<Integer> mRemovingUserIds = new HashSet<Integer>();
+    private final SparseArray<UserInfo> mUsers = new SparseArray<UserInfo>();
+
+    /**
+     * Set of user IDs being actively removed. Removed IDs linger in this set
+     * for several seconds to work around a VFS caching issue.
+     */
+    // @GuardedBy("mPackagesLock")
+    private final SparseBooleanArray mRemovingUserIds = new SparseBooleanArray();
 
     private int[] mUserIds;
     private boolean mGuestEnabled;
     private int mNextSerialNumber;
-    // This resets on a reboot. Otherwise it keeps incrementing so that user ids are
-    // not reused in quick succession
-    private int mNextUserId = MIN_USER_ID;
     private int mUserVersion = 0;
 
     private static UserManagerService sInstance;
@@ -147,6 +154,7 @@
         mPm = pm;
         mInstallLock = installLock;
         mPackagesLock = packagesLock;
+        mHandler = new Handler();
         synchronized (mInstallLock) {
             synchronized (mPackagesLock) {
                 mUsersDir = new File(dataDir, USER_INFO_DIR);
@@ -190,7 +198,7 @@
                 if (ui.partial) {
                     continue;
                 }
-                if (!excludeDying || !mRemovingUserIds.contains(ui.id)) {
+                if (!excludeDying || !mRemovingUserIds.get(ui.id)) {
                     users.add(ui);
                 }
             }
@@ -212,7 +220,7 @@
     private UserInfo getUserInfoLocked(int userId) {
         UserInfo ui = mUsers.get(userId);
         // If it is partial and not in the process of being removed, return as unknown user.
-        if (ui != null && ui.partial && !mRemovingUserIds.contains(userId)) {
+        if (ui != null && ui.partial && !mRemovingUserIds.get(userId)) {
             Slog.w(LOG_TAG, "getUserInfo: unknown user #" + userId);
             return null;
         }
@@ -476,8 +484,7 @@
     }
 
     /**
-     * This fixes an incorrect initialization of user name for the owner.
-     * TODO: Remove in the next release.
+     * Upgrade steps between versions, either for fixing bugs or changing the data format.
      */
     private void upgradeIfNecessary() {
         int userVersion = mUserVersion;
@@ -491,6 +498,16 @@
             userVersion = 1;
         }
 
+        if (userVersion < 2) {
+            // Owner should be marked as initialized
+            UserInfo user = mUsers.get(UserHandle.USER_OWNER);
+            if ((user.flags & UserInfo.FLAG_INITIALIZED) == 0) {
+                user.flags |= UserInfo.FLAG_INITIALIZED;
+                writeUserLocked(user);
+            }
+            userVersion = 2;
+        }
+
         if (userVersion < USER_VERSION) {
             Slog.w(LOG_TAG, "User version " + mUserVersion + " didn't upgrade as expected to "
                     + USER_VERSION);
@@ -502,7 +519,7 @@
 
     private void fallbackToSingleUserLocked() {
         // Create the primary user
-        UserInfo primary = new UserInfo(0, 
+        UserInfo primary = new UserInfo(0,
                 mContext.getResources().getString(com.android.internal.R.string.owner_name), null,
                 UserInfo.FLAG_ADMIN | UserInfo.FLAG_PRIMARY | UserInfo.FLAG_INITIALIZED);
         mUsers.put(0, primary);
@@ -749,7 +766,7 @@
             if (userHandle == 0 || user == null) {
                 return false;
             }
-            mRemovingUserIds.add(userHandle);
+            mRemovingUserIds.put(userHandle, true);
             // Set this to a partially created user, so that the user will be purged
             // on next startup, in case the runtime stops now before stopping and
             // removing the user completely.
@@ -813,13 +830,25 @@
         }
     }
 
-    private void removeUserStateLocked(int userHandle) {
+    private void removeUserStateLocked(final int userHandle) {
         // Cleanup package manager settings
         mPm.cleanUpUserLILPw(userHandle);
 
         // Remove this user from the list
         mUsers.remove(userHandle);
-        mRemovingUserIds.remove(userHandle);
+
+        // Have user ID linger for several seconds to let external storage VFS
+        // cache entries expire. This must be greater than the 'entry_valid'
+        // timeout used by the FUSE daemon.
+        mHandler.postDelayed(new Runnable() {
+            @Override
+            public void run() {
+                synchronized (mPackagesLock) {
+                    mRemovingUserIds.delete(userHandle);
+                }
+            }
+        }, MINUTE_IN_MILLIS);
+
         // Remove user file
         AtomicFile userFile = new AtomicFile(new File(mUsersDir, userHandle + ".xml"));
         userFile.delete();
@@ -906,14 +935,13 @@
      */
     private int getNextAvailableIdLocked() {
         synchronized (mPackagesLock) {
-            int i = mNextUserId;
+            int i = MIN_USER_ID;
             while (i < Integer.MAX_VALUE) {
-                if (mUsers.indexOfKey(i) < 0 && !mRemovingUserIds.contains(i)) {
+                if (mUsers.indexOfKey(i) < 0 && !mRemovingUserIds.get(i)) {
                     break;
                 }
                 i++;
             }
-            mNextUserId = i + 1;
             return i;
         }
     }
@@ -938,7 +966,7 @@
                 UserInfo user = mUsers.valueAt(i);
                 if (user == null) continue;
                 pw.print("  "); pw.print(user); pw.print(" serialNo="); pw.print(user.serialNumber);
-                if (mRemovingUserIds.contains(mUsers.keyAt(i))) pw.print(" <removing> ");
+                if (mRemovingUserIds.get(mUsers.keyAt(i))) pw.print(" <removing> ");
                 if (user.partial) pw.print(" <partial>");
                 pw.println();
                 pw.print("    Created: ");
diff --git a/services/java/com/android/server/power/DisplayPowerController.java b/services/java/com/android/server/power/DisplayPowerController.java
index 317fec0..b5010f2 100644
--- a/services/java/com/android/server/power/DisplayPowerController.java
+++ b/services/java/com/android/server/power/DisplayPowerController.java
@@ -19,6 +19,7 @@
 import com.android.server.LightsService;
 import com.android.server.TwilightService;
 import com.android.server.TwilightService.TwilightState;
+import com.android.server.display.DisplayManagerService;
 
 import android.animation.Animator;
 import android.animation.ObjectAnimator;
@@ -29,7 +30,6 @@
 import android.hardware.SensorEventListener;
 import android.hardware.SensorManager;
 import android.hardware.SystemSensorManager;
-import android.hardware.display.DisplayManager;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
@@ -40,7 +40,6 @@
 import android.util.Slog;
 import android.util.Spline;
 import android.util.TimeUtils;
-import android.view.Display;
 
 import java.io.PrintWriter;
 
@@ -183,7 +182,7 @@
     private final TwilightService mTwilight;
 
     // The display manager.
-    private final DisplayManager mDisplayManager;
+    private final DisplayManagerService mDisplayManager;
 
     // The sensor manager.
     private final SensorManager mSensorManager;
@@ -345,7 +344,8 @@
      * Creates the display power controller.
      */
     public DisplayPowerController(Looper looper, Context context, Notifier notifier,
-            LightsService lights, TwilightService twilight,
+            LightsService lights, TwilightService twilight, SensorManager sensorManager,
+            DisplayManagerService displayManager,
             DisplayBlanker displayBlanker,
             Callbacks callbacks, Handler callbackHandler) {
         mHandler = new DisplayControllerHandler(looper);
@@ -356,8 +356,8 @@
 
         mLights = lights;
         mTwilight = twilight;
-        mSensorManager = new SystemSensorManager(mHandler.getLooper());
-        mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
+        mSensorManager = sensorManager;
+        mDisplayManager = displayManager;
 
         final Resources resources = context.getResources();
 
@@ -518,9 +518,8 @@
     }
 
     private void initialize() {
-        Display display = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY);
         mPowerState = new DisplayPowerState(
-                new ElectronBeam(display), mDisplayBlanker,
+                new ElectronBeam(mDisplayManager), mDisplayBlanker,
                 mLights.getLight(LightsService.LIGHT_ID_BACKLIGHT));
 
         mElectronBeamOnAnimator = ObjectAnimator.ofFloat(
diff --git a/services/java/com/android/server/power/ElectronBeam.java b/services/java/com/android/server/power/ElectronBeam.java
index 9a53648..8e19e11 100644
--- a/services/java/com/android/server/power/ElectronBeam.java
+++ b/services/java/com/android/server/power/ElectronBeam.java
@@ -16,6 +16,9 @@
 
 package com.android.server.power;
 
+import com.android.server.display.DisplayManagerService;
+import com.android.server.display.DisplayTransactionListener;
+
 import android.graphics.Bitmap;
 import android.graphics.PixelFormat;
 import android.opengl.EGL14;
@@ -72,14 +75,13 @@
     private boolean mPrepared;
     private int mMode;
 
-    private final Display mDisplay;
-    private final DisplayInfo mDisplayInfo = new DisplayInfo();
+    private final DisplayManagerService mDisplayManager;
     private int mDisplayLayerStack; // layer stack associated with primary display
-    private int mDisplayRotation;
     private int mDisplayWidth;      // real width, not rotated
     private int mDisplayHeight;     // real height, not rotated
     private SurfaceSession mSurfaceSession;
     private Surface mSurface;
+    private NaturalSurfaceLayout mSurfaceLayout;
     private EGLDisplay mEglDisplay;
     private EGLConfig mEglConfig;
     private EGLContext mEglContext;
@@ -111,8 +113,8 @@
      */
     public static final int MODE_FADE = 2;
 
-    public ElectronBeam(Display display) {
-        mDisplay = display;
+    public ElectronBeam(DisplayManagerService displayManager) {
+        mDisplayManager = displayManager;
     }
 
     /**
@@ -129,18 +131,12 @@
 
         mMode = mode;
 
-        // Get the display size and adjust it for rotation.
-        mDisplay.getDisplayInfo(mDisplayInfo);
-        mDisplayLayerStack = mDisplay.getLayerStack();
-        mDisplayRotation = mDisplayInfo.rotation;
-        if (mDisplayRotation == Surface.ROTATION_90
-                || mDisplayRotation == Surface.ROTATION_270) {
-            mDisplayWidth = mDisplayInfo.logicalHeight;
-            mDisplayHeight = mDisplayInfo.logicalWidth;
-        } else {
-            mDisplayWidth = mDisplayInfo.logicalWidth;
-            mDisplayHeight = mDisplayInfo.logicalHeight;
-        }
+        // Get the display size and layer stack.
+        // This is not expected to change while the electron beam surface is showing.
+        DisplayInfo displayInfo = mDisplayManager.getDisplayInfo(Display.DEFAULT_DISPLAY);
+        mDisplayLayerStack = displayInfo.layerStack;
+        mDisplayWidth = displayInfo.getNaturalWidth();
+        mDisplayHeight = displayInfo.getNaturalHeight();
 
         // Prepare the surface for drawing.
         if (!tryPrepare()) {
@@ -551,24 +547,8 @@
             mSurface.setLayerStack(mDisplayLayerStack);
             mSurface.setSize(mDisplayWidth, mDisplayHeight);
 
-            switch (mDisplayRotation) {
-                case Surface.ROTATION_0:
-                    mSurface.setPosition(0, 0);
-                    mSurface.setMatrix(1, 0, 0, 1);
-                    break;
-                case Surface.ROTATION_90:
-                    mSurface.setPosition(0, mDisplayWidth);
-                    mSurface.setMatrix(0, -1, 1, 0);
-                    break;
-                case Surface.ROTATION_180:
-                    mSurface.setPosition(mDisplayWidth, mDisplayHeight);
-                    mSurface.setMatrix(-1, 0, 0, -1);
-                    break;
-                case Surface.ROTATION_270:
-                    mSurface.setPosition(mDisplayHeight, 0);
-                    mSurface.setMatrix(0, 1, -1, 0);
-                    break;
-            }
+            mSurfaceLayout = new NaturalSurfaceLayout(mDisplayManager, mSurface);
+            mSurfaceLayout.onDisplayTransaction();
         } finally {
             Surface.closeTransaction();
         }
@@ -601,6 +581,8 @@
 
     private void destroySurface() {
         if (mSurface != null) {
+            mSurfaceLayout.dispose();
+            mSurfaceLayout = null;
             Surface.openTransaction();
             try {
                 mSurface.destroy();
@@ -711,10 +693,63 @@
         pw.println("  mPrepared=" + mPrepared);
         pw.println("  mMode=" + mMode);
         pw.println("  mDisplayLayerStack=" + mDisplayLayerStack);
-        pw.println("  mDisplayRotation=" + mDisplayRotation);
         pw.println("  mDisplayWidth=" + mDisplayWidth);
         pw.println("  mDisplayHeight=" + mDisplayHeight);
         pw.println("  mSurfaceVisible=" + mSurfaceVisible);
         pw.println("  mSurfaceAlpha=" + mSurfaceAlpha);
     }
+
+    /**
+     * Keeps a surface aligned with the natural orientation of the device.
+     * Updates the position and transformation of the matrix whenever the display
+     * is rotated.  This is a little tricky because the display transaction
+     * callback can be invoked on any thread, not necessarily the thread that
+     * owns the electron beam.
+     */
+    private static final class NaturalSurfaceLayout implements DisplayTransactionListener {
+        private final DisplayManagerService mDisplayManager;
+        private Surface mSurface;
+
+        public NaturalSurfaceLayout(DisplayManagerService displayManager, Surface surface) {
+            mDisplayManager = displayManager;
+            mSurface = surface;
+            mDisplayManager.registerDisplayTransactionListener(this);
+        }
+
+        public void dispose() {
+            synchronized (this) {
+                mSurface = null;
+            }
+            mDisplayManager.unregisterDisplayTransactionListener(this);
+        }
+
+        @Override
+        public void onDisplayTransaction() {
+            synchronized (this) {
+                if (mSurface == null) {
+                    return;
+                }
+
+                DisplayInfo displayInfo = mDisplayManager.getDisplayInfo(Display.DEFAULT_DISPLAY);
+                switch (displayInfo.rotation) {
+                    case Surface.ROTATION_0:
+                        mSurface.setPosition(0, 0);
+                        mSurface.setMatrix(1, 0, 0, 1);
+                        break;
+                    case Surface.ROTATION_90:
+                        mSurface.setPosition(0, displayInfo.logicalHeight);
+                        mSurface.setMatrix(0, -1, 1, 0);
+                        break;
+                    case Surface.ROTATION_180:
+                        mSurface.setPosition(displayInfo.logicalWidth, displayInfo.logicalHeight);
+                        mSurface.setMatrix(-1, 0, 0, -1);
+                        break;
+                    case Surface.ROTATION_270:
+                        mSurface.setPosition(displayInfo.logicalWidth, 0);
+                        mSurface.setMatrix(0, 1, -1, 0);
+                        break;
+                }
+            }
+        }
+    }
 }
diff --git a/services/java/com/android/server/power/Notifier.java b/services/java/com/android/server/power/Notifier.java
index 5e056934..d99d523 100644
--- a/services/java/com/android/server/power/Notifier.java
+++ b/services/java/com/android/server/power/Notifier.java
@@ -23,6 +23,10 @@
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
+import android.media.AudioManager;
+import android.media.Ringtone;
+import android.media.RingtoneManager;
+import android.net.Uri;
 import android.os.BatteryStats;
 import android.os.Handler;
 import android.os.Looper;
@@ -32,6 +36,7 @@
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.os.WorkSource;
+import android.provider.Settings;
 import android.util.EventLog;
 import android.util.Slog;
 import android.view.WindowManagerPolicy;
@@ -64,6 +69,7 @@
 
     private static final int MSG_USER_ACTIVITY = 1;
     private static final int MSG_BROADCAST = 2;
+    private static final int MSG_WIRELESS_CHARGING_STARTED = 3;
 
     private final Object mLock = new Object();
 
@@ -312,6 +318,20 @@
         }
     }
 
+    /**
+     * Called when wireless charging has started so as to provide user feedback.
+     */
+    public void onWirelessChargingStarted() {
+        if (DEBUG) {
+            Slog.d(TAG, "onWirelessChargingStarted");
+        }
+
+        mSuspendBlocker.acquire();
+        Message msg = mHandler.obtainMessage(MSG_WIRELESS_CHARGING_STARTED);
+        msg.setAsynchronous(true);
+        mHandler.sendMessage(msg);
+    }
+
     private void updatePendingBroadcastLocked() {
         if (!mBroadcastInProgress
                 && mActualPowerState != POWER_STATE_UNKNOWN
@@ -473,6 +493,23 @@
         }
     };
 
+    private void playWirelessChargingStartedSound() {
+        final String soundPath = Settings.Global.getString(mContext.getContentResolver(),
+                Settings.Global.WIRELESS_CHARGING_STARTED_SOUND);
+        if (soundPath != null) {
+            final Uri soundUri = Uri.parse("file://" + soundPath);
+            if (soundUri != null) {
+                final Ringtone sfx = RingtoneManager.getRingtone(mContext, soundUri);
+                if (sfx != null) {
+                    sfx.setStreamType(AudioManager.STREAM_SYSTEM);
+                    sfx.play();
+                }
+            }
+        }
+
+        mSuspendBlocker.release();
+    }
+
     private final class NotifierHandler extends Handler {
         public NotifierHandler(Looper looper) {
             super(looper, null, true /*async*/);
@@ -488,6 +525,10 @@
                 case MSG_BROADCAST:
                     sendNextBroadcast();
                     break;
+
+                case MSG_WIRELESS_CHARGING_STARTED:
+                    playWirelessChargingStartedSound();
+                    break;
             }
         }
     }
diff --git a/services/java/com/android/server/power/PowerManagerService.java b/services/java/com/android/server/power/PowerManagerService.java
index 8650192..546f22e 100644
--- a/services/java/com/android/server/power/PowerManagerService.java
+++ b/services/java/com/android/server/power/PowerManagerService.java
@@ -35,6 +35,8 @@
 import android.content.pm.PackageManager;
 import android.content.res.Resources;
 import android.database.ContentObserver;
+import android.hardware.SensorManager;
+import android.hardware.SystemSensorManager;
 import android.net.Uri;
 import android.os.BatteryManager;
 import android.os.Binder;
@@ -153,11 +155,6 @@
     // Otherwise the user won't get much screen on time before dimming occurs.
     private static final float MAXIMUM_SCREEN_DIM_RATIO = 0.2f;
 
-    // Upper bound on the battery charge percentage in order to consider turning
-    // the screen on when the device starts charging wirelessly.
-    // See point of use for more details.
-    private static final int WIRELESS_CHARGER_TURN_ON_BATTERY_LEVEL_LIMIT = 95;
-
     // The name of the boot animation service in init.rc.
     private static final String BOOT_ANIMATION_SERVICE = "bootanim";
 
@@ -179,6 +176,7 @@
     private WindowManagerPolicy mPolicy;
     private Notifier mNotifier;
     private DisplayPowerController mDisplayPowerController;
+    private WirelessChargerDetector mWirelessChargerDetector;
     private SettingsObserver mSettingsObserver;
     private DreamManagerService mDreamManager;
     private LightsService.Light mAttentionLight;
@@ -423,6 +421,8 @@
             mScreenBrightnessSettingMaximum = pm.getMaximumScreenBrightnessSetting();
             mScreenBrightnessSettingDefault = pm.getDefaultScreenBrightnessSetting();
 
+            SensorManager sensorManager = new SystemSensorManager(mHandler.getLooper());
+
             // The notifier runs on the system server's main looper so as not to interfere
             // with the animations and other critical functions of the power manager.
             mNotifier = new Notifier(Looper.getMainLooper(), mContext, mBatteryStats,
@@ -430,11 +430,14 @@
                     mScreenOnBlocker, mPolicy);
 
             // The display power controller runs on the power manager service's
-            // own handler thread.
+            // own handler thread to ensure timely operation.
             mDisplayPowerController = new DisplayPowerController(mHandler.getLooper(),
-                    mContext, mNotifier, mLightsService, twilight,
-                    mDisplayBlanker, mDisplayPowerControllerCallbacks, mHandler);
+                    mContext, mNotifier, mLightsService, twilight, sensorManager,
+                    mDisplayManagerService, mDisplayBlanker,
+                    mDisplayPowerControllerCallbacks, mHandler);
 
+            mWirelessChargerDetector = new WirelessChargerDetector(sensorManager,
+                    createSuspendBlockerLocked("PowerManagerService.WirelessChargerDetector"));
             mSettingsObserver = new SettingsObserver(mHandler);
             mAttentionLight = mLightsService.getLight(LightsService.LIGHT_ID_ATTENTION);
 
@@ -618,8 +621,19 @@
         }
     }
 
+    private static boolean isScreenLock(final WakeLock wakeLock) {
+        switch (wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK) {
+            case PowerManager.FULL_WAKE_LOCK:
+            case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
+            case PowerManager.SCREEN_DIM_WAKE_LOCK:
+                return true;
+        }
+        return false;
+    }
+
     private void applyWakeLockFlagsOnAcquireLocked(WakeLock wakeLock) {
-        if ((wakeLock.mFlags & PowerManager.ACQUIRE_CAUSES_WAKEUP) != 0) {
+        if ((wakeLock.mFlags & PowerManager.ACQUIRE_CAUSES_WAKEUP) != 0 &&
+                isScreenLock(wakeLock)) {
             wakeUpNoUpdateLocked(SystemClock.uptimeMillis());
         }
     }
@@ -1128,55 +1142,51 @@
             if (wasPowered != mIsPowered || oldPlugType != mPlugType) {
                 mDirty |= DIRTY_IS_POWERED;
 
+                // Update wireless dock detection state.
+                final boolean dockedOnWirelessCharger = mWirelessChargerDetector.update(
+                        mIsPowered, mPlugType, mBatteryLevel);
+
                 // Treat plugging and unplugging the devices as a user activity.
                 // Users find it disconcerting when they plug or unplug the device
                 // and it shuts off right away.
                 // Some devices also wake the device when plugged or unplugged because
                 // they don't have a charging LED.
                 final long now = SystemClock.uptimeMillis();
-                if (shouldWakeUpWhenPluggedOrUnpluggedLocked(wasPowered, oldPlugType)) {
+                if (shouldWakeUpWhenPluggedOrUnpluggedLocked(wasPowered, oldPlugType,
+                        dockedOnWirelessCharger)) {
                     wakeUpNoUpdateLocked(now);
                 }
                 userActivityNoUpdateLocked(
                         now, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);
+
+                // Tell the notifier whether wireless charging has started so that
+                // it can provide feedback to the user.
+                if (dockedOnWirelessCharger) {
+                    mNotifier.onWirelessChargingStarted();
+                }
             }
         }
     }
 
-    private boolean shouldWakeUpWhenPluggedOrUnpluggedLocked(boolean wasPowered, int oldPlugType) {
+    private boolean shouldWakeUpWhenPluggedOrUnpluggedLocked(
+            boolean wasPowered, int oldPlugType, boolean dockedOnWirelessCharger) {
         // Don't wake when powered unless configured to do so.
         if (!mWakeUpWhenPluggedOrUnpluggedConfig) {
             return false;
         }
 
-        // FIXME: Need more accurate detection of wireless chargers.
-        //
-        // We are unable to accurately detect whether the device is resting on the
-        // charger unless it is actually receiving power.  This causes us some grief
-        // because the device might not appear to be plugged into the wireless charger
-        // unless it actually charging.
-        //
-        // To avoid spuriously waking the screen, we apply a special policy to
-        // wireless chargers.
-        //
-        // 1. Don't wake the device when unplugged from wireless charger because
-        //    it might be that the device is still resting on the wireless charger
-        //    but is not receiving power anymore because the battery is full.
-        //
-        // 2. Don't wake the device when plugged into a wireless charger if the
-        //    battery already appears to be mostly full.  This situation may indicate
-        //    that the device was resting on the charger the whole time and simply
-        //    wasn't receiving power because the battery was full.  We can't tell
-        //    whether the device was just placed on the charger or whether it has
-        //    been there for half of the night slowly discharging until it hit
-        //    the point where it needed to start charging again.
+        // Don't wake when undocked from wireless charger.
+        // See WirelessChargerDetector for justification.
         if (wasPowered && !mIsPowered
                 && oldPlugType == BatteryManager.BATTERY_PLUGGED_WIRELESS) {
             return false;
         }
+
+        // Don't wake when docked on wireless charger unless we are certain of it.
+        // See WirelessChargerDetector for justification.
         if (!wasPowered && mIsPowered
                 && mPlugType == BatteryManager.BATTERY_PLUGGED_WIRELESS
-                && mBatteryLevel >= WIRELESS_CHARGER_TURN_ON_BATTERY_LEVEL_LIMIT) {
+                && !dockedOnWirelessCharger) {
             return false;
         }
 
@@ -2162,6 +2172,7 @@
         pw.println("POWER MANAGER (dumpsys power)\n");
 
         final DisplayPowerController dpc;
+        final WirelessChargerDetector wcd;
         synchronized (mLock) {
             pw.println("Power Manager State:");
             pw.println("  mDirty=0x" + Integer.toHexString(mDirty));
@@ -2243,11 +2254,16 @@
             pw.println("Display Blanker: " + mDisplayBlanker);
 
             dpc = mDisplayPowerController;
+            wcd = mWirelessChargerDetector;
         }
 
         if (dpc != null) {
             dpc.dump(pw);
         }
+
+        if (wcd != null) {
+            wcd.dump(pw);
+        }
     }
 
     private SuspendBlocker createSuspendBlockerLocked(String name) {
diff --git a/services/java/com/android/server/power/RampAnimator.java b/services/java/com/android/server/power/RampAnimator.java
index 6f063c3..4a4f080 100644
--- a/services/java/com/android/server/power/RampAnimator.java
+++ b/services/java/com/android/server/power/RampAnimator.java
@@ -102,20 +102,26 @@
             final long frameTimeNanos = mChoreographer.getFrameTimeNanos();
             final float timeDelta = (frameTimeNanos - mLastFrameTimeNanos)
                     * 0.000000001f;
-            final float amount = timeDelta * mRate / ValueAnimator.getDurationScale();
             mLastFrameTimeNanos = frameTimeNanos;
 
             // Advance the animated value towards the target at the specified rate
             // and clamp to the target. This gives us the new current value but
             // we keep the animated value around to allow for fractional increments
             // towards the target.
-            int oldCurrentValue = mCurrentValue;
-            if (mTargetValue > mCurrentValue) {
-                mAnimatedValue = Math.min(mAnimatedValue + amount, mTargetValue);
+            final float scale = ValueAnimator.getDurationScale();
+            if (scale == 0) {
+                // Animation off.
+                mAnimatedValue = mTargetValue;
             } else {
-                mAnimatedValue = Math.max(mAnimatedValue - amount, mTargetValue);
+                final float amount = timeDelta * mRate / scale;
+                if (mTargetValue > mCurrentValue) {
+                    mAnimatedValue = Math.min(mAnimatedValue + amount, mTargetValue);
+                } else {
+                    mAnimatedValue = Math.max(mAnimatedValue - amount, mTargetValue);
+                }
             }
-            mCurrentValue = (int)Math.round(mAnimatedValue);
+            final int oldCurrentValue = mCurrentValue;
+            mCurrentValue = Math.round(mAnimatedValue);
 
             if (oldCurrentValue != mCurrentValue) {
                 mProperty.setValue(mObject, mCurrentValue);
diff --git a/services/java/com/android/server/power/WirelessChargerDetector.java b/services/java/com/android/server/power/WirelessChargerDetector.java
new file mode 100644
index 0000000..ac6dc3e
--- /dev/null
+++ b/services/java/com/android/server/power/WirelessChargerDetector.java
@@ -0,0 +1,320 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.power;
+
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
+import android.os.BatteryManager;
+import android.util.Slog;
+
+import java.io.PrintWriter;
+
+/**
+ * Implements heuristics to detect docking or undocking from a wireless charger.
+ * <p>
+ * Some devices have wireless charging circuits that are unable to detect when the
+ * device is resting on a wireless charger except when the device is actually
+ * receiving power from the charger.  The device may stop receiving power
+ * if the battery is already nearly full or if it is too hot.  As a result, we cannot
+ * always rely on the battery service wireless plug signal to accurately indicate
+ * whether the device has been docked or undocked from a wireless charger.
+ * </p><p>
+ * This is a problem because the power manager typically wakes up the screen and
+ * plays a tone when the device is docked in a wireless charger.  It is important
+ * for the system to suppress spurious docking and undocking signals because they
+ * can be intrusive for the user (especially if they cause a tone to be played
+ * late at night for no apparent reason).
+ * </p><p>
+ * To avoid spurious signals, we apply some special policies to wireless chargers.
+ * </p><p>
+ * 1. Don't wake the device when undocked from the wireless charger because
+ * it might be that the device is still resting on the wireless charger
+ * but is not receiving power anymore because the battery is full.
+ * Ideally we would wake the device if we could be certain that the user had
+ * picked it up from the wireless charger but due to hardware limitations we
+ * must be more conservative.
+ * </p><p>
+ * 2. Don't wake the device when docked on a wireless charger if the
+ * battery already appears to be mostly full.  This situation may indicate
+ * that the device was resting on the charger the whole time and simply
+ * wasn't receiving power because the battery was already full.  We can't tell
+ * whether the device was just placed on the charger or whether it has
+ * been there for half of the night slowly discharging until it reached
+ * the point where it needed to start charging again.  So we suppress docking
+ * signals that occur when the battery level is above a given threshold.
+ * </p><p>
+ * 3. Don't wake the device when docked on a wireless charger if it does
+ * not appear to have moved since it was last undocked because it may
+ * be that the prior undocking signal was spurious.  We use the gravity
+ * sensor to detect this case.
+ * </p>
+ */
+final class WirelessChargerDetector {
+    private static final String TAG = "WirelessChargerDetector";
+    private static final boolean DEBUG = false;
+
+    // Number of nanoseconds per millisecond.
+    private static final long NANOS_PER_MS = 1000000;
+
+    // The minimum amount of time to spend watching the sensor before making
+    // a determination of whether movement occurred.
+    private static final long SETTLE_TIME_NANOS = 500 * NANOS_PER_MS;
+
+    // The minimum number of samples that must be collected.
+    private static final int MIN_SAMPLES = 3;
+
+    // Upper bound on the battery charge percentage in order to consider turning
+    // the screen on when the device starts charging wirelessly.
+    private static final int WIRELESS_CHARGER_TURN_ON_BATTERY_LEVEL_LIMIT = 95;
+
+    // To detect movement, we compute the angle between the gravity vector
+    // at rest and the current gravity vector.  This field specifies the
+    // cosine of the maximum angle variance that we tolerate while at rest.
+    private static final double MOVEMENT_ANGLE_COS_THRESHOLD = Math.cos(5 * Math.PI / 180);
+
+    // Sanity thresholds for the gravity vector.
+    private static final double MIN_GRAVITY = SensorManager.GRAVITY_EARTH - 1.0f;
+    private static final double MAX_GRAVITY = SensorManager.GRAVITY_EARTH + 1.0f;
+
+    private final Object mLock = new Object();
+
+    private final SensorManager mSensorManager;
+    private final SuspendBlocker mSuspendBlocker;
+
+    // The gravity sensor, or null if none.
+    private Sensor mGravitySensor;
+
+    // Previously observed wireless power state.
+    private boolean mPoweredWirelessly;
+
+    // True if the device is thought to be at rest on a wireless charger.
+    private boolean mAtRest;
+
+    // The gravity vector most recently observed while at rest.
+    private float mRestX, mRestY, mRestZ;
+
+    /* These properties are only meaningful while detection is in progress. */
+
+    // True if detection is in progress.
+    // The suspend blocker is held while this is the case.
+    private boolean mDetectionInProgress;
+
+    // True if the rest position should be updated if at rest.
+    // Otherwise, the current rest position is simply checked and cleared if movement
+    // is detected but no new rest position is stored.
+    private boolean mMustUpdateRestPosition;
+
+    // The total number of samples collected.
+    private int mTotalSamples;
+
+    // The number of samples collected that showed evidence of not being at rest.
+    private int mMovingSamples;
+
+    // The time and value of the first sample that was collected.
+    private long mFirstSampleTime;
+    private float mFirstSampleX, mFirstSampleY, mFirstSampleZ;
+
+    public WirelessChargerDetector(SensorManager sensorManager,
+            SuspendBlocker suspendBlocker) {
+        mSensorManager = sensorManager;
+        mSuspendBlocker = suspendBlocker;
+
+        mGravitySensor = sensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY);
+    }
+
+    public void dump(PrintWriter pw) {
+        synchronized (mLock) {
+            pw.println();
+            pw.println("Wireless Charger Detector State:");
+            pw.println("  mGravitySensor=" + mGravitySensor);
+            pw.println("  mPoweredWirelessly=" + mPoweredWirelessly);
+            pw.println("  mAtRest=" + mAtRest);
+            pw.println("  mRestX=" + mRestX + ", mRestY=" + mRestY + ", mRestZ=" + mRestZ);
+            pw.println("  mDetectionInProgress=" + mDetectionInProgress);
+            pw.println("  mMustUpdateRestPosition=" + mMustUpdateRestPosition);
+            pw.println("  mTotalSamples=" + mTotalSamples);
+            pw.println("  mMovingSamples=" + mMovingSamples);
+            pw.println("  mFirstSampleTime=" + mFirstSampleTime);
+            pw.println("  mFirstSampleX=" + mFirstSampleX
+                    + ", mFirstSampleY=" + mFirstSampleY + ", mFirstSampleZ=" + mFirstSampleZ);
+        }
+    }
+
+    /**
+     * Updates the charging state and returns true if docking was detected.
+     *
+     * @param isPowered True if the device is powered.
+     * @param plugType The current plug type.
+     * @param batteryLevel The current battery level.
+     * @return True if the device is determined to have just been docked on a wireless
+     * charger, after suppressing spurious docking or undocking signals.
+     */
+    public boolean update(boolean isPowered, int plugType, int batteryLevel) {
+        synchronized (mLock) {
+            final boolean wasPoweredWirelessly = mPoweredWirelessly;
+
+            if (isPowered && plugType == BatteryManager.BATTERY_PLUGGED_WIRELESS) {
+                // The device is receiving power from the wireless charger.
+                // Update the rest position asynchronously.
+                mPoweredWirelessly = true;
+                mMustUpdateRestPosition = true;
+                startDetectionLocked();
+            } else {
+                // The device may or may not be on the wireless charger depending on whether
+                // the unplug signal that we received was spurious.
+                mPoweredWirelessly = false;
+                if (mAtRest) {
+                    if (plugType != 0 && plugType != BatteryManager.BATTERY_PLUGGED_WIRELESS) {
+                        // The device was plugged into a new non-wireless power source.
+                        // It's safe to assume that it is no longer on the wireless charger.
+                        mMustUpdateRestPosition = false;
+                        clearAtRestLocked();
+                    } else {
+                        // The device may still be on the wireless charger but we don't know.
+                        // Check whether the device has remained at rest on the charger
+                        // so that we will know to ignore the next wireless plug event
+                        // if needed.
+                        startDetectionLocked();
+                    }
+                }
+            }
+
+            // Report that the device has been docked only if the device just started
+            // receiving power wirelessly, has a high enough battery level that we
+            // can be assured that charging was not delayed due to the battery previously
+            // having been full, and the device is not known to already be at rest
+            // on the wireless charger from earlier.
+            return mPoweredWirelessly && !wasPoweredWirelessly
+                    && batteryLevel < WIRELESS_CHARGER_TURN_ON_BATTERY_LEVEL_LIMIT
+                    && !mAtRest;
+        }
+    }
+
+    private void startDetectionLocked() {
+        if (!mDetectionInProgress && mGravitySensor != null) {
+            if (mSensorManager.registerListener(mListener, mGravitySensor,
+                    SensorManager.SENSOR_DELAY_UI)) {
+                mSuspendBlocker.acquire();
+                mDetectionInProgress = true;
+                mTotalSamples = 0;
+                mMovingSamples = 0;
+            }
+        }
+    }
+
+    private void processSample(long timeNanos, float x, float y, float z) {
+        synchronized (mLock) {
+            if (!mDetectionInProgress) {
+                return;
+            }
+
+            mTotalSamples += 1;
+            if (mTotalSamples == 1) {
+                // Save information about the first sample collected.
+                mFirstSampleTime = timeNanos;
+                mFirstSampleX = x;
+                mFirstSampleY = y;
+                mFirstSampleZ = z;
+            } else {
+                // Determine whether movement has occurred relative to the first sample.
+                if (hasMoved(mFirstSampleX, mFirstSampleY, mFirstSampleZ, x, y, z)) {
+                    mMovingSamples += 1;
+                }
+            }
+
+            // Clear the at rest flag if movement has occurred relative to the rest sample.
+            if (mAtRest && hasMoved(mRestX, mRestY, mRestZ, x, y, z)) {
+                if (DEBUG) {
+                    Slog.d(TAG, "No longer at rest: "
+                            + "mRestX=" + mRestX + ", mRestY=" + mRestY + ", mRestZ=" + mRestZ
+                            + ", x=" + x + ", y=" + y + ", z=" + z);
+                }
+                clearAtRestLocked();
+            }
+
+            // Save the result when done.
+            if (timeNanos - mFirstSampleTime >= SETTLE_TIME_NANOS
+                    && mTotalSamples >= MIN_SAMPLES) {
+                mSensorManager.unregisterListener(mListener);
+                if (mMustUpdateRestPosition) {
+                    if (mMovingSamples == 0) {
+                        mAtRest = true;
+                        mRestX = x;
+                        mRestY = y;
+                        mRestZ = z;
+                    } else {
+                        clearAtRestLocked();
+                    }
+                    mMustUpdateRestPosition = false;
+                }
+                mDetectionInProgress = false;
+                mSuspendBlocker.release();
+
+                if (DEBUG) {
+                    Slog.d(TAG, "New state: mAtRest=" + mAtRest
+                            + ", mRestX=" + mRestX + ", mRestY=" + mRestY + ", mRestZ=" + mRestZ
+                            + ", mTotalSamples=" + mTotalSamples
+                            + ", mMovingSamples=" + mMovingSamples);
+                }
+            }
+        }
+    }
+
+    private void clearAtRestLocked() {
+        mAtRest = false;
+        mRestX = 0;
+        mRestY = 0;
+        mRestZ = 0;
+    }
+
+    private static boolean hasMoved(float x1, float y1, float z1,
+            float x2, float y2, float z2) {
+        final double dotProduct = (x1 * x2) + (y1 * y2) + (z1 * z2);
+        final double mag1 = Math.sqrt((x1 * x1) + (y1 * y1) + (z1 * z1));
+        final double mag2 = Math.sqrt((x2 * x2) + (y2 * y2) + (z2 * z2));
+        if (mag1 < MIN_GRAVITY || mag1 > MAX_GRAVITY
+                || mag2 < MIN_GRAVITY || mag2 > MAX_GRAVITY) {
+            if (DEBUG) {
+                Slog.d(TAG, "Weird gravity vector: mag1=" + mag1 + ", mag2=" + mag2);
+            }
+            return true;
+        }
+        final boolean moved = (dotProduct < mag1 * mag2 * MOVEMENT_ANGLE_COS_THRESHOLD);
+        if (DEBUG) {
+            Slog.d(TAG, "Check: moved=" + moved
+                    + ", x1=" + x1 + ", y1=" + y1 + ", z1=" + z1
+                    + ", x2=" + x2 + ", y2=" + y2 + ", z2=" + z2
+                    + ", angle=" + (Math.acos(dotProduct / mag1 / mag2) * 180 / Math.PI)
+                    + ", dotProduct=" + dotProduct
+                    + ", mag1=" + mag1 + ", mag2=" + mag2);
+        }
+        return moved;
+    }
+
+    private final SensorEventListener mListener = new SensorEventListener() {
+        @Override
+        public void onSensorChanged(SensorEvent event) {
+            processSample(event.timestamp, event.values[0], event.values[1], event.values[2]);
+        }
+
+        @Override
+        public void onAccuracyChanged(Sensor sensor, int accuracy) {
+        }
+    };
+}
diff --git a/services/java/com/android/server/usb/UsbDeviceManager.java b/services/java/com/android/server/usb/UsbDeviceManager.java
index f34a52d..c7c2c62 100644
--- a/services/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/java/com/android/server/usb/UsbDeviceManager.java
@@ -47,6 +47,8 @@
 import android.util.Pair;
 import android.util.Slog;
 
+import com.android.internal.annotations.GuardedBy;
+
 import java.io.File;
 import java.io.FileDescriptor;
 import java.io.FileNotFoundException;
@@ -105,7 +107,7 @@
 
     private final Context mContext;
     private final ContentResolver mContentResolver;
-    // @GuardedBy("mLock")
+    @GuardedBy("mLock")
     private UsbSettingsManager mCurrentSettings;
     private NotificationManager mNotificationManager;
     private final boolean mHasUsbAccessory;
diff --git a/services/java/com/android/server/usb/UsbHostManager.java b/services/java/com/android/server/usb/UsbHostManager.java
index 175ae6f..10272f2 100644
--- a/services/java/com/android/server/usb/UsbHostManager.java
+++ b/services/java/com/android/server/usb/UsbHostManager.java
@@ -26,6 +26,8 @@
 import android.os.Parcelable;
 import android.util.Slog;
 
+import com.android.internal.annotations.GuardedBy;
+
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.HashMap;
@@ -46,7 +48,7 @@
     private final Context mContext;
     private final Object mLock = new Object();
 
-    // @GuardedBy("mLock")
+    @GuardedBy("mLock")
     private UsbSettingsManager mCurrentSettings;
 
     public UsbHostManager(Context context) {
diff --git a/services/java/com/android/server/usb/UsbService.java b/services/java/com/android/server/usb/UsbService.java
index 629f5fa..3918d15 100644
--- a/services/java/com/android/server/usb/UsbService.java
+++ b/services/java/com/android/server/usb/UsbService.java
@@ -30,6 +30,7 @@
 import android.os.UserHandle;
 import android.util.SparseArray;
 
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.IndentingPrintWriter;
 
 import java.io.File;
@@ -52,7 +53,7 @@
     private final Object mLock = new Object();
 
     /** Map from {@link UserHandle} to {@link UsbSettingsManager} */
-    // @GuardedBy("mLock")
+    @GuardedBy("mLock")
     private final SparseArray<UsbSettingsManager>
             mSettingsByUser = new SparseArray<UsbSettingsManager>();
 
diff --git a/services/java/com/android/server/wm/AppWindowToken.java b/services/java/com/android/server/wm/AppWindowToken.java
index 7efffe5..2802ad7 100644
--- a/services/java/com/android/server/wm/AppWindowToken.java
+++ b/services/java/com/android/server/wm/AppWindowToken.java
@@ -37,6 +37,8 @@
  * really activity) that is displaying windows.
  */
 class AppWindowToken extends WindowToken {
+    // The user who owns this app window token.
+    final int userId;
     // Non-null only for application tokens.
     final IApplicationToken appToken;
 
@@ -98,9 +100,10 @@
     // Input application handle used by the input dispatcher.
     final InputApplicationHandle mInputApplicationHandle;
 
-    AppWindowToken(WindowManagerService _service, IApplicationToken _token) {
+    AppWindowToken(WindowManagerService _service, int _userId, IApplicationToken _token) {
         super(_service, _token.asBinder(),
                 WindowManager.LayoutParams.TYPE_APPLICATION, true);
+        userId = _userId;
         appWindowToken = this;
         appToken = _token;
         mInputApplicationHandle = new InputApplicationHandle(this);
@@ -225,7 +228,8 @@
     void dump(PrintWriter pw, String prefix) {
         super.dump(pw, prefix);
         if (appToken != null) {
-            pw.print(prefix); pw.println("app=true");
+            pw.print(prefix); pw.print("app=true");
+                    pw.print(" userId="); pw.println(userId);
         }
         if (allAppWindows.size() > 0) {
             pw.print(prefix); pw.print("allAppWindows="); pw.println(allAppWindows);
diff --git a/services/java/com/android/server/wm/ScreenRotationAnimation.java b/services/java/com/android/server/wm/ScreenRotationAnimation.java
index 8d2e2e8..cfcf841 100644
--- a/services/java/com/android/server/wm/ScreenRotationAnimation.java
+++ b/services/java/com/android/server/wm/ScreenRotationAnimation.java
@@ -668,6 +668,10 @@
         return hasAnimations() || (TWO_PHASE_ANIMATION && mFinishAnimReady);
     }
 
+    public boolean isRotating() {
+        return mCurRotation != mOriginalRotation;
+    }
+
     private boolean hasAnimations() {
         return (TWO_PHASE_ANIMATION &&
                     (mStartEnterAnimation != null || mStartExitAnimation != null
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 51edb44..5b9fc9a 100755
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -268,6 +268,9 @@
     /** Amount of time (in milliseconds) to delay before declaring a window freeze timeout. */
     static final int WINDOW_FREEZE_TIMEOUT_DURATION = 2000;
 
+    /** Fraction of animation at which the recents thumbnail becomes completely transparent */
+    static final float RECENTS_THUMBNAIL_FADEOUT_FRACTION = 0.25f;
+
     /**
      * If true, the window manager will do its own custom freezing and general
      * management of the screen during rotation.
@@ -821,7 +824,7 @@
         mTransitionAnimationScale = Settings.Global.getFloat(context.getContentResolver(),
                 Settings.Global.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScale);
         setAnimatorDurationScale(Settings.Global.getFloat(context.getContentResolver(),
-                Settings.Global.ANIMATOR_DURATION_SCALE, mTransitionAnimationScale));
+                Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScale));
 
         // Track changes to DevicePolicyManager state so we can enable/disable keyguard.
         IntentFilter filter = new IntentFilter();
@@ -919,6 +922,27 @@
         return windowList;
     }
 
+    /**
+     * Recursive search through a WindowList and all of its windows' children.
+     * @param targetWin The window to search for.
+     * @param windows The list to search.
+     * @return The index of win in windows or of the window that is an ancestor of win.
+     */
+    private int indexOfWinInWindowList(WindowState targetWin, WindowList windows) {
+        for (int i = windows.size() - 1; i >= 0; i--) {
+            final WindowState w = windows.get(i);
+            if (w == targetWin) {
+                return i;
+            }
+            if (!w.mChildWindows.isEmpty()) {
+                if (indexOfWinInWindowList(targetWin, w.mChildWindows) >= 0) {
+                    return i;
+                }
+            }
+        }
+        return -1;
+    }
+
     private void addWindowToListInOrderLocked(WindowState win, boolean addToToken) {
         final IWindow client = win.mClient;
         final WindowToken token = win.mToken;
@@ -942,13 +966,13 @@
                         // Base windows go behind everything else.
                         WindowState lowestWindow = tokenWindowList.get(0);
                         placeWindowBefore(lowestWindow, win);
-                        tokenWindowsPos = token.windows.indexOf(lowestWindow);
+                        tokenWindowsPos = indexOfWinInWindowList(lowestWindow, token.windows);
                     } else {
                         AppWindowToken atoken = win.mAppToken;
                         WindowState lastWindow = tokenWindowList.get(index);
                         if (atoken != null && lastWindow == atoken.startingWindow) {
                             placeWindowBefore(lastWindow, win);
-                            tokenWindowsPos = token.windows.indexOf(lastWindow);
+                            tokenWindowsPos = indexOfWinInWindowList(lastWindow, token.windows);
                         } else {
                             int newIdx = findIdxBasedOnAppTokens(win);
                             //there is a window above this one associated with the same
@@ -964,7 +988,8 @@
                                 // No window from token found on win's display.
                                 tokenWindowsPos = 0;
                             } else {
-                                tokenWindowsPos = token.windows.indexOf(windows.get(newIdx)) + 1;
+                                tokenWindowsPos = indexOfWinInWindowList(
+                                        windows.get(newIdx), token.windows) + 1;
                             }
                             mWindowsChanged = true;
                         }
@@ -2848,7 +2873,7 @@
                     }
                     if (win.isConfigChanged()) {
                         if (DEBUG_CONFIGURATION) Slog.i(TAG, "Window " + win
-                                + " visible with new config: " + win.mConfiguration);
+                                + " visible with new config: " + mCurConfiguration);
                         outConfig.setTo(mCurConfiguration);
                     }
                 }
@@ -3178,7 +3203,7 @@
         return info;
     }
 
-    private AttributeCache.Entry getCachedAnimations(WindowManager.LayoutParams lp) {
+    private AttributeCache.Entry getCachedAnimations(int userId, WindowManager.LayoutParams lp) {
         if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: layout params pkg="
                 + (lp != null ? lp.packageName : null)
                 + " resId=0x" + (lp != null ? Integer.toHexString(lp.windowAnimations) : null));
@@ -3193,13 +3218,13 @@
             }
             if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: picked package="
                     + packageName);
-            return AttributeCache.instance().get(packageName, resId,
+            return AttributeCache.instance().get(userId, packageName, resId,
                     com.android.internal.R.styleable.WindowAnimation);
         }
         return null;
     }
 
-    private AttributeCache.Entry getCachedAnimations(String packageName, int resId) {
+    private AttributeCache.Entry getCachedAnimations(int userId, String packageName, int resId) {
         if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: package="
                 + packageName + " resId=0x" + Integer.toHexString(resId));
         if (packageName != null) {
@@ -3208,17 +3233,17 @@
             }
             if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: picked package="
                     + packageName);
-            return AttributeCache.instance().get(packageName, resId,
+            return AttributeCache.instance().get(userId, packageName, resId,
                     com.android.internal.R.styleable.WindowAnimation);
         }
         return null;
     }
 
-    Animation loadAnimation(WindowManager.LayoutParams lp, int animAttr) {
+    Animation loadAnimation(int userId, WindowManager.LayoutParams lp, int animAttr) {
         int anim = 0;
         Context context = mContext;
         if (animAttr >= 0) {
-            AttributeCache.Entry ent = getCachedAnimations(lp);
+            AttributeCache.Entry ent = getCachedAnimations(userId, lp);
             if (ent != null) {
                 context = ent.context;
                 anim = ent.array.getResourceId(animAttr, 0);
@@ -3230,11 +3255,11 @@
         return null;
     }
 
-    private Animation loadAnimation(String packageName, int resId) {
+    private Animation loadAnimation(int userId, String packageName, int resId) {
         int anim = 0;
         Context context = mContext;
         if (resId >= 0) {
-            AttributeCache.Entry ent = getCachedAnimations(packageName, resId);
+            AttributeCache.Entry ent = getCachedAnimations(userId, packageName, resId);
             if (ent != null) {
                 context = ent.context;
                 anim = resId;
@@ -3361,13 +3386,24 @@
                 Animation scale = new ScaleAnimation(1, scaleW, 1, scaleH,
                         computePivot(mNextAppTransitionStartX, 1 / scaleW),
                         computePivot(mNextAppTransitionStartY, 1 / scaleH));
-                AnimationSet set = new AnimationSet(true);
+                AnimationSet set = new AnimationSet(false);
                 Animation alpha = new AlphaAnimation(1, 0);
                 scale.setDuration(duration);
-                scale.setInterpolator(
-                        new DecelerateInterpolator(THUMBNAIL_ANIMATION_DECELERATE_FACTOR));
+                scale.setInterpolator(AnimationUtils.loadInterpolator(mContext,
+                        com.android.internal.R.interpolator.decelerate_quad));
                 set.addAnimation(scale);
                 alpha.setDuration(duration);
+                alpha.setInterpolator(new Interpolator() {
+                    @Override
+                    public float getInterpolation(float input) {
+                        if (input < RECENTS_THUMBNAIL_FADEOUT_FRACTION) {
+                            // linear response
+                            return input / RECENTS_THUMBNAIL_FADEOUT_FRACTION;
+                        }
+                        // complete
+                        return 1;
+                    }
+                });
                 set.addAnimation(alpha);
                 set.setFillBefore(true);
                 a = set;
@@ -3462,7 +3498,7 @@
             Animation a;
             boolean initialized = false;
             if (mNextAppTransitionType == ActivityOptions.ANIM_CUSTOM) {
-                a = loadAnimation(mNextAppTransitionPackage, enter ?
+                a = loadAnimation(atoken.userId, mNextAppTransitionPackage, enter ?
                         mNextAppTransitionEnter : mNextAppTransitionExit);
                 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG,
                         "applyAnimation: atoken=" + atoken
@@ -3543,7 +3579,7 @@
                                 : com.android.internal.R.styleable.WindowAnimation_wallpaperIntraCloseExitAnimation;
                         break;
                 }
-                a = animAttr != 0 ? loadAnimation(lp, animAttr) : null;
+                a = animAttr != 0 ? loadAnimation(atoken.userId, lp, animAttr) : null;
                 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG,
                         "applyAnimation: atoken=" + atoken
                         + " anim=" + a
@@ -3730,7 +3766,7 @@
     }
 
     @Override
-    public void addAppToken(int addPos, IApplicationToken token,
+    public void addAppToken(int addPos, int userId, IApplicationToken token,
             int groupId, int requestedOrientation, boolean fullscreen, boolean showWhenLocked) {
         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
                 "addAppToken()")) {
@@ -3757,7 +3793,7 @@
                 Slog.w(TAG, "Attempted to add existing app token: " + token);
                 return;
             }
-            atoken = new AppWindowToken(this, token);
+            atoken = new AppWindowToken(this, userId, token);
             atoken.inputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos;
             atoken.groupId = groupId;
             atoken.appFullscreen = fullscreen;
@@ -3808,22 +3844,23 @@
         final WindowList windows = getDefaultWindowListLocked();
         int pos = windows.size() - 1;
         while (pos >= 0) {
-            WindowState wtoken = windows.get(pos);
+            WindowState win = windows.get(pos);
             pos--;
-            if (wtoken.mAppToken != null) {
+            if (win.mAppToken != null) {
                 // We hit an application window. so the orientation will be determined by the
                 // app window. No point in continuing further.
                 return (mLastWindowForcedOrientation=ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
             }
-            if (!wtoken.isVisibleLw() || !wtoken.mPolicyVisibilityAfterAnim) {
+            if (!win.isVisibleLw() || !win.mPolicyVisibilityAfterAnim) {
                 continue;
             }
-            int req = wtoken.mAttrs.screenOrientation;
+            int req = win.mAttrs.screenOrientation;
             if((req == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) ||
                     (req == ActivityInfo.SCREEN_ORIENTATION_BEHIND)){
                 continue;
             }
 
+            if (DEBUG_ORIENTATION) Slog.v(TAG, win + " forcing orientation to " + req);
             return (mLastWindowForcedOrientation=req);
         }
         return (mLastWindowForcedOrientation=ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
@@ -4373,8 +4410,8 @@
             if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Checking theme of starting window: 0x"
                     + Integer.toHexString(theme));
             if (theme != 0) {
-                AttributeCache.Entry ent = AttributeCache.instance().get(pkg, theme,
-                        com.android.internal.R.styleable.Window);
+                AttributeCache.Entry ent = AttributeCache.instance().get(wtoken.userId,
+                        pkg, theme, com.android.internal.R.styleable.Window);
                 if (ent == null) {
                     // Whoops!  App doesn't exist.  Um.  Okay.  We'll just
                     // pretend like we didn't see that.
@@ -5777,50 +5814,64 @@
             // Figure out the part of the screen that is actually the app.
             boolean including = false;
             final WindowList windows = displayContent.getWindowList();
-            for (int i = windows.size() - 1; i >= 0; i--) {
-                WindowState ws = windows.get(i);
-                if (!ws.mHasSurface) {
-                    continue;
-                }
-                if (ws.mLayer >= aboveAppLayer) {
-                    continue;
-                }
-                // When we will skip windows: when we are not including
-                // ones behind a window we didn't skip, and we are actually
-                // taking a screenshot of a specific app.
-                if (!including && appToken != null) {
-                    // Also, we can possibly skip this window if it is not
-                    // an IME target or the application for the screenshot
-                    // is not the current IME target.
-                    if (!ws.mIsImWindow || !isImeTarget) {
-                        // And finally, this window is of no interest if it
-                        // is not associated with the screenshot app.
-                        if (ws.mAppToken == null || ws.mAppToken.token != appToken) {
-                            continue;
+            try {
+                Surface.openTransaction();
+                for (int i = windows.size() - 1; i >= 0; i--) {
+                    WindowState ws = windows.get(i);
+                    if (!ws.mHasSurface) {
+                        continue;
+                    }
+                    if (ws.mLayer >= aboveAppLayer) {
+                        continue;
+                    }
+                    // When we will skip windows: when we are not including
+                    // ones behind a window we didn't skip, and we are actually
+                    // taking a screenshot of a specific app.
+                    if (!including && appToken != null) {
+                        // Also, we can possibly skip this window if it is not
+                        // an IME target or the application for the screenshot
+                        // is not the current IME target.
+                        if (!ws.mIsImWindow || !isImeTarget) {
+                            // And finally, this window is of no interest if it
+                            // is not associated with the screenshot app.
+                            if (ws.mAppToken == null || ws.mAppToken.token != appToken) {
+                                continue;
+                            }
                         }
                     }
-                }
 
-                // We keep on including windows until we go past a full-screen
-                // window.
-                including = !ws.mIsImWindow && !ws.isFullscreen(dw, dh);
+                    // We keep on including windows until we go past a full-screen
+                    // window.
+                    including = !ws.mIsImWindow && !ws.isFullscreen(dw, dh);
 
-                if (maxLayer < ws.mWinAnimator.mSurfaceLayer) {
-                    maxLayer = ws.mWinAnimator.mSurfaceLayer;
+                    final WindowStateAnimator winAnimator = ws.mWinAnimator;
+
+                    // The setSize() method causes all previous Surface transactions to sync to
+                    // the SurfaceFlinger. This will force any outstanding setLayer calls to be
+                    // synced as well for screen capture. Without this we can get black bitmaps.
+                    Surface surface = winAnimator.mSurface;
+                    surface.setSize(surface.getWidth(), surface.getHeight());
+
+
+                    if (maxLayer < winAnimator.mSurfaceLayer) {
+                        maxLayer = winAnimator.mSurfaceLayer;
+                    }
+
+                    // Don't include wallpaper in bounds calculation
+                    if (!ws.mIsWallpaper) {
+                        final Rect wf = ws.mFrame;
+                        final Rect cr = ws.mContentInsets;
+                        int left = wf.left + cr.left;
+                        int top = wf.top + cr.top;
+                        int right = wf.right - cr.right;
+                        int bottom = wf.bottom - cr.bottom;
+                        frame.union(left, top, right, bottom);
+                    }
                 }
-                
-                // Don't include wallpaper in bounds calculation
-                if (!ws.mIsWallpaper) {
-                    final Rect wf = ws.mFrame;
-                    final Rect cr = ws.mContentInsets;
-                    int left = wf.left + cr.left;
-                    int top = wf.top + cr.top;
-                    int right = wf.right - cr.right;
-                    int bottom = wf.bottom - cr.bottom;
-                    frame.union(left, top, right, bottom);
-                }
+            } finally {
+                Surface.closeTransaction();
+                Binder.restoreCallingIdentity(ident);
             }
-            Binder.restoreCallingIdentity(ident);
 
             // Constrain frame to the screen size.
             frame.intersect(0, 0, dw, dh);
@@ -9407,7 +9458,7 @@
                             + " / " + mCurConfiguration + " / 0x"
                             + Integer.toHexString(diff));
                 }
-                win.mConfiguration = mCurConfiguration;
+                win.setConfiguration(mCurConfiguration);
                 if (DEBUG_ORIENTATION &&
                         winAnimator.mDrawState == WindowStateAnimator.DRAW_PENDING) Slog.i(
                         TAG, "Resizing " + win + " WITH DRAW PENDING");
diff --git a/services/java/com/android/server/wm/WindowState.java b/services/java/com/android/server/wm/WindowState.java
index 35bebbe..81eac20 100644
--- a/services/java/com/android/server/wm/WindowState.java
+++ b/services/java/com/android/server/wm/WindowState.java
@@ -21,6 +21,7 @@
 import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
+import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD;
 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
 
 import com.android.server.input.InputWindowHandle;
@@ -78,7 +79,7 @@
     final WindowManager.LayoutParams mAttrs = new WindowManager.LayoutParams();
     final DeathRecipient mDeathRecipient;
     final WindowState mAttachedWindow;
-    final ArrayList<WindowState> mChildWindows = new ArrayList<WindowState>();
+    final WindowList mChildWindows = new WindowList();
     final int mBaseLayer;
     final int mSubLayer;
     final boolean mLayoutAttached;
@@ -112,6 +113,9 @@
     int mLayoutSeq = -1;
 
     Configuration mConfiguration = null;
+    // Sticky answer to isConfigChanged(), remains true until new Configuration is assigned.
+    // Used only on {@link #TYPE_KEYGUARD}.
+    private boolean mConfigHasChanged;
 
     /**
      * Actual frame shown on-screen (may be modified by animation).  These
@@ -627,6 +631,7 @@
                 : WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
     }
 
+    @Override
     public boolean hasAppShownWindows() {
         return mAppToken != null && (mAppToken.firstWindowDrawn || mAppToken.startingDisplayed);
     }
@@ -857,9 +862,17 @@
     }
 
     boolean isConfigChanged() {
-        return mConfiguration != mService.mCurConfiguration
+        boolean configChanged = mConfiguration != mService.mCurConfiguration
                 && (mConfiguration == null
                         || (mConfiguration.diff(mService.mCurConfiguration) != 0));
+
+        if (mAttrs.type == TYPE_KEYGUARD) {
+            // Retain configuration changed status until resetConfiguration called.
+            mConfigHasChanged |= configChanged;
+            configChanged = mConfigHasChanged;
+        }
+
+        return configChanged;
     }
 
     boolean isConfigDiff(int mask) {
@@ -886,6 +899,11 @@
         }
     }
 
+    void setConfiguration(final Configuration newConfig) {
+        mConfiguration = newConfig;
+        mConfigHasChanged = false;
+    }
+
     void setInputChannel(InputChannel inputChannel) {
         if (mInputChannel != null) {
             throw new IllegalStateException("Window already has an input channel.");
@@ -907,6 +925,7 @@
     }
 
     private class DeathRecipient implements IBinder.DeathRecipient {
+        @Override
         public void binderDied() {
             try {
                 synchronized(mService.mWindowMap) {
diff --git a/services/java/com/android/server/wm/WindowStateAnimator.java b/services/java/com/android/server/wm/WindowStateAnimator.java
index 7b30c89..10784fe 100644
--- a/services/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/java/com/android/server/wm/WindowStateAnimator.java
@@ -14,6 +14,7 @@
 import android.graphics.Rect;
 import android.graphics.Region;
 import android.os.Debug;
+import android.os.UserHandle;
 import android.util.Slog;
 import android.view.DisplayInfo;
 import android.view.Surface;
@@ -803,7 +804,7 @@
 
             mSurfaceShown = false;
             mSurface = null;
-            mWin.mHasSurface =false;
+            mWin.mHasSurface = false;
             mDrawState = NO_SURFACE;
         }
     }
@@ -876,7 +877,7 @@
             final Matrix tmpMatrix = mWin.mTmpMatrix;
 
             // Compute the desired transformation.
-            if (screenAnimation) {
+            if (screenAnimation && screenRotationAnimation.isRotating()) {
                 // If we are doing a screen animation, the global rotation
                 // applied to windows can result in windows that are carefully
                 // aligned with each other to slightly separate, allowing you
@@ -1533,7 +1534,8 @@
                         break;
                 }
                 if (attr >= 0) {
-                    a = mService.loadAnimation(mWin.mAttrs, attr);
+                    a = mService.loadAnimation(UserHandle.getUserId(mWin.mOwnerUid),
+                            mWin.mAttrs, attr);
                 }
             }
             if (WindowManagerService.DEBUG_ANIM) Slog.v(TAG,
diff --git a/services/java/com/android/server/wm/WindowToken.java b/services/java/com/android/server/wm/WindowToken.java
index e581915..bd0ace8 100644
--- a/services/java/com/android/server/wm/WindowToken.java
+++ b/services/java/com/android/server/wm/WindowToken.java
@@ -48,7 +48,7 @@
     AppWindowToken appWindowToken;
 
     // All of the windows associated with this token.
-    final ArrayList<WindowState> windows = new ArrayList<WindowState>();
+    final WindowList windows = new WindowList();
 
     // Is key dispatching paused for this token?
     boolean paused = false;
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
index 5f93e6f..0f531b7 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
@@ -139,7 +139,7 @@
         // Write the package files and make sure they're parsed properly the first time
         writeOldFiles();
         Settings settings = new Settings(getContext(), getContext().getFilesDir());
-        assertEquals(true, settings.readLPw(null));
+        assertEquals(true, settings.readLPw(null, 0, false));
         assertNotNull(settings.peekPackageLPr(PACKAGE_NAME_3));
         assertNotNull(settings.peekPackageLPr(PACKAGE_NAME_1));
 
@@ -157,11 +157,11 @@
         // Write the package files and make sure they're parsed properly the first time
         writeOldFiles();
         Settings settings = new Settings(getContext(), getContext().getFilesDir());
-        assertEquals(true, settings.readLPw(null));
+        assertEquals(true, settings.readLPw(null, 0, false));
 
         // Create Settings again to make it read from the new files
         settings = new Settings(getContext(), getContext().getFilesDir());
-        assertEquals(true, settings.readLPw(null));
+        assertEquals(true, settings.readLPw(null, 0, false));
 
         PackageSetting ps = settings.peekPackageLPr(PACKAGE_NAME_2);
         assertEquals(COMPONENT_ENABLED_STATE_DISABLED_USER, ps.getEnabled(0));
@@ -172,7 +172,7 @@
         // Write the package files and make sure they're parsed properly the first time
         writeOldFiles();
         Settings settings = new Settings(getContext(), getContext().getFilesDir());
-        assertEquals(true, settings.readLPw(null));
+        assertEquals(true, settings.readLPw(null, 0, false));
 
         // Enable/Disable a package
         PackageSetting ps = settings.peekPackageLPr(PACKAGE_NAME_1);
diff --git a/telephony/java/com/android/internal/telephony/GsmAlphabet.java b/telephony/java/com/android/internal/telephony/GsmAlphabet.java
index 04b1220..ba14ea7 100644
--- a/telephony/java/com/android/internal/telephony/GsmAlphabet.java
+++ b/telephony/java/com/android/internal/telephony/GsmAlphabet.java
@@ -803,6 +803,10 @@
      */
     public static TextEncodingDetails
     countGsmSeptets(CharSequence s, boolean use7bitOnly) {
+        // Load enabled language tables from config.xml, including any MCC overlays
+        if (!sDisableCountryEncodingCheck) {
+            enableCountrySpecificEncodings();
+        }
         // fast path for common case where no national language shift tables are enabled
         if (sEnabledSingleShiftTables.length + sEnabledLockingShiftTables.length == 0) {
             TextEncodingDetails ted = new TextEncodingDetails();
@@ -989,6 +993,7 @@
      */
     static synchronized void setEnabledSingleShiftTables(int[] tables) {
         sEnabledSingleShiftTables = tables;
+        sDisableCountryEncodingCheck = true;
 
         if (tables.length > 0) {
             sHighestEnabledSingleShiftCode = tables[tables.length - 1];
@@ -1006,6 +1011,7 @@
      */
     static synchronized void setEnabledLockingShiftTables(int[] tables) {
         sEnabledLockingShiftTables = tables;
+        sDisableCountryEncodingCheck = true;
     }
 
     /**
@@ -1030,6 +1036,24 @@
         return sEnabledLockingShiftTables;
     }
 
+    /**
+     * Enable country-specific language tables from MCC-specific overlays.
+     * @context the context to use to get the TelephonyManager
+     */
+    private static void enableCountrySpecificEncodings() {
+        Resources r = Resources.getSystem();
+        // See comments in frameworks/base/core/res/res/values/config.xml for allowed values
+        sEnabledSingleShiftTables = r.getIntArray(R.array.config_sms_enabled_single_shift_tables);
+        sEnabledLockingShiftTables = r.getIntArray(R.array.config_sms_enabled_locking_shift_tables);
+
+        if (sEnabledSingleShiftTables.length > 0) {
+            sHighestEnabledSingleShiftCode =
+                    sEnabledSingleShiftTables[sEnabledSingleShiftTables.length-1];
+        } else {
+            sHighestEnabledSingleShiftCode = 0;
+        }
+    }
+
     /** Reverse mapping from Unicode characters to indexes into language tables. */
     private static final SparseIntArray[] sCharsToGsmTables;
 
@@ -1045,6 +1069,9 @@
     /** Highest language code to include in array of single shift counters. */
     private static int sHighestEnabledSingleShiftCode;
 
+    /** Flag to bypass check for country-specific overlays (for test cases only). */
+    private static boolean sDisableCountryEncodingCheck = false;
+
     /**
      * Septet counter for a specific locking shift table and all of
      * the single shift tables that it can be paired with.
@@ -1408,10 +1435,7 @@
     };
 
     static {
-        Resources r = Resources.getSystem();
-        // See comments in frameworks/base/core/res/res/values/config.xml for allowed values
-        sEnabledSingleShiftTables = r.getIntArray(R.array.config_sms_enabled_single_shift_tables);
-        sEnabledLockingShiftTables = r.getIntArray(R.array.config_sms_enabled_locking_shift_tables);
+        enableCountrySpecificEncodings();
         int numTables = sLanguageTables.length;
         int numShiftTables = sLanguageShiftTables.length;
         if (numTables != numShiftTables) {
@@ -1419,13 +1443,6 @@
                     " != shift tables array length " + numShiftTables);
         }
 
-        if (sEnabledSingleShiftTables.length > 0) {
-            sHighestEnabledSingleShiftCode =
-                    sEnabledSingleShiftTables[sEnabledSingleShiftTables.length-1];
-        } else {
-            sHighestEnabledSingleShiftCode = 0;
-        }
-
         sCharsToGsmTables = new SparseIntArray[numTables];
         for (int i = 0; i < numTables; i++) {
             String table = sLanguageTables[i];
diff --git a/telephony/java/com/android/internal/telephony/IExtendedNetworkService.aidl b/telephony/java/com/android/internal/telephony/IExtendedNetworkService.aidl
deleted file mode 100644
index facdc49..0000000
--- a/telephony/java/com/android/internal/telephony/IExtendedNetworkService.aidl
+++ /dev/null
@@ -1,31 +0,0 @@
-package com.android.internal.telephony;
-
-/**
- * Interface used to interact with extended MMI/USSD network service.
- */
-interface IExtendedNetworkService {
-    /**
-     * Set a MMI/USSD command to ExtendedNetworkService for further process.
-     * This should be called when a MMI command is placed from panel.
-     * @param number the dialed MMI/USSD number.
-     */
-    void setMmiString(String number);
-
-    /**
-     * return the specific string which is used to prompt MMI/USSD is running
-     */
-    CharSequence getMmiRunningText();
-
-    /**
-     * Get specific message which should be displayed on pop-up dialog.
-     * @param text original MMI/USSD message response from framework
-     * @return specific user message correspond to text. null stands for no pop-up dialog need to show.
-     */
-    CharSequence getUserMessage(CharSequence text);
-
-    /**
-     * Clear pre-set MMI/USSD command.
-     * This should be called when user cancel a pre-dialed MMI command.
-     */
-    void clearMmiString();
-}
diff --git a/tests/AppLaunch/Android.mk b/tests/AppLaunch/Android.mk
new file mode 100644
index 0000000..c0560fd
--- /dev/null
+++ b/tests/AppLaunch/Android.mk
@@ -0,0 +1,17 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+# Only compile source java files in this apk.
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := AppLaunch
+
+LOCAL_CERTIFICATE := platform
+LOCAL_JAVA_LIBRARIES := android.test.runner
+
+include $(BUILD_PACKAGE)
+
+# Use the following include to make our test apk.
+include $(call all-makefiles-under,$(LOCAL_PATH))
\ No newline at end of file
diff --git a/tests/AppLaunch/AndroidManifest.xml b/tests/AppLaunch/AndroidManifest.xml
new file mode 100644
index 0000000..ac6760b
--- /dev/null
+++ b/tests/AppLaunch/AndroidManifest.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.tests.applaunch"
+    android:sharedUserId="android.uid.system" >
+    <instrumentation android:label="Measure app start up time"
+                     android:name="android.test.InstrumentationTestRunner"
+                     android:targetPackage="com.android.tests.applaunch" />
+
+    <application android:label="App Launch Test">
+        <uses-library android:name="android.test.runner" />
+    </application>
+</manifest>
\ No newline at end of file
diff --git a/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java b/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
new file mode 100644
index 0000000..e2cb65d
--- /dev/null
+++ b/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.tests.applaunch;
+
+import android.app.ActivityManager;
+import android.app.ActivityManager.ProcessErrorStateInfo;
+import android.app.ActivityManagerNative;
+import android.app.IActivityManager;
+import android.app.IActivityManager.WaitResult;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ResolveInfo;
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.test.InstrumentationTestCase;
+import android.test.InstrumentationTestRunner;
+import android.util.Log;
+
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * This test is intended to measure the time it takes for the apps to start.
+ * Names of the applications are passed in command line, and the
+ * test starts each application, and reports the start up time in milliseconds.
+ * The instrumentation expects the following key to be passed on the command line:
+ * apps - A list of applications to start and their corresponding result keys
+ * in the following format:
+ * -e apps <app name>^<result key>|<app name>^<result key>
+ */
+public class AppLaunch extends InstrumentationTestCase {
+
+    private static final int JOIN_TIMEOUT = 10000;
+    private static final String TAG = "AppLaunch";
+    private static final String KEY_APPS = "apps";
+
+    private Map<String, Intent> mNameToIntent;
+    private Map<String, String> mNameToProcess;
+    private Map<String, String> mNameToResultKey;
+
+    private IActivityManager mAm;
+
+    public void testMeasureStartUpTime() throws RemoteException {
+        InstrumentationTestRunner instrumentation =
+                (InstrumentationTestRunner)getInstrumentation();
+        Bundle args = instrumentation.getBundle();
+        mAm = ActivityManagerNative.getDefault();
+
+        createMappings();
+        parseArgs(args);
+
+        Bundle results = new Bundle();
+        for (String app : mNameToResultKey.keySet()) {
+            try {
+                startApp(app, results);
+                sleep(750);
+                closeApp(app);
+                sleep(2000);
+            } catch (NameNotFoundException e) {
+                Log.i(TAG, "Application " + app + " not found");
+            }
+
+        }
+        instrumentation.sendStatus(0, results);
+    }
+
+    private void parseArgs(Bundle args) {
+        mNameToResultKey = new LinkedHashMap<String, String>();
+        String appList = args.getString(KEY_APPS);
+
+        if (appList == null)
+            return;
+
+        String appNames[] = appList.split("\\|");
+        for (String pair : appNames) {
+            String[] parts = pair.split("\\^");
+            if (parts.length != 2) {
+                Log.e(TAG, "The apps key is incorectly formatted");
+                fail();
+            }
+
+            mNameToResultKey.put(parts[0], parts[1]);
+        }
+    }
+
+    private void createMappings() {
+        mNameToIntent = new LinkedHashMap<String, Intent>();
+        mNameToProcess = new LinkedHashMap<String, String>();
+
+        PackageManager pm = getInstrumentation().getContext()
+                .getPackageManager();
+        Intent intentToResolve = new Intent(Intent.ACTION_MAIN);
+        intentToResolve.addCategory(Intent.CATEGORY_LAUNCHER);
+        List<ResolveInfo> ris = pm.queryIntentActivities(intentToResolve, 0);
+        if (ris == null || ris.isEmpty()) {
+            Log.i(TAG, "Could not find any apps");
+        } else {
+            for (ResolveInfo ri : ris) {
+                Intent startIntent = new Intent(intentToResolve);
+                startIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+                        | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+                startIntent.setClassName(ri.activityInfo.packageName,
+                        ri.activityInfo.name);
+                mNameToIntent.put(ri.loadLabel(pm).toString(), startIntent);
+                mNameToProcess.put(ri.loadLabel(pm).toString(),
+                        ri.activityInfo.processName);
+            }
+        }
+    }
+
+    private void startApp(String appName, Bundle results)
+            throws NameNotFoundException, RemoteException {
+        Log.i(TAG, "Starting " + appName);
+
+        Intent startIntent = mNameToIntent.get(appName);
+        if (startIntent == null) {
+            Log.w(TAG, "App does not exist: " + appName);
+            return;
+        }
+        AppLaunchRunnable runnable = new AppLaunchRunnable(startIntent);
+        Thread t = new Thread(runnable);
+        t.start();
+        try {
+            t.join(JOIN_TIMEOUT);
+        } catch (InterruptedException e) {
+            // ignore
+        }
+        WaitResult result = runnable.getResult();
+        if(t.isAlive() || (result != null && result.result != ActivityManager.START_SUCCESS)) {
+            Log.w(TAG, "Assuming app " + appName + " crashed.");
+            reportError(appName, mNameToProcess.get(appName), results);
+            return;
+        }
+        results.putString(mNameToResultKey.get(appName), String.valueOf(result.thisTime));
+    }
+
+    private void closeApp(String appName) {
+        Intent homeIntent = new Intent(Intent.ACTION_MAIN);
+        homeIntent.addCategory(Intent.CATEGORY_HOME);
+        homeIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+                | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+        getInstrumentation().getContext().startActivity(homeIntent);
+        Intent startIntent = mNameToIntent.get(appName);
+        if (startIntent != null) {
+            String packageName = startIntent.getComponent().getPackageName();
+            try {
+                mAm.forceStopPackage(packageName, UserHandle.USER_CURRENT);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Error closing app", e);
+            }
+        }
+    }
+
+    private void sleep(int time) {
+        try {
+            Thread.sleep(time);
+        } catch (InterruptedException e) {
+            // ignore
+        }
+    }
+
+    private void reportError(String appName, String processName, Bundle results) {
+        ActivityManager am = (ActivityManager) getInstrumentation()
+                .getContext().getSystemService(Context.ACTIVITY_SERVICE);
+        List<ProcessErrorStateInfo> crashes = am.getProcessesInErrorState();
+        if (crashes != null) {
+            for (ProcessErrorStateInfo crash : crashes) {
+                if (!crash.processName.equals(processName))
+                    continue;
+
+                Log.w(TAG, appName + " crashed: " + crash.shortMsg);
+                results.putString(mNameToResultKey.get(appName), crash.shortMsg);
+                return;
+            }
+        }
+
+        results.putString(mNameToResultKey.get(appName),
+                "Crashed for unknown reason");
+        Log.w(TAG, appName
+                + " not found in process list, most likely it is crashed");
+    }
+
+    private class AppLaunchRunnable implements Runnable {
+        private Intent mLaunchIntent;
+        private IActivityManager.WaitResult mResult;
+        public AppLaunchRunnable(Intent intent) {
+            mLaunchIntent = intent;
+        }
+
+        public IActivityManager.WaitResult getResult() {
+            return mResult;
+        }
+
+        public void run() {
+            try {
+                String packageName = mLaunchIntent.getComponent().getPackageName();
+                mAm.forceStopPackage(packageName, UserHandle.USER_CURRENT);
+                String mimeType = mLaunchIntent.getType();
+                if (mimeType == null && mLaunchIntent.getData() != null
+                        && "content".equals(mLaunchIntent.getData().getScheme())) {
+                    mimeType = mAm.getProviderMimeType(mLaunchIntent.getData(),
+                            UserHandle.USER_CURRENT);
+                }
+
+                mResult = mAm.startActivityAndWait(null, mLaunchIntent, mimeType,
+                        null, null, 0, mLaunchIntent.getFlags(), null, null, null,
+                        UserHandle.USER_CURRENT);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Error launching app", e);
+            }
+        }
+    }
+}
diff --git a/tests/MemoryUsage/Android.mk b/tests/MemoryUsage/Android.mk
index e7bfb4f..0ab793b 100644
--- a/tests/MemoryUsage/Android.mk
+++ b/tests/MemoryUsage/Android.mk
@@ -8,7 +8,8 @@
 
 LOCAL_PACKAGE_NAME := MemoryUsage
 
-LOCAL_SDK_VERSION := 7
+LOCAL_CERTIFICATE := platform
+LOCAL_JAVA_LIBRARIES := android.test.runner
 
 include $(BUILD_PACKAGE)
 
diff --git a/tests/MemoryUsage/src/com/android/tests/memoryusage/MemoryUsageTest.java b/tests/MemoryUsage/src/com/android/tests/memoryusage/MemoryUsageTest.java
index 5e27ba7..b550957 100644
--- a/tests/MemoryUsage/src/com/android/tests/memoryusage/MemoryUsageTest.java
+++ b/tests/MemoryUsage/src/com/android/tests/memoryusage/MemoryUsageTest.java
@@ -18,14 +18,17 @@
 import android.app.ActivityManager;
 import android.app.ActivityManager.ProcessErrorStateInfo;
 import android.app.ActivityManager.RunningAppProcessInfo;
+import android.app.ActivityManagerNative;
+import android.app.IActivityManager;
 import android.content.Context;
 import android.content.Intent;
-import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.ResolveInfo;
 import android.os.Bundle;
 import android.os.Debug.MemoryInfo;
+import android.os.RemoteException;
+import android.os.UserHandle;
 import android.test.InstrumentationTestCase;
 import android.util.Log;
 
@@ -48,8 +51,9 @@
 
     private static final int SLEEP_TIME = 1000;
     private static final int THRESHOLD = 1024;
-    private static final int MAX_ITERATIONS = 10;
-    private static final int MIN_ITERATIONS = 4;
+    private static final int MAX_ITERATIONS = 20;
+    private static final int MIN_ITERATIONS = 6;
+    private static final int JOIN_TIMEOUT = 10000;
 
     private static final String TAG = "MemoryUsageInstrumentation";
     private static final String KEY_APPS = "apps";
@@ -58,10 +62,13 @@
     private Map<String, String> mNameToProcess;
     private Map<String, String> mNameToResultKey;
 
+    private IActivityManager mAm;
+
     public void testMemory() {
         MemoryUsageInstrumentation instrumentation =
-                    (MemoryUsageInstrumentation) getInstrumentation();
+                (MemoryUsageInstrumentation) getInstrumentation();
         Bundle args = instrumentation.getBundle();
+        mAm = ActivityManagerNative.getDefault();
 
         createMappings();
         parseArgs(args);
@@ -136,7 +143,16 @@
 
         String process = mNameToProcess.get(appName);
         Intent startIntent = mNameToIntent.get(appName);
-        getInstrumentation().getContext().startActivity(startIntent);
+
+        AppLaunchRunnable runnable = new AppLaunchRunnable(startIntent);
+        Thread t = new Thread(runnable);
+        t.start();
+        try {
+            t.join(JOIN_TIMEOUT);
+        } catch (InterruptedException e) {
+            // ignore
+        }
+
         return process;
     }
 
@@ -234,7 +250,7 @@
             }
 
             int[] pids = {
-                proc.pid };
+                    proc.pid };
 
             MemoryInfo meminfo = am.getProcessMemoryInfo(pids)[0];
             return meminfo.getTotalPss();
@@ -242,4 +258,29 @@
         }
         return -1;
     }
+
+    private class AppLaunchRunnable implements Runnable {
+        private Intent mLaunchIntent;
+
+        public AppLaunchRunnable(Intent intent) {
+            mLaunchIntent = intent;
+        }
+
+        public void run() {
+            try {
+                String mimeType = mLaunchIntent.getType();
+                if (mimeType == null && mLaunchIntent.getData() != null
+                        && "content".equals(mLaunchIntent.getData().getScheme())) {
+                    mimeType = mAm.getProviderMimeType(mLaunchIntent.getData(),
+                            UserHandle.USER_CURRENT);
+                }
+
+                mAm.startActivityAndWait(null, mLaunchIntent, mimeType,
+                        null, null, 0, mLaunchIntent.getFlags(), null, null, null,
+                        UserHandle.USER_CURRENT_OR_SELF);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Error launching app", e);
+            }
+        }
+    }
 }
diff --git a/tests/RenderScriptTests/ImageProcessing/AndroidManifest.xml b/tests/RenderScriptTests/ImageProcessing/AndroidManifest.xml
index 2232b98..d51fa39 100644
--- a/tests/RenderScriptTests/ImageProcessing/AndroidManifest.xml
+++ b/tests/RenderScriptTests/ImageProcessing/AndroidManifest.xml
@@ -3,7 +3,7 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.android.rs.image">
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
-    <uses-sdk android:minSdkVersion="11" />
+    <uses-sdk android:minSdkVersion="17" />
     <application android:label="Image Processing"
                  android:hardwareAccelerated="true">
         <uses-library android:name="android.test.runner" />
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/mandelbrot.fs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/mandelbrot.rs
similarity index 100%
rename from tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/mandelbrot.fs
rename to tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/mandelbrot.rs
diff --git a/tests/StatusBar/res/layout/notification_builder_test.xml b/tests/StatusBar/res/layout/notification_builder_test.xml
index 94fc089..5987c84 100644
--- a/tests/StatusBar/res/layout/notification_builder_test.xml
+++ b/tests/StatusBar/res/layout/notification_builder_test.xml
@@ -222,307 +222,320 @@
                 >
 
             <!-- setWhen -->
-            <RadioGroup
-                    android:id="@+id/group_when"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:orientation="horizontal"
-                    >
+            <LinearLayout
+                style="@style/FieldGroup"
+                >
                 <TextView
                         style="@style/FieldTitle"
                         android:text="setWhen"
                         />
-                <RadioButton
-                        android:id="@+id/when_midnight"
-                        style="@style/FieldContents"
-                        android:text="midnight"
-                        />
-                <RadioButton
-                        android:id="@+id/when_now"
-                        style="@style/FieldContents"
-                        android:text="now"
-                        />
-                <RadioButton
-                        android:id="@+id/when_now_plus_1h"
-                        style="@style/FieldContents.Disabled"
-                        android:text="now + 1h"
-                        />
-                <RadioButton
-                        android:id="@+id/when_tomorrow"
-                        style="@style/FieldContents.Disabled"
-                        android:text="tomorrow"
-                        />
-            </RadioGroup>
+	            <RadioGroup
+	                    android:id="@+id/group_when"
+	                    style="@style/FieldChoices"
+	                    >
+	                <RadioButton
+	                        android:id="@+id/when_midnight"
+	                        style="@style/FieldContents"
+	                        android:text="midnight"
+	                        />
+	                <RadioButton
+	                        android:id="@+id/when_now"
+	                        style="@style/FieldContents"
+	                        android:text="now"
+	                        />
+	                <RadioButton
+	                        android:id="@+id/when_now_plus_1h"
+	                        style="@style/FieldContents.Disabled"
+	                        android:text="now + 1h"
+	                        />
+	                <RadioButton
+	                        android:id="@+id/when_tomorrow"
+	                        style="@style/FieldContents.Disabled"
+	                        android:text="tomorrow"
+	                        />
+	            </RadioGroup>
+            </LinearLayout>
 
             <!-- icon -->
-            <RadioGroup
-                    android:id="@+id/group_icon"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:orientation="horizontal"
-                    >
+            <LinearLayout
+                style="@style/FieldGroup"
+                >
                 <TextView
                         style="@style/FieldTitle"
                         android:text="setSmallIcon"
                         />
-                <RadioButton
-                        android:id="@+id/icon_im"
-                        style="@style/FieldContents"
-                        android:text="IM"
-                        />
-                <RadioButton
-                        android:id="@+id/icon_alert"
-                        style="@style/FieldContents"
-                        android:text="alert"
-                        />
-                <RadioButton
-                        android:id="@+id/icon_surprise"
-                        style="@style/FieldContents"
-                        android:text="surprise"
-                        />
-                <RadioButton
-                        android:id="@+id/icon_level0"
-                        style="@style/FieldContents.Disabled"
-                        android:text="level 0"
-                        />
-                <RadioButton
-                        android:id="@+id/icon_level50"
-                        style="@style/FieldContents.Disabled"
-                        android:text="level 50"
-                        />
-                <RadioButton
-                        android:id="@+id/icon_level100"
-                        style="@style/FieldContents.Disabled"
-                        android:text="level 100"
-                        />
-                <!-- todo setSmallIcon(int icon, int level) -->
-            </RadioGroup>
-            
+                <RadioGroup
+                        android:id="@+id/group_icon"
+                        style="@style/FieldChoices"
+                        >
+                    <RadioButton
+                            android:id="@+id/icon_im"
+                            style="@style/FieldContents"
+                            android:text="IM"
+                            />
+                    <RadioButton
+                            android:id="@+id/icon_alert"
+                            style="@style/FieldContents"
+                            android:text="alert"
+                            />
+                    <RadioButton
+                            android:id="@+id/icon_surprise"
+                            style="@style/FieldContents"
+                            android:text="surprise"
+                            />
+                    <RadioButton
+                            android:id="@+id/icon_level0"
+                            style="@style/FieldContents.Disabled"
+                            android:text="level 0"
+                            />
+                    <RadioButton
+                            android:id="@+id/icon_level50"
+                            style="@style/FieldContents.Disabled"
+                            android:text="level 50"
+                            />
+                    <RadioButton
+                            android:id="@+id/icon_level100"
+                            style="@style/FieldContents.Disabled"
+                            android:text="level 100"
+                            />
+                    <!-- todo setSmallIcon(int icon, int level) -->
+                </RadioGroup>
+            </LinearLayout>
+
             <!-- setContentTitle -->
-            <RadioGroup
-                    android:id="@+id/group_title"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:orientation="horizontal"
-                    >
+            <LinearLayout
+                style="@style/FieldGroup"
+                >
                 <TextView
                         style="@style/FieldTitle"
                         android:text="setContentTitle"
                         />
-                <RadioButton
-                        android:id="@+id/title_short"
-                        style="@style/FieldContents"
-                        android:text="none"
-                        android:tag=""
-                        />
-                <RadioButton
-                        android:id="@+id/title_short"
-                        style="@style/FieldContents"
-                        android:text="short"
-                        android:tag="Title"
-                        />
-                <RadioButton
-                        android:id="@+id/title_medium"
-                        style="@style/FieldContents"
-                        android:text="medium"
-                        android:tag="Notification Test"
-                        />
-                <RadioButton
-                        android:id="@+id/title_long"
-                        style="@style/FieldContents"
-                        android:text="long"
-                        android:tag="This is one heckuva long title for a notification"
-                        />
-            </RadioGroup>
-            
+                <RadioGroup
+                        android:id="@+id/group_title"
+                        style="@style/FieldChoices"
+                        >
+                    <RadioButton
+                            android:id="@+id/title_short"
+                            style="@style/FieldContents"
+                            android:text="none"
+                            android:tag=""
+                            />
+                    <RadioButton
+                            android:id="@+id/title_short"
+                            style="@style/FieldContents"
+                            android:text="short"
+                            android:tag="Title"
+                            />
+                    <RadioButton
+                            android:id="@+id/title_medium"
+                            style="@style/FieldContents"
+                            android:text="medium"
+                            android:tag="Notification Test"
+                            />
+                    <RadioButton
+                            android:id="@+id/title_long"
+                            style="@style/FieldContents"
+                            android:text="long"
+                            android:tag="This is one heckuva long title for a notification"
+                            />
+                </RadioGroup>
+            </LinearLayout>
+
             <!-- setContentText -->
-            <RadioGroup
-                    android:id="@+id/group_text"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:orientation="horizontal"
-                    >
+            <LinearLayout
+                style="@style/FieldGroup"
+                >
                 <TextView
                         style="@style/FieldTitle"
                         android:text="setContentText"
                         />
-                <RadioButton
-                        android:id="@+id/text_none"
-                        style="@style/FieldContents"
-                        android:text="none"
-                        android:tag=""
-                        />
-                <RadioButton
-                        android:id="@+id/text_short"
-                        style="@style/FieldContents"
-                        android:tag="short"
-                        android:text="text"
-                        />
-                <RadioButton
-                        android:id="@+id/text_medium"
-                        style="@style/FieldContents"
-                        android:text="medium"
-                        android:tag="Something happened"
-                        />
-                <RadioButton
-                        android:id="@+id/text_long"
-                        style="@style/FieldContents"
-                        android:text="long"
-                        android:tag="Oh my goodness.  SOMETHING HAPPENED!!!!"
-                        />
-                <RadioButton
-                        android:id="@+id/text_emoji"
-                        style="@style/FieldContents"
-                        android:text="emoji"
-                        android:tag="_ Cactus _ Cactus _"
-                        />
-                <RadioButton
-                        android:id="@+id/text_haiku"
-                        style="@style/FieldContents"
-                        android:text="haiku"
-                        android:tag="sholes final approach\nlanding gear punted to flan\nrunway foam glistens"
-                        />
-            </RadioGroup>
+                <RadioGroup
+                        android:id="@+id/group_text"
+                        style="@style/FieldChoices"
+                        >
+                    <RadioButton
+                            android:id="@+id/text_none"
+                            style="@style/FieldContents"
+                            android:text="none"
+                            android:tag=""
+                            />
+                    <RadioButton
+                            android:id="@+id/text_short"
+                            style="@style/FieldContents"
+                            android:tag="short"
+                            android:text="text"
+                            />
+                    <RadioButton
+                            android:id="@+id/text_medium"
+                            style="@style/FieldContents"
+                            android:text="medium"
+                            android:tag="Something happened"
+                            />
+                    <RadioButton
+                            android:id="@+id/text_long"
+                            style="@style/FieldContents"
+                            android:text="long"
+                            android:tag="Oh my goodness.  SOMETHING HAPPENED!!!!"
+                            />
+                    <RadioButton
+                            android:id="@+id/text_emoji"
+                            style="@style/FieldContents"
+                            android:text="emoji"
+                            android:tag="_ Cactus _ Cactus _"
+                            />
+                    <RadioButton
+                            android:id="@+id/text_haiku"
+                            style="@style/FieldContents"
+                            android:text="haiku"
+                            android:tag="sholes final approach\nlanding gear punted to flan\nrunway foam glistens"
+                            />
+                </RadioGroup>
+            </LinearLayout>
 
             <!-- setContentInfo -->
-            <RadioGroup
-                    android:id="@+id/group_info"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:orientation="horizontal"
-                    >
+            <LinearLayout
+                style="@style/FieldGroup"
+                >
                 <TextView
                         style="@style/FieldTitle"
                         android:text="setContentInfo"
                         />
-                <RadioButton
-                        android:id="@+id/info_none"
-                        style="@style/FieldContents"
-                        android:text="none"
-                        android:tag=""
-                        />
-                <RadioButton
-                        android:id="@+id/info_number"
-                        style="@style/FieldContents"
-                        android:text="snoozed"
-                        android:tag="snoozed"
-                        />
-                <RadioButton
-                        android:id="@+id/info_long"
-                        style="@style/FieldContents"
-                        android:text="longer"
-                        android:tag="this content info is way too long"
-                        />
-            </RadioGroup>
+                <RadioGroup
+                        android:id="@+id/group_info"
+                        style="@style/FieldChoices"
+                        >
+                    <RadioButton
+                            android:id="@+id/info_none"
+                            style="@style/FieldContents"
+                            android:text="none"
+                            android:tag=""
+                            />
+                    <RadioButton
+                            android:id="@+id/info_number"
+                            style="@style/FieldContents"
+                            android:text="snoozed"
+                            android:tag="snoozed"
+                            />
+                    <RadioButton
+                            android:id="@+id/info_long"
+                            style="@style/FieldContents"
+                            android:text="longer"
+                            android:tag="this content info is way too long"
+                            />
+                </RadioGroup>
+            </LinearLayout>
 
             <!-- setNumber -->
-            <RadioGroup
-                    android:id="@+id/group_number"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:orientation="horizontal"
-                    >
+            <LinearLayout
+                style="@style/FieldGroup"
+                >
                 <TextView
                         style="@style/FieldTitle"
                         android:text="setNumber"
                         />
-                <RadioButton
-                        android:id="@+id/number_0"
-                        style="@style/FieldContents"
-                        android:text="0"
-                        android:tag="0"
-                        />
-                <RadioButton
-                        android:id="@+id/number_1"
-                        style="@style/FieldContents"
-                        android:text="1"
-                        android:tag="1"
-                        />
-                <RadioButton
-                        android:id="@+id/number_42"
-                        style="@style/FieldContents"
-                        android:text="42"
-                        android:tag="42"
-                        />
-                <RadioButton
-                        android:id="@+id/number_334"
-                        style="@style/FieldContents"
-                        android:text="334"
-                        android:tag="334"
-                        />
-                <RadioButton
-                        android:id="@+id/number_999"
-                        style="@style/FieldContents"
-                        android:text="999"
-                        android:tag="999"
-                        />
-                <RadioButton
-                        android:id="@+id/number_9876"
-                        style="@style/FieldContents"
-                        android:text="9,876"
-                        android:tag="9876"
-                        />
-                <RadioButton
-                        android:id="@+id/number_12345"
-                        style="@style/FieldContents"
-                        android:text="12,345"
-                        android:tag="12345"
-                        />
-            </RadioGroup>
-            
+                <RadioGroup
+                        android:id="@+id/group_number"
+                        style="@style/FieldChoices"
+                        >
+                    <RadioButton
+                            android:id="@+id/number_0"
+                            style="@style/FieldContents"
+                            android:text="0"
+                            android:tag="0"
+                            />
+                    <RadioButton
+                            android:id="@+id/number_1"
+                            style="@style/FieldContents"
+                            android:text="1"
+                            android:tag="1"
+                            />
+                    <RadioButton
+                            android:id="@+id/number_42"
+                            style="@style/FieldContents"
+                            android:text="42"
+                            android:tag="42"
+                            />
+                    <RadioButton
+                            android:id="@+id/number_334"
+                            style="@style/FieldContents"
+                            android:text="334"
+                            android:tag="334"
+                            />
+                    <RadioButton
+                            android:id="@+id/number_999"
+                            style="@style/FieldContents"
+                            android:text="999"
+                            android:tag="999"
+                            />
+                    <RadioButton
+                            android:id="@+id/number_9876"
+                            style="@style/FieldContents"
+                            android:text="9,876"
+                            android:tag="9876"
+                            />
+                    <RadioButton
+                            android:id="@+id/number_12345"
+                            style="@style/FieldContents"
+                            android:text="12,345"
+                            android:tag="12345"
+                            />
+                </RadioGroup>
+            </LinearLayout>
+
             <!-- setContentIntent -->
-            <RadioGroup
-                    android:id="@+id/group_intent"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:orientation="horizontal"
-                    >
+            <LinearLayout
+                style="@style/FieldGroup"
+                >
                 <TextView
                         style="@style/FieldTitle"
                         android:text="setContentIntent"
                         />
-                <RadioButton
-                        android:id="@+id/intent_none"
-                        style="@style/FieldContents"
-                        android:text="none"
-                        />
-                <RadioButton
-                        android:id="@+id/intent_alert"
-                        style="@style/FieldContents"
-                        android:text="alert"
-                        />
-            </RadioGroup>
-            
+                <RadioGroup
+                        android:id="@+id/group_intent"
+                        style="@style/FieldChoices"
+                        >
+                    <RadioButton
+                            android:id="@+id/intent_none"
+                            style="@style/FieldContents"
+                            android:text="none"
+                            />
+                    <RadioButton
+                            android:id="@+id/intent_alert"
+                            style="@style/FieldContents"
+                            android:text="alert"
+                            />
+                </RadioGroup>
+            </LinearLayout>
+
             <!-- setDeleteIntent -->
-            <RadioGroup
-                    android:id="@+id/group_delete"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:orientation="horizontal"
-                    >
+            <LinearLayout
+                style="@style/FieldGroup"
+                >
                 <TextView
                         style="@style/FieldTitle"
                         android:text="setDeleteIntent"
                         />
-                <RadioButton
-                        android:id="@+id/delete_none"
-                        style="@style/FieldContents"
-                        android:text="none"
-                        />
-                <RadioButton
-                        android:id="@+id/delete_alert"
-                        style="@style/FieldContents"
-                        android:text="alert"
-                        />
-            </RadioGroup>
-            
+                <RadioGroup
+                        android:id="@+id/group_delete"
+                        style="@style/FieldChoices"
+                        >
+                    <RadioButton
+                            android:id="@+id/delete_none"
+                            style="@style/FieldContents"
+                            android:text="none"
+                            />
+                    <RadioButton
+                            android:id="@+id/delete_alert"
+                            style="@style/FieldContents"
+                            android:text="alert"
+                            />
+                </RadioGroup>
+            </LinearLayout>
 
             <!-- setFullScreenIntent -->
             <RadioGroup
                     android:id="@+id/group_full_screen"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:orientation="horizontal"
+                    style="@style/FieldChoices"
                     android:visibility="gone"
                     >
                 <TextView
@@ -543,94 +556,94 @@
             
 
             <!-- setTicker -->
-            <RadioGroup
-                    android:id="@+id/group_ticker"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:orientation="horizontal"
-                    >
+            <LinearLayout
+                style="@style/FieldGroup"
+                >
                 <TextView
                         style="@style/FieldTitle"
                         android:text="setTicker"
                         />
-                <RadioButton
-                        android:id="@+id/ticker_none"
-                        style="@style/FieldContents"
-                        android:text="none"
-                        android:tag=""
-                        />
-                <RadioButton
-                        android:id="@+id/ticker_short"
-                        style="@style/FieldContents"
-                        android:text="short"
-                        android:tag="tick"
-                        />
-                <RadioButton
-                        android:id="@+id/ticker_wrap"
-                        style="@style/FieldContents"
-                        android:text="wrap"
-                        android:tag="tick tick tick tock tock tock something fun has happened but i don't know what it is just yet"
-                        />
-                <RadioButton
-                        android:id="@+id/ticker_haiku"
-                        style="@style/FieldContents"
-                        android:text="haiku"
-                        android:tag="sholes final approach\nlanding gear punted to flan\nrunway foam glistens"
-                        />
-                <RadioButton
-                        android:id="@+id/ticker_emoji"
-                        style="@style/FieldContents"
-                        android:text="emoji"
-                        android:tag="_ Cactus _ Cactus _"
-                        />
-                <RadioButton
-                        android:id="@+id/ticker_custom"
-                        style="@style/FieldContents.Disabled"
-                        android:text="custom view"
-                        />
-            </RadioGroup>
-            
+                <RadioGroup
+                        android:id="@+id/group_ticker"
+                        style="@style/FieldChoices"
+                        >
+                    <RadioButton
+                            android:id="@+id/ticker_none"
+                            style="@style/FieldContents"
+                            android:text="none"
+                            android:tag=""
+                            />
+                    <RadioButton
+                            android:id="@+id/ticker_short"
+                            style="@style/FieldContents"
+                            android:text="short"
+                            android:tag="tick"
+                            />
+                    <RadioButton
+                            android:id="@+id/ticker_wrap"
+                            style="@style/FieldContents"
+                            android:text="wrap"
+                            android:tag="tick tick tick tock tock tock something fun has happened but i don't know what it is just yet"
+                            />
+                    <RadioButton
+                            android:id="@+id/ticker_haiku"
+                            style="@style/FieldContents"
+                            android:text="haiku"
+                            android:tag="sholes final approach\nlanding gear punted to flan\nrunway foam glistens"
+                            />
+                    <RadioButton
+                            android:id="@+id/ticker_emoji"
+                            style="@style/FieldContents"
+                            android:text="emoji"
+                            android:tag="_ Cactus _ Cactus _"
+                            />
+                    <RadioButton
+                            android:id="@+id/ticker_custom"
+                            style="@style/FieldContents.Disabled"
+                            android:text="custom view"
+                            />
+                </RadioGroup>
+            </LinearLayout>
 
             <!-- setLargeIcon -->
-            <RadioGroup
-                    android:id="@+id/group_large_icon"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:orientation="horizontal"
-                    >
+            <LinearLayout
+                style="@style/FieldGroup"
+                >
                 <TextView
                         style="@style/FieldTitle"
                         android:text="setLargeIcon"
                         />
-                <RadioButton
-                        android:id="@+id/large_icon_none"
-                        style="@style/FieldContents"
-                        android:text="none"
-                        />
-                <RadioButton
-                        android:id="@+id/large_icon_pineapple"
-                        style="@style/FieldContents"
-                        android:text="pineapple"
-                        />
-                <RadioButton
-                        android:id="@+id/large_icon_pineapple2"
-                        style="@style/FieldContents"
-                        android:text="pineapple2"
-                        />
-                <RadioButton
-                        android:id="@+id/large_icon_small"
-                        style="@style/FieldContents"
-                        android:text="small"
-                        />
-            </RadioGroup>
-            
+                <RadioGroup
+                        android:id="@+id/group_large_icon"
+                        style="@style/FieldChoices"
+                        >
+                    <RadioButton
+                            android:id="@+id/large_icon_none"
+                            style="@style/FieldContents"
+                            android:text="none"
+                            />
+                    <RadioButton
+                            android:id="@+id/large_icon_pineapple"
+                            style="@style/FieldContents"
+                            android:text="pineapple"
+                            />
+                    <RadioButton
+                            android:id="@+id/large_icon_pineapple2"
+                            style="@style/FieldContents"
+                            android:text="pineapple2"
+                            />
+                    <RadioButton
+                            android:id="@+id/large_icon_small"
+                            style="@style/FieldContents"
+                            android:text="small"
+                            />
+                </RadioGroup>
+            </LinearLayout>
 
             <!-- setSound -->
             <RadioGroup
                     android:id="@+id/group_sound"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:orientation="horizontal"
+                    style="@style/FieldChoices"
                     android:visibility="gone"
                     >
                 <TextView
@@ -646,190 +659,260 @@
             
 
             <!-- setVibrate -->
-            <RadioGroup
-                    android:id="@+id/group_vibrate"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:orientation="horizontal"
-                    >
+            <LinearLayout
+                style="@style/FieldGroup"
+                >
                 <TextView
                         style="@style/FieldTitle"
                         android:text="setVibrate"
                         />
-                <RadioButton
-                        android:id="@+id/vibrate_none"
-                        style="@style/FieldContents"
-                        android:text="none"
-                        />
-                <RadioButton
-                        android:id="@+id/vibrate_short"
-                        style="@style/FieldContents"
-                        android:text="short"
-                        />
-                <RadioButton
-                        android:id="@+id/vibrate_medium"
-                        style="@style/FieldContents"
-                        android:text="long"
-                        />
-                <RadioButton
-                        android:id="@+id/vibrate_long"
-                        style="@style/FieldContents"
-                        android:text="long"
-                        />
-                <RadioButton
-                        android:id="@+id/vibrate_pattern"
-                        style="@style/FieldContents"
-                        android:text="longer"
-                        />
-            </RadioGroup>
-            
+	            <RadioGroup
+	                    android:id="@+id/group_vibrate"
+	                    style="@style/FieldChoices"
+	                    >
+	                <RadioButton
+	                        android:id="@+id/vibrate_none"
+	                        style="@style/FieldContents"
+	                        android:text="none"
+	                        />
+	                <RadioButton
+	                        android:id="@+id/vibrate_zero"
+	                        style="@style/FieldContents"
+	                        android:text="0"
+	                        />
+	                <RadioButton
+	                        android:id="@+id/vibrate_short"
+	                        style="@style/FieldContents"
+	                        android:text="100"
+	                        />
+	                <RadioButton
+	                        android:id="@+id/vibrate_long"
+	                        style="@style/FieldContents"
+	                        android:text="1000"
+	                        />
+	                <RadioButton
+	                        android:id="@+id/vibrate_pattern"
+	                        style="@style/FieldContents"
+	                        android:text="...---..."
+	                        />
+	            </RadioGroup>
+			</LinearLayout>            
 
             <!-- setLights -->
-            <RadioGroup
-                    android:id="@+id/group_lights_color"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:orientation="horizontal"
-                    >
+            <LinearLayout
+                style="@style/FieldGroup"
+                >
                 <TextView
                         style="@style/FieldTitle"
                         android:text="setLights (color)"
                         />
-                <RadioButton
-                        android:id="@+id/lights_red"
-                        style="@style/FieldContents"
-                        android:text="red"
-                        android:tag="0xff0000"
+                <RadioGroup
+                        android:id="@+id/group_lights_color"
+                        style="@style/FieldChoices"
+                        >
+                    <RadioButton
+                            android:id="@+id/lights_red"
+                            style="@style/FieldContents"
+                            android:text="red"
+                            android:tag="0xff0000"
+                            />
+                    <RadioButton
+                            android:id="@+id/lights_green"
+                            style="@style/FieldContents"
+                            android:text="green"
+                            android:tag="0x00ff00"
+                            />
+                    <RadioButton
+                            android:id="@+id/lights_blue"
+                            style="@style/FieldContents"
+                            android:text="blue"
+                            android:tag="0x0000ff"
+                            />
+                    <RadioButton
+                            android:id="@+id/lights_cyan"
+                            style="@style/FieldContents"
+                            android:text="cyan"
+                            android:tag="0x00ffff"
+                            />
+                    <RadioButton
+                            android:id="@+id/lights_magenta"
+                            style="@style/FieldContents"
+                            android:text="magenta"
+                            android:tag="0xff00ff"
+                            />
+                    <RadioButton
+                            android:id="@+id/lights_yellow"
+                            style="@style/FieldContents"
+                            android:text="yellow"
+                            android:tag="0xffff00"
+                            />
+                    <RadioButton
+                            android:id="@+id/lights_white"
+                            style="@style/FieldContents"
+                            android:text="white"
+                            android:tag="0xffffff"
+                            />
+                </RadioGroup>
+            </LinearLayout>
+
+            <!-- setPriority -->
+            <LinearLayout
+                style="@style/FieldGroup"
+                >
+                <TextView
+                        style="@style/FieldTitle"
+                        android:text="setPriority"
                         />
-                <RadioButton
-                        android:id="@+id/lights_green"
-                        style="@style/FieldContents"
-                        android:text="green"
-                        android:tag="0x00ff00"
-                        />
-                <RadioButton
-                        android:id="@+id/lights_blue"
-                        style="@style/FieldContents"
-                        android:text="blue"
-                        android:tag="0x0000ff"
-                        />
-                <RadioButton
-                        android:id="@+id/lights_cyan"
-                        style="@style/FieldContents"
-                        android:text="cyan"
-                        android:tag="0x00ffff"
-                        />
-                <RadioButton
-                        android:id="@+id/lights_magenta"
-                        style="@style/FieldContents"
-                        android:text="magenta"
-                        android:tag="0xff00ff"
-                        />
-                <RadioButton
-                        android:id="@+id/lights_yellow"
-                        style="@style/FieldContents"
-                        android:text="yellow"
-                        android:tag="0xffff00"
-                        />
-                <RadioButton
-                        android:id="@+id/lights_white"
-                        style="@style/FieldContents"
-                        android:text="white"
-                        android:tag="0xffffff"
-                        />
-            </RadioGroup>
+	            <RadioGroup
+	                    android:id="@+id/group_priority"
+	                    style="@style/FieldChoices"
+	                    >
+	                <RadioButton
+	                        android:id="@+id/pri_max"
+	                        style="@style/FieldContents"
+	                        android:text="MAX"
+	                        />
+	                <RadioButton
+	                        android:id="@+id/pri_high"
+	                        style="@style/FieldContents"
+	                        android:text="HIGH"
+	                        />
+	                <RadioButton
+	                        android:id="@+id/pri_default"
+	                        style="@style/FieldContents"
+	                        android:text="DEFAULT"
+	                        />
+	                <RadioButton
+	                        android:id="@+id/pri_low"
+	                        style="@style/FieldContents"
+	                        android:text="LOW"
+	                        />
+	                <RadioButton
+	                        android:id="@+id/pri_min"
+	                        style="@style/FieldContents"
+	                        android:text="MIN"
+	                        />
+	            </RadioGroup>
+			</LinearLayout>            
 
             <!-- setLights -->
-            <RadioGroup
-                    android:id="@+id/group_lights_blink"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:orientation="horizontal"
-                    >
+            <LinearLayout
+                style="@style/FieldGroup"
+                >
                 <TextView
                         style="@style/FieldTitle"
                         android:text="setLights (blink)"
                         />
-                <RadioButton
-                        android:id="@+id/lights_off"
-                        style="@style/FieldContents"
-                        android:text="off"
-                        />
-                <RadioButton
-                        android:id="@+id/lights_slow"
-                        style="@style/FieldContents"
-                        android:text="slow"
-                        />
-                <RadioButton
-                        android:id="@+id/lights_fast"
-                        style="@style/FieldContents"
-                        android:text="fast"
-                        />
-                <RadioButton
-                        android:id="@+id/lights_on"
-                        style="@style/FieldContents"
-                        android:text="on"
-                        />
-            </RadioGroup>
-            
+                <RadioGroup
+                        android:id="@+id/group_lights_blink"
+                        style="@style/FieldChoices"
+                        >
+                    <RadioButton
+                            android:id="@+id/lights_off"
+                            style="@style/FieldContents"
+                            android:text="off"
+                            />
+                    <RadioButton
+                            android:id="@+id/lights_slow"
+                            style="@style/FieldContents"
+                            android:text="slow"
+                            />
+                    <RadioButton
+                            android:id="@+id/lights_fast"
+                            style="@style/FieldContents"
+                            android:text="fast"
+                            />
+                    <RadioButton
+                            android:id="@+id/lights_on"
+                            style="@style/FieldContents"
+                            android:text="on"
+                            />
+                </RadioGroup>
+            </LinearLayout>
+
             <!-- flags -->
             <LinearLayout
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:orientation="horizontal"
-                    android:layout_marginTop="12dp"
-                    >
+                style="@style/FieldGroup"
+                android:layout_marginTop="30dp"
+                >
                 <TextView
                         style="@style/FieldTitle"
                         android:text="flags"
                         />
-                <CheckBox
-                        android:id="@+id/flag_ongoing"
-                        style="@style/FieldContents"
-                        android:text="setOngoing"
-                        />
-                <CheckBox
-                        android:id="@+id/flag_once"
-                        style="@style/FieldContents"
-                        android:text="setOnlyAlertOnce"
-                        />
-                <CheckBox
-                        android:id="@+id/flag_auto_cancel"
-                        style="@style/FieldContents"
-                        android:text="setAutoCancel"
-                        />
+                <LinearLayout
+                        style="@style/FieldChoices"
+                        >
+                    <CheckBox
+                            android:id="@+id/flag_ongoing"
+                            style="@style/FieldContents"
+                            android:text="ongoing"
+                            />
+                    <CheckBox
+                            android:id="@+id/flag_once"
+                            style="@style/FieldContents"
+                            android:text="onlyAlertOnce"
+                            />
+                    <CheckBox
+                            android:id="@+id/flag_auto_cancel"
+                            style="@style/FieldContents"
+                            android:text="autoCancel"
+                            />
+                </LinearLayout>
             </LinearLayout>
-            
+
             <!-- defaults -->
             <LinearLayout
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:orientation="horizontal"
-                    >
+                style="@style/FieldGroup"
+                >
                 <TextView
                         style="@style/FieldTitle"
                         android:text="defaults"
                         />
-                <CheckBox
-                        android:id="@+id/default_sound"
-                        style="@style/FieldContents"
-                        android:text="sound"
-                        />
-                <CheckBox
-                        android:id="@+id/default_vibrate"
-                        style="@style/FieldContents"
-                        android:text="vibrate"
-                        />
-                <CheckBox
-                        android:id="@+id/default_lights"
-                        style="@style/FieldContents"
-                        android:text="lights"
-                        />
+                <LinearLayout
+                        style="@style/FieldChoices"
+                        >
+                    <CheckBox
+                            android:id="@+id/default_sound"
+                            style="@style/FieldContents"
+                            android:text="sound"
+                            />
+                    <CheckBox
+                            android:id="@+id/default_vibrate"
+                            style="@style/FieldContents"
+                            android:text="vibrate"
+                            />
+                    <CheckBox
+                            android:id="@+id/default_lights"
+                            style="@style/FieldContents"
+                            android:text="lights"
+                            />
+                </LinearLayout>
             </LinearLayout>
-            
 
-
-
+            <!-- delay -->
+            <LinearLayout
+                style="@style/FieldGroup"
+                >
+                <TextView
+                        style="@style/FieldTitle"
+                        android:text="notify"
+                        />
+                <RadioGroup
+                        android:id="@+id/group_delay"
+                        style="@style/FieldChoices"
+                        >
+                    <RadioButton
+                            android:id="@+id/delay_none"
+                            style="@style/FieldContents"
+                            android:text="immediately"
+                            />
+                    <RadioButton
+                            android:id="@+id/delay_5"
+                            style="@style/FieldContents"
+                            android:text="in 5 sec"
+                            />
+                </RadioGroup>
+            </LinearLayout>
         </LinearLayout>
     </LinearLayout>
 
diff --git a/tests/StatusBar/res/values/styles.xml b/tests/StatusBar/res/values/styles.xml
index 103a25a..f2c9f0d 100644
--- a/tests/StatusBar/res/values/styles.xml
+++ b/tests/StatusBar/res/values/styles.xml
@@ -45,8 +45,10 @@
 
     <style name="FieldTitle">
         <item name="android:textAppearance">?android:attr/textAppearanceSmall</item>
-        <item name="android:layout_width">wrap_content</item>
+        <item name="android:layout_width">120dp</item>
         <item name="android:layout_height">wrap_content</item>
+        <item name="android:gravity">right</item>
+        <item name="android:textStyle">bold</item>
     </style>
 
     <style name="FieldContents">
@@ -61,5 +63,18 @@
         <item name="android:visibility">gone</item>
     </style>
 
+    <style name="FieldGroup">
+        <item name="android:layout_width">wrap_content</item>
+        <item name="android:layout_height">wrap_content</item>
+        <item name="android:orientation">horizontal</item>
+        <item name="android:layout_marginTop">18dp</item>
+    </style>
+    
+    <style name="FieldChoices">
+        <item name="android:layout_width">wrap_content</item>
+        <item name="android:layout_height">wrap_content</item>
+        <item name="android:orientation">vertical</item>
+        <item name="android:baselineAlignedChildIndex">0</item>
+    </style>
 </resources>
 
diff --git a/tests/StatusBar/src/com/android/statusbartest/NotificationBuilderTest.java b/tests/StatusBar/src/com/android/statusbartest/NotificationBuilderTest.java
index 2f0c173..5d0b155 100644
--- a/tests/StatusBar/src/com/android/statusbartest/NotificationBuilderTest.java
+++ b/tests/StatusBar/src/com/android/statusbartest/NotificationBuilderTest.java
@@ -30,6 +30,7 @@
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.Environment;
+import android.os.Handler;
 import android.os.Vibrator;
 import android.os.Handler;
 import android.text.SpannableStringBuilder;
@@ -49,11 +50,14 @@
     private final static String TAG = "NotificationTestList";
 
     NotificationManager mNM;
+    Handler mHandler;
+    int mStartDelay;
 
     @Override
     public void onCreate(Bundle icicle) {
         super.onCreate(icicle);
         mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
+        mHandler = new Handler();
         setContentView(R.layout.notification_builder_test);
         if (icicle == null) {
             setDefaults();
@@ -100,8 +104,13 @@
         setChecked(R.id.large_icon_none);
         setChecked(R.id.sound_none);
         setChecked(R.id.vibrate_none);
+        setChecked(R.id.pri_default);
         setChecked(R.id.lights_red);
         setChecked(R.id.lights_off);
+        setChecked(R.id.delay_none);
+//        setChecked(R.id.default_vibrate);
+//        setChecked(R.id.default_sound);
+//        setChecked(R.id.default_lights);
     }
 
     private View.OnClickListener mClickListener = new View.OnClickListener() {
@@ -183,9 +192,13 @@
         }
     };
 
-    private void sendNotification(int id) {
+    private void sendNotification(final int id) {
         final Notification n = buildNotification(id);
-        mNM.notify(id, n);
+        mHandler.postDelayed(new Runnable() {
+            public void run() {
+                mNM.notify(id, n);
+            }
+        }, mStartDelay);
     }
 
     private static CharSequence subst(CharSequence in, char ch, CharSequence sub) {
@@ -323,23 +336,26 @@
         // vibrate
         switch (getRadioChecked(R.id.group_vibrate)) {
             case R.id.vibrate_none:
+                b.setVibrate(null);
+                break;
+            case R.id.vibrate_zero:
+                b.setVibrate(new long[] { 0 });
                 break;
             case R.id.vibrate_short:
-                b.setVibrate(new long[] { 0, 200 });
-                break;
-            case R.id.vibrate_medium:
-                b.setVibrate(new long[] { 0, 500 });
+                b.setVibrate(new long[] { 0, 100 });
                 break;
             case R.id.vibrate_long:
                 b.setVibrate(new long[] { 0, 1000 });
                 break;
             case R.id.vibrate_pattern:
-                b.setVibrate(new long[] { 0, 250, 250, 250, 250, 250, 250, 250 });
+                b.setVibrate(new long[] { 0, 50,  200, 50,  200, 50,  500,
+                                             500, 200, 500, 200, 500, 500,
+                                             50,  200, 50,  200, 50        });
                 break;
         }
 
         // lights
-        final int color = getRadioInt(R.id.group_lights_color, 0xff0000);
+        final int color = getRadioHex(R.id.group_lights_color, 0xff0000);
         int onMs;
         int offMs;
         switch (getRadioChecked(R.id.group_lights_blink)) {
@@ -365,6 +381,35 @@
             b.setLights(color, onMs, offMs);
         }
 
+        // priority
+        switch (getRadioChecked(R.id.group_priority)) {
+            case R.id.pri_min:
+                b.setPriority(Notification.PRIORITY_MIN);
+                break;
+            case R.id.pri_low:
+                b.setPriority(Notification.PRIORITY_LOW);
+                break;
+            case R.id.pri_default:
+                b.setPriority(Notification.PRIORITY_DEFAULT);
+                break;
+            case R.id.pri_high:
+                b.setPriority(Notification.PRIORITY_HIGH);
+                break;
+            case R.id.pri_max:
+                b.setPriority(Notification.PRIORITY_MAX);
+                break;
+        }
+
+        // start delay
+        switch (getRadioChecked(R.id.group_delay)) {
+            case R.id.delay_none:
+                mStartDelay = 0;
+                break;
+            case R.id.delay_5:
+                mStartDelay = 5000;
+                break;
+        }
+
         // flags
         b.setOngoing(getChecked(R.id.flag_ongoing));
         b.setOnlyAlertOnce(getChecked(R.id.flag_once));
@@ -383,7 +428,7 @@
         }
         b.setDefaults(defaults);
 
-        return b.getNotification();
+        return b.build();
     }
 
     private void setChecked(int id) {
@@ -396,14 +441,14 @@
         return g.getCheckedRadioButtonId();
     }
 
-    private CharSequence getRadioTag(int id) {
+    private String getRadioTag(int id) {
         final RadioGroup g = (RadioGroup)findViewById(id);
         final View v = findViewById(g.getCheckedRadioButtonId());
-        return (CharSequence) v.getTag();
+        return (String) v.getTag();
     }
 
     private int getRadioInt(int id, int def) {
-        CharSequence str = getRadioTag(id);
+        String str = getRadioTag(id);
         if (TextUtils.isEmpty(str)) {
             return def;
         } else {
@@ -415,6 +460,22 @@
         }
     }
 
+    private int getRadioHex(int id, int def) {
+        String str = getRadioTag(id);
+        if (TextUtils.isEmpty(str)) {
+            return def;
+        } else {
+            if (str.startsWith("0x")) {
+                str = str.substring(2);
+            }
+            try {
+                return Integer.parseInt(str.toString(), 16);
+            } catch (NumberFormatException ex) {
+                return def;
+            }
+        }
+    }
+
     private boolean getChecked(int id) {
         final CompoundButton b = (CompoundButton)findViewById(id);
         return b.isChecked();
diff --git a/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java b/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java
index 746ac06..596f722 100644
--- a/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java
+++ b/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java
@@ -93,7 +93,7 @@
         }
         
         try {
-            mWm.addAppToken(0, null, 0, 0, false, false);
+            mWm.addAppToken(0, 0, null, 0, 0, false, false);
             fail("IWindowManager.addAppToken did not throw SecurityException as"
                     + " expected");
         } catch (SecurityException e) {
diff --git a/tools/layoutlib/bridge/src/android/text/format/DateFormat_Delegate.java b/tools/layoutlib/bridge/src/android/text/format/DateFormat_Delegate.java
new file mode 100644
index 0000000..8cd1a69
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/text/format/DateFormat_Delegate.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.text.format;
+
+import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
+
+import android.content.Context;
+
+
+/**
+ * Delegate used to provide new implementation for the native methods of {@link DateFormat}
+ *
+ * Through the layoutlib_create tool, the original  methods of DateFormat have been replaced
+ * by calls to methods of the same name in this delegate class.
+ *
+ */
+public class DateFormat_Delegate {
+
+    @LayoutlibDelegate
+    /*package*/ static boolean is24HourFormat(Context context) {
+        return false;
+    }
+}
diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
index 3e625f9..091c6e5 100644
--- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
+++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
@@ -87,7 +87,7 @@
     // ---- unused implementation of IWindowManager ----
 
     @Override
-    public void addAppToken(int arg0, IApplicationToken arg1, int arg2, int arg3, boolean arg4,
+    public void addAppToken(int arg0, int arg1p5, IApplicationToken arg1, int arg2, int arg3, boolean arg4,
                             boolean arg5)
             throws RemoteException {
         // TODO Auto-generated method stub
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 80a1a60..d955040 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
@@ -110,6 +110,7 @@
         "android.os.Handler#sendMessageAtTime",
         "android.os.HandlerThread#run",
         "android.os.Build#getString",
+        "android.text.format.DateFormat#is24HourFormat",
         "android.view.Choreographer#getRefreshRate",
         "android.view.Display#updateDisplayInfoLocked",
         "android.view.LayoutInflater#rInflate",
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index b871cdc..0e29882 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -508,6 +508,10 @@
     private Messenger mWifiServiceMessenger;
     private final CountDownLatch mConnected = new CountDownLatch(1);
 
+    private static Object sThreadRefLock = new Object();
+    private static int sThreadRefCount;
+    private static HandlerThread sHandlerThread;
+
     /**
      * Create a new WifiManager instance.
      * Applications will almost always want to use
@@ -1365,9 +1369,14 @@
             return;
         }
 
-        HandlerThread t = new HandlerThread("WifiManager");
-        t.start();
-        mHandler = new ServiceHandler(t.getLooper());
+        synchronized (sThreadRefLock) {
+            if (++sThreadRefCount == 1) {
+                sHandlerThread = new HandlerThread("WifiManager");
+                sHandlerThread.start();
+            }
+        }
+
+        mHandler = new ServiceHandler(sHandlerThread.getLooper());
         mAsyncChannel.connect(mContext, mHandler, mWifiServiceMessenger);
         try {
             mConnected.await();
@@ -1983,8 +1992,10 @@
 
     protected void finalize() throws Throwable {
         try {
-            if (mHandler != null && mHandler.getLooper() != null) {
-                mHandler.getLooper().quit();
+            synchronized (sThreadRefLock) {
+                if (--sThreadRefCount == 0 && sHandlerThread != null) {
+                    sHandlerThread.getLooper().quit();
+                }
             }
         } finally {
             super.finalize();
diff --git a/wifi/java/android/net/wifi/WifiNative.java b/wifi/java/android/net/wifi/WifiNative.java
index 4c5fc5d..5e25623 100644
--- a/wifi/java/android/net/wifi/WifiNative.java
+++ b/wifi/java/android/net/wifi/WifiNative.java
@@ -61,7 +61,7 @@
 
     /* Sends a kill signal to supplicant. To be used when we have lost connection
        or when the supplicant is hung */
-    public native static boolean killSupplicant();
+    public native static boolean killSupplicant(boolean p2pSupported);
 
     private native boolean connectToSupplicant(String iface);
 
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index 040ff24..dafa8e8 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -1944,6 +1944,7 @@
                 case CMD_STOP_DRIVER:
                 case CMD_DELAYED_STOP_DRIVER:
                 case CMD_DRIVER_START_TIMED_OUT:
+                case CMD_CAPTIVE_CHECK_COMPLETE:
                 case CMD_START_AP:
                 case CMD_START_AP_SUCCESS:
                 case CMD_START_AP_FAILURE:
@@ -2189,6 +2190,13 @@
                         loge("Unable to change interface settings: " + ie);
                     }
 
+                    /* Stop a running supplicant after a runtime restart
+                     * Avoids issues with drivers that do not handle interface down
+                     * on a running supplicant properly.
+                     */
+                    if (DBG) log("Kill any running supplicant");
+                    mWifiNative.killSupplicant(mP2pSupported);
+
                     if(mWifiNative.startSupplicant(mP2pSupported)) {
                         if (DBG) log("Supplicant start successful");
                         mWifiMonitor.startMonitoring();
@@ -2384,7 +2392,7 @@
                 case WifiMonitor.SUP_DISCONNECTION_EVENT:
                     if (++mSupplicantRestartCount <= SUPPLICANT_RESTART_TRIES) {
                         loge("Failed to setup control channel, restart supplicant");
-                        mWifiNative.killSupplicant();
+                        mWifiNative.killSupplicant(mP2pSupported);
                         transitionTo(mDriverLoadedState);
                         sendMessageDelayed(CMD_START_SUPPLICANT, SUPPLICANT_RESTART_INTERVAL_MSECS);
                     } else {
@@ -2451,7 +2459,7 @@
                     break;
                 case WifiMonitor.SUP_DISCONNECTION_EVENT:  /* Supplicant connection lost */
                     loge("Connection lost, restart supplicant");
-                    mWifiNative.killSupplicant();
+                    mWifiNative.killSupplicant(mP2pSupported);
                     mWifiNative.closeSupplicantConnection();
                     mNetworkInfo.setIsAvailable(false);
                     handleNetworkDisconnect();
@@ -2605,14 +2613,14 @@
                     /* Socket connection can be lost when we do a graceful shutdown
                      * or when the driver is hung. Ensure supplicant is stopped here.
                      */
-                    mWifiNative.killSupplicant();
+                    mWifiNative.killSupplicant(mP2pSupported);
                     mWifiNative.closeSupplicantConnection();
                     transitionTo(mDriverLoadedState);
                     break;
                 case CMD_STOP_SUPPLICANT_FAILED:
                     if (message.arg1 == mSupplicantStopFailureToken) {
                         loge("Timed out on a supplicant stop, kill and proceed");
-                        mWifiNative.killSupplicant();
+                        mWifiNative.killSupplicant(mP2pSupported);
                         mWifiNative.closeSupplicantConnection();
                         transitionTo(mDriverLoadedState);
                     }