Merge "Remove unnecessary lock to save 1 allocation per TextView"
diff --git a/api/current.txt b/api/current.txt
index 8b02878..16e4a09 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -6808,6 +6808,7 @@
     ctor public ComponentInfo(android.content.pm.ComponentInfo);
     ctor protected ComponentInfo(android.os.Parcel);
     method public final int getIconResource();
+    method public final int getLogoResource();
     method public boolean isEnabled();
     field public android.content.pm.ApplicationInfo applicationInfo;
     field public int descriptionRes;
@@ -12057,7 +12058,6 @@
     method public void start();
     method public void stop();
     method public void writeSampleData(int, java.nio.ByteBuffer, android.media.MediaCodec.BufferInfo);
-    field public static final int SAMPLE_FLAG_SYNC = 1; // 0x1
   }
 
   public static final class MediaMuxer.OutputFormat {
@@ -12285,7 +12285,7 @@
     method public void removeCallback(android.media.MediaRouter.Callback);
     method public void removeUserRoute(android.media.MediaRouter.UserRouteInfo);
     method public void selectRoute(int, android.media.MediaRouter.RouteInfo);
-    field public static final int CALLBACK_FLAG_ACTIVE_SCAN = 1; // 0x1
+    field public static final int CALLBACK_FLAG_PERFORM_ACTIVE_SCAN = 1; // 0x1
     field public static final int CALLBACK_FLAG_UNFILTERED_EVENTS = 2; // 0x2
     field public static final int ROUTE_TYPE_LIVE_AUDIO = 1; // 0x1
     field public static final int ROUTE_TYPE_LIVE_VIDEO = 2; // 0x2
@@ -19962,6 +19962,7 @@
     field public static final java.lang.String ACTION_DATE_SETTINGS = "android.settings.DATE_SETTINGS";
     field public static final java.lang.String ACTION_DEVICE_INFO_SETTINGS = "android.settings.DEVICE_INFO_SETTINGS";
     field public static final java.lang.String ACTION_DISPLAY_SETTINGS = "android.settings.DISPLAY_SETTINGS";
+    field public static final java.lang.String ACTION_DREAM_SETTINGS = "android.settings.DREAM_SETTINGS";
     field public static final java.lang.String ACTION_INPUT_METHOD_SETTINGS = "android.settings.INPUT_METHOD_SETTINGS";
     field public static final java.lang.String ACTION_INPUT_METHOD_SUBTYPE_SETTINGS = "android.settings.INPUT_METHOD_SUBTYPE_SETTINGS";
     field public static final java.lang.String ACTION_INTERNAL_STORAGE_SETTINGS = "android.settings.INTERNAL_STORAGE_SETTINGS";
@@ -27040,7 +27041,9 @@
     method public void setFlags(int, int);
     method public void setFormat(int);
     method public void setGravity(int);
+    method public void setIcon(int);
     method public void setLayout(int, int);
+    method public void setLogo(int);
     method public void setSoftInputMode(int);
     method public abstract void setTitle(java.lang.CharSequence);
     method public abstract void setTitleColor(int);
diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java
index b4a12c4..12fcdcf 100644
--- a/core/java/android/accounts/AccountManager.java
+++ b/core/java/android/accounts/AccountManager.java
@@ -822,7 +822,7 @@
      * {@link android.Manifest.permission#USE_CREDENTIALS}.
      *
      * @param account The account to fetch an auth token for
-     * @param authTokenType The auth token type, see {#link getAuthToken}
+     * @param authTokenType The auth token type, see {@link #getAuthToken getAuthToken()}
      * @param notifyAuthFailure If true, display a notification and return null
      *     if authentication fails; if false, prompt and wait for the user to
      *     re-enter correct credentials before returning
diff --git a/core/java/android/accounts/ChooseTypeAndAccountActivity.java b/core/java/android/accounts/ChooseTypeAndAccountActivity.java
index 58eb66f..82c2159 100644
--- a/core/java/android/accounts/ChooseTypeAndAccountActivity.java
+++ b/core/java/android/accounts/ChooseTypeAndAccountActivity.java
@@ -29,6 +29,7 @@
 import android.text.TextUtils;
 import android.util.Log;
 import android.view.View;
+import android.view.Window;
 import android.widget.AdapterView;
 import android.widget.ArrayAdapter;
 import android.widget.Button;
@@ -127,6 +128,7 @@
     private int mCallingUid;
     private String mCallingPackage;
     private boolean mDisallowAddAccounts;
+    private boolean mDontShowPicker;
 
     @Override
     public void onCreate(Bundle savedInstanceState) {
@@ -189,11 +191,23 @@
         mSetOfRelevantAccountTypes = getReleventAccountTypes(intent);
         mAlwaysPromptForAccount = intent.getBooleanExtra(EXTRA_ALWAYS_PROMPT_FOR_ACCOUNT, false);
         mDescriptionOverride = intent.getStringExtra(EXTRA_DESCRIPTION_TEXT_OVERRIDE);
+
+        // Need to do this once here to request the window feature. Can't do it in onResume
+        mAccounts = getAcceptableAccountChoices(AccountManager.get(this));
+        if (mAccounts.isEmpty()
+                && mDisallowAddAccounts) {
+            requestWindowFeature(Window.FEATURE_NO_TITLE);
+            setContentView(R.layout.app_not_authorized);
+            mDontShowPicker = true;
+        }
     }
 
     @Override
     protected void onResume() {
         super.onResume();
+
+        if (mDontShowPicker) return;
+
         final AccountManager accountManager = AccountManager.get(this);
 
         mAccounts = getAcceptableAccountChoices(accountManager);
@@ -206,11 +220,6 @@
             // If there are no relevant accounts and only one relevant account type go directly to
             // add account. Otherwise let the user choose.
             if (mAccounts.isEmpty()) {
-                if (mDisallowAddAccounts) {
-                    setContentView(R.layout.app_not_authorized);
-                    setTitle(R.string.error_message_title);
-                    return;
-                }
                 if (mSetOfRelevantAccountTypes.size() == 1) {
                     runAddAccountForAuthenticator(mSetOfRelevantAccountTypes.iterator().next());
                 } else {
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 6b5df7f..7f2f744 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -1877,9 +1877,12 @@
         if (isChild() || !window.hasFeature(Window.FEATURE_ACTION_BAR) || mActionBar != null) {
             return;
         }
-        
+
         mActionBar = new ActionBarImpl(this);
         mActionBar.setDefaultDisplayHomeAsUpEnabled(mEnableDefaultActionBarUp);
+
+        mWindow.setDefaultIcon(mActivityInfo.getIconResource());
+        mWindow.setDefaultLogo(mActivityInfo.getLogoResource());
     }
     
     /**
diff --git a/core/java/android/app/Dialog.java b/core/java/android/app/Dialog.java
index b3d99c5..634fa30 100644
--- a/core/java/android/app/Dialog.java
+++ b/core/java/android/app/Dialog.java
@@ -16,6 +16,8 @@
 
 package android.app;
 
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
 import com.android.internal.app.ActionBarImpl;
 import com.android.internal.policy.PolicyManager;
 
@@ -264,6 +266,9 @@
         mDecor = mWindow.getDecorView();
 
         if (mActionBar == null && mWindow.hasFeature(Window.FEATURE_ACTION_BAR)) {
+            final ApplicationInfo info = mContext.getApplicationInfo();
+            mWindow.setDefaultIcon(info.icon);
+            mWindow.setDefaultLogo(info.logo);
             mActionBar = new ActionBarImpl(this);
         }
 
diff --git a/core/java/android/appwidget/AppWidgetManager.java b/core/java/android/appwidget/AppWidgetManager.java
index 1166e4b..d1c7bec 100644
--- a/core/java/android/appwidget/AppWidgetManager.java
+++ b/core/java/android/appwidget/AppWidgetManager.java
@@ -529,9 +529,9 @@
 
     /**
      * Notifies the specified collection view in all the specified AppWidget instances
-     * to invalidate their currently data.
+     * to invalidate their data.
      *
-     * @param appWidgetIds  The AppWidget instances for which to notify of view data changes.
+     * @param appWidgetIds  The AppWidget instances to notify of view data changes.
      * @param viewId        The collection view id.
      */
     public void notifyAppWidgetViewDataChanged(int[] appWidgetIds, int viewId) {
@@ -544,11 +544,11 @@
     }
 
     /**
-     * Notifies the specified collection view in all the specified AppWidget instance
-     * to invalidate it's currently data.
+     * Notifies the specified collection view in the specified AppWidget instance
+     * to invalidate its data.
      *
-     * @param appWidgetId  The AppWidget instance for which to notify of view data changes.
-     * @param viewId        The collection view id.
+     * @param appWidgetId  The AppWidget instance to notify of view data changes.
+     * @param viewId       The collection view id.
      */
     public void notifyAppWidgetViewDataChanged(int appWidgetId, int viewId) {
         notifyAppWidgetViewDataChanged(new int[] { appWidgetId }, viewId);
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 7ec73ef..79bb476 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -47,17 +47,22 @@
  * device discovery, query a list of bonded (paired) devices,
  * instantiate a {@link BluetoothDevice} using a known MAC address, and create
  * a {@link BluetoothServerSocket} to listen for connection requests from other
- * devices.
+ * devices, and start a scan for Bluetooth LE devices.
  *
  * <p>To get a {@link BluetoothAdapter} representing the local Bluetooth
- * adapter, call the static {@link #getDefaultAdapter} method.
+ * adapter, when running on JELLY_BEAN_MR1 and below, call the 
+ * static {@link #getDefaultAdapter} method; when running on JELLY_BEAN_MR2 and
+ * higher, retrieve it through
+ * {@link android.content.Context#getSystemService} with
+ * {@link android.content.Context#BLUETOOTH_SERVICE}.
  * Fundamentally, this is your starting point for all
  * Bluetooth actions. Once you have the local adapter, you can get a set of
  * {@link BluetoothDevice} objects representing all paired devices with
  * {@link #getBondedDevices()}; start device discovery with
  * {@link #startDiscovery()}; or create a {@link BluetoothServerSocket} to
  * listen for incoming connection requests with
- * {@link #listenUsingRfcommWithServiceRecord(String,UUID)}.
+ * {@link #listenUsingRfcommWithServiceRecord(String,UUID)}; or start a scan for
+ * Bluetooth LE devices with {@link #startLeScan(LeScanCallback callback)}.
  *
  * <p class="note"><strong>Note:</strong>
  * Most methods require the {@link android.Manifest.permission#BLUETOOTH}
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index 79a5ffe..3ee7142 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -107,7 +107,7 @@
      * <p>Always contains the extra fields {@link #EXTRA_DEVICE} and {@link
      * #EXTRA_CLASS}.
      * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
-     * @see {@link BluetoothClass}
+     * {@see BluetoothClass}
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_CLASS_CHANGED =
diff --git a/core/java/android/bluetooth/BluetoothGatt.java b/core/java/android/bluetooth/BluetoothGatt.java
index 77e5f84..df3ec1a 100644
--- a/core/java/android/bluetooth/BluetoothGatt.java
+++ b/core/java/android/bluetooth/BluetoothGatt.java
@@ -565,6 +565,9 @@
 
     /**
      * Close this Bluetooth GATT client.
+     *
+     * Application should call this method as early as possible after it is done with
+     * this GATT client.
      */
     public void close() {
         if (DBG) Log.d(TAG, "close()");
diff --git a/core/java/android/bluetooth/BluetoothGattCallback.java b/core/java/android/bluetooth/BluetoothGattCallback.java
index 2259c1e..80ea4a6 100644
--- a/core/java/android/bluetooth/BluetoothGattCallback.java
+++ b/core/java/android/bluetooth/BluetoothGattCallback.java
@@ -27,6 +27,7 @@
      *
      * @param gatt GATT client
      * @param status Status of the connect or disconnect operation.
+     *               {@link BluetoothGatt#GATT_SUCCESS} if the operation succeeds.
      * @param newState Returns the new connection state. Can be one of
      *                  {@link BluetoothProfile#STATE_DISCONNECTED} or
      *                  {@link BluetoothProfile#STATE_CONNECTED}
@@ -72,6 +73,7 @@
      * @param characteristic Characteristic that was written to the associated
      *                       remote device.
      * @param status The result of the write operation
+     *               {@link BluetoothGatt#GATT_SUCCESS} if the operation succeeds.
      */
     public void onCharacteristicWrite(BluetoothGatt gatt,
                                       BluetoothGattCharacteristic characteristic, int status) {
@@ -108,6 +110,7 @@
      * @param descriptor Descriptor that was writte to the associated
      *                   remote device.
      * @param status The result of the write operation
+     *               {@link BluetoothGatt#GATT_SUCCESS} if the operation succeeds.
      */
     public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor,
                                   int status) {
diff --git a/core/java/android/bluetooth/BluetoothGattServer.java b/core/java/android/bluetooth/BluetoothGattServer.java
index d3b85a9..58ee54f 100644
--- a/core/java/android/bluetooth/BluetoothGattServer.java
+++ b/core/java/android/bluetooth/BluetoothGattServer.java
@@ -289,6 +289,9 @@
 
     /**
      * Close this GATT server instance.
+     *
+     * Application should call this method as early as possible after it is done with
+     * this GATT server.
      */
     public void close() {
         if (DBG) Log.d(TAG, "close()");
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 03a6093..897e6fe 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -2269,7 +2269,7 @@
     /**
      * Broadcast Action: An outgoing call is about to be placed.
      *
-     * <p>The Intent will have the following extra value:
+     * <p>The Intent will have the following extra value:</p>
      * <ul>
      *   <li><em>{@link android.content.Intent#EXTRA_PHONE_NUMBER}</em> -
      *       the phone number originally intended to be dialed.</li>
diff --git a/core/java/android/content/pm/ComponentInfo.java b/core/java/android/content/pm/ComponentInfo.java
index 2812477..4dbcf23 100644
--- a/core/java/android/content/pm/ComponentInfo.java
+++ b/core/java/android/content/pm/ComponentInfo.java
@@ -116,6 +116,17 @@
     public final int getIconResource() {
         return icon != 0 ? icon : applicationInfo.icon;
     }
+
+    /**
+     * Return the logo resource identifier to use for this component.  If
+     * the component defines a logo, that is used; else, the application
+     * logo is used.
+     *
+     * @return The logo associated with this component.
+     */
+    public final int getLogoResource() {
+        return logo != 0 ? logo : applicationInfo.logo;
+    }
     
     protected void dumpFront(Printer pw, String prefix) {
         super.dumpFront(pw, prefix);
diff --git a/core/java/android/content/pm/ResolveInfo.java b/core/java/android/content/pm/ResolveInfo.java
index 07117fe..de8e256 100644
--- a/core/java/android/content/pm/ResolveInfo.java
+++ b/core/java/android/content/pm/ResolveInfo.java
@@ -328,6 +328,7 @@
             implements Comparator<ResolveInfo> {
         public DisplayNameComparator(PackageManager pm) {
             mPM = pm;
+            mCollator.setStrength(Collator.PRIMARY);
         }
 
         public final int compare(ResolveInfo a, ResolveInfo b) {
@@ -336,10 +337,10 @@
             CharSequence  sb = b.loadLabel(mPM);
             if (sb == null) sb = b.activityInfo.name;
             
-            return sCollator.compare(sa.toString(), sb.toString());
+            return mCollator.compare(sa.toString(), sb.toString());
         }
 
-        private final Collator   sCollator = Collator.getInstance();
+        private final Collator   mCollator = Collator.getInstance();
         private PackageManager   mPM;
     }
 }
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index 4881d14..7f82ce3 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -381,7 +381,6 @@
             if (DEBUG) Log.v(TAG, "unbindInput(): binding=" + mInputBinding
                     + " ic=" + mInputConnection);
             onUnbindInput();
-            mInputStarted = false;
             mInputBinding = null;
             mInputConnection = null;
         }
@@ -719,7 +718,7 @@
         super.onDestroy();
         mRootView.getViewTreeObserver().removeOnComputeInternalInsetsListener(
                 mInsetsComputer);
-        finishViews();
+        doFinishInput();
         if (mWindowAdded) {
             // Disable exit animation for the current IME window
             // to avoid the race condition between the exit and enter animations
diff --git a/core/java/android/os/RemoteCallbackList.java b/core/java/android/os/RemoteCallbackList.java
index d02a320..c1d4ae9 100644
--- a/core/java/android/os/RemoteCallbackList.java
+++ b/core/java/android/os/RemoteCallbackList.java
@@ -16,6 +16,8 @@
 
 package android.os;
 
+import android.util.ArrayMap;
+
 import java.util.HashMap;
 
 /**
@@ -47,8 +49,8 @@
  * implements the {@link #onCallbackDied} method.
  */
 public class RemoteCallbackList<E extends IInterface> {
-    /*package*/ HashMap<IBinder, Callback> mCallbacks
-            = new HashMap<IBinder, Callback>();
+    /*package*/ ArrayMap<IBinder, Callback> mCallbacks
+            = new ArrayMap<IBinder, Callback>();
     private Object[] mActiveBroadcast;
     private int mBroadcastCount = -1;
     private boolean mKilled = false;
@@ -159,7 +161,8 @@
      */
     public void kill() {
         synchronized (mCallbacks) {
-            for (Callback cb : mCallbacks.values()) {
+            for (int cbi=mCallbacks.size()-1; cbi>=0; cbi--) {
+                Callback cb = mCallbacks.valueAt(cbi);
                 cb.mCallback.asBinder().unlinkToDeath(cb, 0);
             }
             mCallbacks.clear();
@@ -238,11 +241,10 @@
             if (active == null || active.length < N) {
                 mActiveBroadcast = active = new Object[N];
             }
-            int i=0;
-            for (Callback cb : mCallbacks.values()) {
-                active[i++] = cb;
+            for (int i=0; i<N; i++) {
+                active[i] = mCallbacks.valueAt(i);
             }
-            return i;
+            return N;
         }
     }
 
diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java
index 3267939..31da091 100644
--- a/core/java/android/os/StrictMode.java
+++ b/core/java/android/os/StrictMode.java
@@ -24,6 +24,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.ServiceConnection;
+import android.util.ArrayMap;
 import android.util.Log;
 import android.util.Printer;
 import android.util.Singleton;
@@ -1069,7 +1070,7 @@
         // Map from violation stacktrace hashcode -> uptimeMillis of
         // last violation.  No locking needed, as this is only
         // accessed by the same thread.
-        private final HashMap<Integer, Long> mLastViolationTime = new HashMap<Integer, Long>();
+        private ArrayMap<Integer, Long> mLastViolationTime;
 
         public AndroidBlockGuardPolicy(final int policyMask) {
             mPolicyMask = policyMask;
@@ -1279,8 +1280,13 @@
             // Not perfect, but fast and good enough for dup suppression.
             Integer crashFingerprint = info.hashCode();
             long lastViolationTime = 0;
-            if (mLastViolationTime.containsKey(crashFingerprint)) {
-                lastViolationTime = mLastViolationTime.get(crashFingerprint);
+            if (mLastViolationTime != null) {
+                Long vtime = mLastViolationTime.get(crashFingerprint);
+                if (vtime != null) {
+                    lastViolationTime = vtime;
+                }
+            } else {
+                mLastViolationTime = new ArrayMap<Integer, Long>(1);
             }
             long now = SystemClock.uptimeMillis();
             mLastViolationTime.put(crashFingerprint, now);
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index ff06df0..c1a296d 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -650,7 +650,6 @@
      * <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";
diff --git a/core/java/android/util/ArrayMap.java b/core/java/android/util/ArrayMap.java
index 70f7d2e..6da7546 100644
--- a/core/java/android/util/ArrayMap.java
+++ b/core/java/android/util/ArrayMap.java
@@ -212,10 +212,12 @@
      */
     @Override
     public void clear() {
-        freeArrays(mHashes, mArray, mSize);
-        mHashes = SparseArray.EMPTY_INTS;
-        mArray = SparseArray.EMPTY_OBJECTS;
-        mSize = 0;
+        if (mSize != 0) {
+            freeArrays(mHashes, mArray, mSize);
+            mHashes = SparseArray.EMPTY_INTS;
+            mArray = SparseArray.EMPTY_OBJECTS;
+            mSize = 0;
+        }
     }
 
     /**
@@ -227,9 +229,9 @@
             int[] ohashes = mHashes;
             Object[] oarray = mArray;
             allocArrays(minimumCapacity);
-            if (mHashes.length > 0) {
-                System.arraycopy(ohashes, 0, mHashes, 0, mHashes.length);
-                System.arraycopy(oarray, 0, mArray, 0, mArray.length);
+            if (mSize > 0) {
+                System.arraycopy(ohashes, 0, mHashes, 0, mSize);
+                System.arraycopy(oarray, 0, mArray, 0, mSize<<1);
             }
             freeArrays(ohashes, oarray, mSize);
         }
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 8007d9a..ad3082e 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -97,7 +97,7 @@
     void executeAppTransition();
     void setAppStartingWindow(IBinder token, String pkg, int theme,
             in CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes,
-            int icon, int windowFlags, IBinder transferFrom, boolean createIfNeeded);
+            int icon, int logo, int windowFlags, IBinder transferFrom, boolean createIfNeeded);
     void setAppWillBeHidden(IBinder token);
     void setAppVisibility(IBinder token, boolean visible);
     void startAppFreezingScreen(IBinder token, int configChanges);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index d1fa455..6f88bb2 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -12413,8 +12413,8 @@
 
     /**
      * <p>Specifies the type of layer backing this view. The layer can be
-     * {@link #LAYER_TYPE_NONE disabled}, {@link #LAYER_TYPE_SOFTWARE software} or
-     * {@link #LAYER_TYPE_HARDWARE hardware}.</p>
+     * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
+     * {@link #LAYER_TYPE_HARDWARE}.</p>
      *
      * <p>A layer is associated with an optional {@link android.graphics.Paint}
      * instance that controls how the layer is composed on screen. The following
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 06974d3..39d48a7 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -1256,4 +1256,38 @@
      * @param mask Flags specifying which options should be modified. Others will remain unchanged.
      */
     public void setUiOptions(int uiOptions, int mask) { }
+
+    /**
+     * Set the primary icon for this window.
+     *
+     * @param resId resource ID of a drawable to set
+     */
+    public void setIcon(int resId) { }
+
+    /**
+     * Set the default icon for this window.
+     * This will be overridden by any other icon set operation which could come from the
+     * theme or another explicit set.
+     *
+     * @hide
+     */
+    public void setDefaultIcon(int resId) { }
+
+    /**
+     * Set the logo for this window. A logo is often shown in place of an
+     * {@link #setIcon(int) icon} but is generally wider and communicates window title information
+     * as well.
+     *
+     * @param resId resource ID of a drawable to set
+     */
+    public void setLogo(int resId) { }
+
+    /**
+     * Set the default logo for this window.
+     * This will be overridden by any other logo set operation which could come from the
+     * theme or another explicit set.
+     *
+     * @hide
+     */
+    public void setDefaultLogo(int resId) { }
 }
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index 6a35f20..6291e62 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -642,7 +642,7 @@
      */
     public View addStartingWindow(IBinder appToken, String packageName,
             int theme, CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel,
-            int labelRes, int icon, int windowFlags);
+            int labelRes, int icon, int logo, int windowFlags);
 
     /**
      * Called when the first window of an application has been displayed, while
diff --git a/core/java/android/view/inputmethod/BaseInputConnection.java b/core/java/android/view/inputmethod/BaseInputConnection.java
index b3ff54d..f730cf7 100644
--- a/core/java/android/view/inputmethod/BaseInputConnection.java
+++ b/core/java/android/view/inputmethod/BaseInputConnection.java
@@ -42,7 +42,8 @@
  * Base class for implementors of the InputConnection interface, taking care
  * of most of the common behavior for providing a connection to an Editable.
  * Implementors of this class will want to be sure to implement
- * {@link #getEditable} to provide access to their own editable object.
+ * {@link #getEditable} to provide access to their own editable object, and
+ * to refer to the documentation in {@link InputConnection}.
  */
 public class BaseInputConnection implements InputConnection {
     private static final boolean DEBUG = false;
diff --git a/core/java/android/view/inputmethod/CompletionInfo.java b/core/java/android/view/inputmethod/CompletionInfo.java
index 3591cb1..70b8059 100644
--- a/core/java/android/view/inputmethod/CompletionInfo.java
+++ b/core/java/android/view/inputmethod/CompletionInfo.java
@@ -1,12 +1,12 @@
 /*
  * Copyright (C) 2007-2008 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
@@ -23,6 +23,30 @@
 /**
  * Information about a single text completion that an editor has reported to
  * an input method.
+ *
+ * <p>This class encapsulates a completion offered by an application
+ * that wants it to be presented to the user by the IME. Usually, apps
+ * present their completions directly in a scrolling list for example
+ * (UI developers will usually use or extend
+ * {@see android.widget.AutoCompleteTextView} to implement this).
+ * However, in some cases, the editor may not be visible, as in the
+ * case in extract mode where the IME has taken over the full
+ * screen. In this case, the editor can choose to send their
+ * completions to the IME for display.
+ *
+ * <p>Most applications who want to send completions to an IME should use
+ * {@link android.widget.AutoCompleteTextView} as this class makes this
+ * process easy. In this case, the application would not have to deal directly
+ * with this class.
+ *
+ * <p>An application who implements its own editor and wants direct control
+ * over this would create an array of CompletionInfo objects, and send it to the IME using
+ * {@link InputMethodManager#displayCompletions(View, CompletionInfo[])}.
+ * The IME would present the completions however they see fit, and
+ * call back to the editor through
+ * {@link InputConnection#commitCompletion(CompletionInfo)}.
+ * The application can then pick up the commit event by overriding
+ * {@link android.widget.TextView#onCommitCompletion(CompletionInfo)}.
  */
 public final class CompletionInfo implements Parcelable {
     private final long mId;
@@ -32,6 +56,12 @@
 
     /**
      * Create a simple completion with just text, no label.
+     *
+     * @param id An id that get passed as is (to the editor's discretion)
+     * @param index An index that get passed as is. Typically this is the
+     * index in the list of completions inside the editor.
+     * @param text The text that should be inserted into the editor when
+     * this completion is chosen.
      */
     public CompletionInfo(long id, int index, CharSequence text) {
         mId = id;
@@ -41,7 +71,18 @@
     }
 
     /**
-     * Create a full completion with both text and label.
+     * Create a full completion with both text and label. The text is
+     * what will get inserted into the editor, while the label is what
+     * the IME should display. If they are the same, use the version
+     * of the constructor without a `label' argument.
+     *
+     * @param id An id that get passed as is (to the editor's discretion)
+     * @param index An index that get passed as is. Typically this is the
+     * index in the list of completions inside the editor.
+     * @param text The text that should be inserted into the editor when
+     * this completion is chosen.
+     * @param label The text that the IME should be showing among the
+     * completions list.
      */
     public CompletionInfo(long id, int index, CharSequence text, CharSequence label) {
         mId = id;
@@ -56,7 +97,7 @@
         mText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
         mLabel = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
     }
-    
+
     /**
      * Return the abstract identifier for this completion, typically
      * corresponding to the id associated with it in the original adapter.
@@ -64,7 +105,7 @@
     public long getId() {
         return mId;
     }
-    
+
     /**
      * Return the original position of this completion, typically
      * corresponding to its position in the original adapter.
@@ -72,7 +113,7 @@
     public int getPosition() {
         return mPosition;
     }
-    
+
     /**
      * Return the actual text associated with this completion.  This is the
      * real text that will be inserted into the editor if the user selects it.
@@ -80,7 +121,7 @@
     public CharSequence getText() {
         return mText;
     }
-    
+
     /**
      * Return the user-visible label for the completion, or null if the plain
      * text should be shown.  If non-null, this will be what the user sees as
@@ -89,7 +130,7 @@
     public CharSequence getLabel() {
         return mLabel;
     }
-    
+
     @Override
     public String toString() {
         return "CompletionInfo{#" + mPosition + " \"" + mText
diff --git a/core/java/android/view/inputmethod/ExtractedText.java b/core/java/android/view/inputmethod/ExtractedText.java
index 3b2508c..0c5d9e9 100644
--- a/core/java/android/view/inputmethod/ExtractedText.java
+++ b/core/java/android/view/inputmethod/ExtractedText.java
@@ -22,6 +22,9 @@
 
 /**
  * Information about text that has been extracted for use by an input method.
+ *
+ * This contains information about a portion of the currently edited text,
+ * that the IME should display into its own interface while in extracted mode.
  */
 public class ExtractedText implements Parcelable {
     /**
@@ -33,7 +36,7 @@
      * The offset in the overall text at which the extracted text starts.
      */
     public int startOffset;
-    
+
     /**
      * If the content is a report of a partial text change, this is the
      * offset where the change starts and it runs until
@@ -41,7 +44,7 @@
      * field is -1.
      */
     public int partialStartOffset;
-    
+
     /**
      * If the content is a report of a partial text change, this is the offset
      * where the change ends.  Note that the actual text may be larger or
@@ -49,40 +52,43 @@
      * meaning a reduction or increase, respectively, in the total text.
      */
     public int partialEndOffset;
-    
+
     /**
      * The offset where the selection currently starts within the extracted
      * text.  The real selection start position is at
      * <var>startOffset</var>+<var>selectionStart</var>.
      */
     public int selectionStart;
-    
+
     /**
      * The offset where the selection currently ends within the extracted
      * text.  The real selection end position is at
      * <var>startOffset</var>+<var>selectionEnd</var>.
      */
     public int selectionEnd;
-    
+
     /**
      * Bit for {@link #flags}: set if the text being edited can only be on
      * a single line.
      */
     public static final int FLAG_SINGLE_LINE = 0x0001;
-    
+
     /**
      * Bit for {@link #flags}: set if the editor is currently in selection mode.
+     *
+     * This happens when a hardware keyboard with latched keys is attached and
+     * the shift key is currently latched.
      */
     public static final int FLAG_SELECTING = 0x0002;
-    
+
     /**
      * Additional bit flags of information about the edited text.
      */
     public int flags;
-    
+
     /**
      * Used to package this object into a {@link Parcel}.
-     * 
+     *
      * @param dest The {@link Parcel} to be written.
      * @param flags The flags used for parceling.
      */
@@ -99,7 +105,8 @@
     /**
      * Used to make this class parcelable.
      */
-    public static final Parcelable.Creator<ExtractedText> CREATOR = new Parcelable.Creator<ExtractedText>() {
+    public static final Parcelable.Creator<ExtractedText> CREATOR
+            = new Parcelable.Creator<ExtractedText>() {
         public ExtractedText createFromParcel(Parcel source) {
             ExtractedText res = new ExtractedText();
             res.text = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
diff --git a/core/java/android/view/inputmethod/InputConnection.java b/core/java/android/view/inputmethod/InputConnection.java
index 76c6d19..e7d84c2 100644
--- a/core/java/android/view/inputmethod/InputConnection.java
+++ b/core/java/android/view/inputmethod/InputConnection.java
@@ -1,12 +1,12 @@
 /*
  * Copyright (C) 2007-2008 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
@@ -22,60 +22,167 @@
 
 /**
  * The InputConnection interface is the communication channel from an
- * {@link InputMethod} back to the application that is receiving its input. It
- * is used to perform such things as reading text around the cursor,
- * committing text to the text box, and sending raw key events to the application.
- * 
- * <p>Applications should never directly implement this interface, but instead
- * subclass from {@link BaseInputConnection}.  This will ensure that the
- * application does not break when new methods are added to the interface.
+ * {@link InputMethod} back to the application that is receiving its
+ * input. It is used to perform such things as reading text around the
+ * cursor, committing text to the text box, and sending raw key events
+ * to the application.
+ *
+ * <p>Applications should never directly implement this interface, but
+ * instead subclass from {@link BaseInputConnection}. This will ensure
+ * that the application does not break when new methods are added to
+ * the interface.</p>
+ *
+ * <h3>Implementing an IME or an editor</h3>
+ * <p>Text input is the result of the synergy of two essential components:
+ * an Input Method Engine (IME) and an editor. The IME can be a
+ * software keyboard, a handwriting interface, an emoji palette, a
+ * speech-to-text engine, and so on. There are typically several IMEs
+ * installed on any given Android device. In Android, IMEs extend
+ * {@link android.inputmethodservice.InputMethodService}.
+ * For more information about how to create an IME, see the
+ * <a href="{@docRoot}guide/topics/text/creating-input-method.html">
+ * Creating an input method</a> guide.
+ *
+ * The editor is the component that receives text and displays it.
+ * Typically, this is an {@link android.widget.EditText} instance, but
+ * some applications may choose to implement their own editor for
+ * various reasons. This is a large and complicated task, and an
+ * application that does this needs to make sure the behavior is
+ * consistent with standard EditText behavior in Android. An editor
+ * needs to interact with the IME, receiving commands through
+ * this InputConnection interface, and sending commands through
+ * {@link android.view.inputmethod.InputMethodManager}. An editor
+ * should start by implementing
+ * {@link android.view.View#onCreateInputConnection(EditorInfo)}
+ * to return its own input connection.</p>
+ *
+ * <p>If you are implementing your own IME, you will need to call the
+ * methods in this interface to interact with the application. Be sure
+ * to test your IME with a wide range of applications, including
+ * browsers and rich text editors, as some may have peculiarities you
+ * need to deal with. Remember your IME may not be the only source of
+ * changes on the text, and try to be as conservative as possible in
+ * the data you send and as liberal as possible in the data you
+ * receive.</p>
+ *
+ * <p>If you are implementing your own editor, you will probably need
+ * to provide your own subclass of {@link BaseInputConnection} to
+ * answer to the commands from IMEs. Please be sure to test your
+ * editor with as many IMEs as you can as their behavior can vary a
+ * lot. Also be sure to test with various languages, including CJK
+ * languages and right-to-left languages like Arabic, as these may
+ * have different input requirements. When in doubt about the
+ * behavior you should adopt for a particular call, please mimic the
+ * default TextView implementation in the latest Android version, and
+ * if you decide to drift from it, please consider carefully that
+ * inconsistencies in text edition behavior is almost universally felt
+ * as a bad thing by users.</p>
+ *
+ * <h3>Cursors, selections and compositions</h3>
+ * <p>In Android, the cursor and the selection are one and the same
+ * thing. A "cursor" is just the special case of a zero-sized
+ * selection. As such, this documentation uses them
+ * interchangeably. Any method acting "before the cursor" would act
+ * before the start of the selection if there is one, and any method
+ * acting "after the cursor" would act after the end of the
+ * selection.</p>
+ *
+ * <p>An editor needs to be able to keep track of a currently
+ * "composing" region, like the standard edition widgets do. The
+ * composition is marked in a specific style: see
+ * {@link android.text.Spanned#SPAN_COMPOSING}. IMEs use this to help
+ * the user keep track of what part of the text they are currently
+ * focusing on, and interact with the editor using
+ * {@link InputConnection#setComposingText(CharSequence, int)},
+ * {@link InputConnection#setComposingRegion(int, int)} and
+ * {@link InputConnection#finishComposingText()}.
+ * The composing region and the selection are completely independent
+ * of each other, and the IME may use them however they see fit.</p>
  */
 public interface InputConnection {
     /**
      * Flag for use with {@link #getTextAfterCursor} and
-     * {@link #getTextBeforeCursor} to have style information returned along
-     * with the text.  If not set, you will receive only the raw text.  If
-     * set, you may receive a complex CharSequence of both text and style
-     * spans.
+     * {@link #getTextBeforeCursor} to have style information returned
+     * along with the text. If not set, {@link #getTextAfterCursor}
+     * sends only the raw text, without style or other spans. If set,
+     * it may return a complex CharSequence of both text and style
+     * spans. <strong>Editor authors</strong>: you should strive to
+     * send text with styles if possible, but it is not required.
      */
     static final int GET_TEXT_WITH_STYLES = 0x0001;
-    
+
     /**
-     * Flag for use with {@link #getExtractedText} to indicate you would
-     * like to receive updates when the extracted text changes.
+     * Flag for use with {@link #getExtractedText} to indicate you
+     * would like to receive updates when the extracted text changes.
      */
     public static final int GET_EXTRACTED_TEXT_MONITOR = 0x0001;
-    
+
     /**
-     * Get <var>n</var> characters of text before the current cursor position.
-     * 
-     * <p>This method may fail either if the input connection has become invalid
-     * (such as its process crashing) or the client is taking too long to
-     * respond with the text (it is given a couple seconds to return).
-     * In either case, a null is returned.
-     * 
+     * Get <var>n</var> characters of text before the current cursor
+     * position.
+     *
+     * <p>This method may fail either if the input connection has
+     * become invalid (such as its process crashing) or the editor is
+     * taking too long to respond with the text (it is given a couple
+     * seconds to return). In either case, null is returned. This
+     * method does not affect the text in the editor in any way, nor
+     * does it affect the selection or composing spans.</p>
+     *
+     * <p>If {@link #GET_TEXT_WITH_STYLES} is supplied as flags, the
+     * editor should return a {@link android.text.SpannableString}
+     * with all the spans set on the text.</p>
+     *
+     * <p><strong>IME authors:</strong> please consider this will
+     * trigger an IPC round-trip that will take some time. Assume this
+     * method consumes a lot of time. Also, please keep in mind the
+     * Editor may choose to return less characters than requested even
+     * if they are available for performance reasons.</p>
+     *
+     * <p><strong>Editor authors:</strong> please be careful of race
+     * conditions in implementing this call. An IME can make a change
+     * to the text and use this method right away; you need to make
+     * sure the returned value is consistent with the result of the
+     * latest edits.
+     *
      * @param n The expected length of the text.
      * @param flags Supplies additional options controlling how the text is
-     * returned.  May be either 0 or {@link #GET_TEXT_WITH_STYLES}.
-     * 
-     * @return Returns the text before the cursor position; the length of the
+     * returned. May be either 0 or {@link #GET_TEXT_WITH_STYLES}.
+     * @return the text before the cursor position; the length of the
      * returned text might be less than <var>n</var>.
      */
     public CharSequence getTextBeforeCursor(int n, int flags);
 
     /**
-     * Get <var>n</var> characters of text after the current cursor position.
-     * 
-     * <p>This method may fail either if the input connection has become invalid
-     * (such as its process crashing) or the client is taking too long to
-     * respond with the text (it is given a couple seconds to return).
-     * In either case, a null is returned.
-     * 
+     * Get <var>n</var> characters of text after the current cursor
+     * position.
+     *
+     * <p>This method may fail either if the input connection has
+     * become invalid (such as its process crashing) or the client is
+     * taking too long to respond with the text (it is given a couple
+     * seconds to return). In either case, null is returned.
+     *
+     * <p>This method does not affect the text in the editor in any
+     * way, nor does it affect the selection or composing spans.</p>
+     *
+     * <p>If {@link #GET_TEXT_WITH_STYLES} is supplied as flags, the
+     * editor should return a {@link android.text.SpannableString}
+     * with all the spans set on the text.</p>
+     *
+     * <p><strong>IME authors:</strong> please consider this will
+     * trigger an IPC round-trip that will take some time. Assume this
+     * method consumes a lot of time.</p>
+     *
+     * <p><strong>Editor authors:</strong> please be careful of race
+     * conditions in implementing this call. An IME can make a change
+     * to the text and use this method right away; you need to make
+     * sure the returned value is consistent with the result of the
+     * latest edits.</p>
+     *
      * @param n The expected length of the text.
      * @param flags Supplies additional options controlling how the text is
-     * returned.  May be either 0 or {@link #GET_TEXT_WITH_STYLES}.
-     * 
-     * @return Returns the text after the cursor position; the length of the
+     * returned. May be either 0 or {@link #GET_TEXT_WITH_STYLES}.
+     *
+     * @return the text after the cursor position; the length of the
      * returned text might be less than <var>n</var>.
      */
     public CharSequence getTextAfterCursor(int n, int flags);
@@ -83,139 +190,287 @@
     /**
      * Gets the selected text, if any.
      *
-     * <p>This method may fail if either the input connection has become
-     * invalid (such as its process crashing) or the client is taking too
-     * long to respond with the text (it is given a couple of seconds to return).
-     * In either case, a null is returned.
+     * <p>This method may fail if either the input connection has
+     * become invalid (such as its process crashing) or the client is
+     * taking too long to respond with the text (it is given a couple
+     * of seconds to return). In either case, null is returned.</p>
+     *
+     * <p>This method must not cause any changes in the editor's
+     * state.</p>
+     *
+     * <p>If {@link #GET_TEXT_WITH_STYLES} is supplied as flags, the
+     * editor should return a {@link android.text.SpannableString}
+     * with all the spans set on the text.</p>
+     *
+     * <p><strong>IME authors:</strong> please consider this will
+     * trigger an IPC round-trip that will take some time. Assume this
+     * method consumes a lot of time.</p>
+     *
+     * <p><strong>Editor authors:</strong> please be careful of race
+     * conditions in implementing this call. An IME can make a change
+     * to the text or change the selection position and use this
+     * method right away; you need to make sure the returned value is
+     * consistent with the results of the latest edits.</p>
      *
      * @param flags Supplies additional options controlling how the text is
-     * returned.  May be either 0 or {@link #GET_TEXT_WITH_STYLES}.
-     * @return Returns the text that is currently selected, if any, or null if
+     * returned. May be either 0 or {@link #GET_TEXT_WITH_STYLES}.
+     * @return the text that is currently selected, if any, or null if
      * no text is selected.
      */
     public CharSequence getSelectedText(int flags);
 
     /**
-     * Retrieve the current capitalization mode in effect at the current
-     * cursor position in the text.  See
-     * {@link android.text.TextUtils#getCapsMode TextUtils.getCapsMode} for
-     * more information.
-     * 
-     * <p>This method may fail either if the input connection has become invalid
-     * (such as its process crashing) or the client is taking too long to
-     * respond with the text (it is given a couple seconds to return).
-     * In either case, a 0 is returned.
-     * 
+     * Retrieve the current capitalization mode in effect at the
+     * current cursor position in the text. See
+     * {@link android.text.TextUtils#getCapsMode TextUtils.getCapsMode}
+     * for more information.
+     *
+     * <p>This method may fail either if the input connection has
+     * become invalid (such as its process crashing) or the client is
+     * taking too long to respond with the text (it is given a couple
+     * seconds to return). In either case, 0 is returned.</p>
+     *
+     * <p>This method does not affect the text in the editor in any
+     * way, nor does it affect the selection or composing spans.</p>
+     *
+     * <p><strong>Editor authors:</strong> please be careful of race
+     * conditions in implementing this call. An IME can change the
+     * cursor position and use this method right away; you need to make
+     * sure the returned value is consistent with the results of the
+     * latest edits and changes to the cursor position.</p>
+     *
      * @param reqModes The desired modes to retrieve, as defined by
-     * {@link android.text.TextUtils#getCapsMode TextUtils.getCapsMode}.  These
+     * {@link android.text.TextUtils#getCapsMode TextUtils.getCapsMode}. These
      * constants are defined so that you can simply pass the current
      * {@link EditorInfo#inputType TextBoxAttribute.contentType} value
      * directly in to here.
-     * 
-     * @return Returns the caps mode flags that are in effect.
+     * @return the caps mode flags that are in effect at the current
+     * cursor position. See TYPE_TEXT_FLAG_CAPS_* in {@link android.text.InputType}.
      */
     public int getCursorCapsMode(int reqModes);
-    
+
     /**
-     * Retrieve the current text in the input connection's editor, and monitor
-     * for any changes to it.  This function returns with the current text,
-     * and optionally the input connection can send updates to the
-     * input method when its text changes.
-     * 
-     * <p>This method may fail either if the input connection has become invalid
-     * (such as its process crashing) or the client is taking too long to
-     * respond with the text (it is given a couple seconds to return).
-     * In either case, a null is returned.
-     * 
+     * Retrieve the current text in the input connection's editor, and
+     * monitor for any changes to it. This function returns with the
+     * current text, and optionally the input connection can send
+     * updates to the input method when its text changes.
+     *
+     * <p>This method may fail either if the input connection has
+     * become invalid (such as its process crashing) or the client is
+     * taking too long to respond with the text (it is given a couple
+     * seconds to return). In either case, null is returned.</p>
+     *
+     * <p>Editor authors: as a general rule, try to comply with the
+     * fields in <code>request</code> for how many chars to return,
+     * but if performance or convenience dictates otherwise, please
+     * feel free to do what is most appropriate for your case. Also,
+     * if the
+     * {@link #GET_EXTRACTED_TEXT_MONITOR} flag is set, you should be
+     * calling
+     * {@link InputMethodManager#updateExtractedText(View, int, ExtractedText)}
+     * whenever you call
+     * {@link InputMethodManager#updateSelection(View, int, int, int, int)}.</p>
+     *
      * @param request Description of how the text should be returned.
+     * {@link android.view.inputmethod.ExtractedTextRequest}
      * @param flags Additional options to control the client, either 0 or
      * {@link #GET_EXTRACTED_TEXT_MONITOR}.
-     * 
-     * @return Returns an ExtractedText object describing the state of the
-     * text view and containing the extracted text itself.
+
+     * @return an {@link android.view.inputmethod.ExtractedText}
+     * object describing the state of the text view and containing the
+     * extracted text itself, or null if the input connection is no
+     * longer valid of the editor can't comply with the request for
+     * some reason.
      */
     public ExtractedText getExtractedText(ExtractedTextRequest request,
             int flags);
 
     /**
-     * Delete <var>beforeLength</var> characters of text before the current cursor
-     * position, and delete <var>afterLength</var> characters of text after the
-     * current cursor position, excluding composing text. Before and after refer
-     * to the order of the characters in the string, not to their visual representation.
-     * 
+     * Delete <var>beforeLength</var> characters of text before the
+     * current cursor position, and delete <var>afterLength</var>
+     * characters of text after the current cursor position, excluding
+     * the selection. Before and after refer to the order of the
+     * characters in the string, not to their visual representation:
+     * this means you don't have to figure out the direction of the
+     * text and can just use the indices as-is.
+     *
+     * <p>The lengths are supplied in Java chars, not in code points
+     * or in glyphs.</p>
+     *
+     * <p>Since this method only operates on text before and after the
+     * selection, it can't affect the contents of the selection. This
+     * may affect the composing span if the span includes characters
+     * that are to be deleted, but otherwise will not change it. If
+     * some characters in the composing span are deleted, the
+     * composing span will persist but get shortened by however many
+     * chars inside it have been removed.</p>
+     *
+     * <p><strong>IME authors:</strong> please be careful not to
+     * delete only half of a surrogate pair. Also take care not to
+     * delete more characters than are in the editor, as that may have
+     * ill effects on the application. Calling this method will cause
+     * the editor to call
+     * {@link android.inputmethodservice.InputMethodService#onUpdateSelection(int, int, int, int, int, int)}
+     * on your service after the batch input is over.</p>
+     *
+     * <p><strong>Editor authors:</strong> please be careful of race
+     * conditions in implementing this call. An IME can make a change
+     * to the text or change the selection position and use this
+     * method right away; you need to make sure the effects are
+     * consistent with the results of the latest edits. Also, although
+     * the IME should not send lengths bigger than the contents of the
+     * string, you should check the values for overflows and trim the
+     * indices to the size of the contents to avoid crashes. Since
+     * this changes the contents of the editor, you need to make the
+     * changes known to the input method by calling
+     * {@link InputMethodManager#updateSelection(View, int, int, int, int)},
+     * but be careful to wait until the batch edit is over if one is
+     * in progress.</p>
      *
      * @param beforeLength The number of characters to be deleted before the
      *        current cursor position.
      * @param afterLength The number of characters to be deleted after the
      *        current cursor position.
-     *
-     * @return Returns true on success, false if the input connection is no longer
+     * @return true on success, false if the input connection is no longer
      * valid.
      */
     public boolean deleteSurroundingText(int beforeLength, int afterLength);
 
     /**
-     * Set composing text around the current cursor position with the given text,
-     * and set the new cursor position.  Any composing text set previously will
-     * be removed automatically.
-     * 
+     * Set composing text around the current cursor position with the
+     * given text, and set the new cursor position. Any composing text
+     * set previously will be removed automatically.
+     *
+     * <p>If there is any composing span currently active, all
+     * characters that it comprises are removed. The passed text is
+     * added in its place, and a composing span is added to this
+     * text. Finally, the cursor is moved to the location specified by
+     * <code>newCursorPosition</code>.</p>
+     *
+     * <p>This is usually called by IMEs to add or remove or change
+     * characters in the composing span. Calling this method will
+     * cause the editor to call
+     * {@link android.inputmethodservice.InputMethodService#onUpdateSelection(int, int, int, int, int, int)}
+     * on the current IME after the batch input is over.</p>
+     *
+     * <p><strong>Editor authors:</strong> please keep in mind the
+     * text may be very similar or completely different than what was
+     * in the composing span at call time, or there may not be a
+     * composing span at all. Please note that although it's not
+     * typical use, the string may be empty. Treat this normally,
+     * replacing the currently composing text with an empty string.
+     * Also, be careful with the cursor position. IMEs rely on this
+     * working exactly as described above. Since this changes the
+     * contents of the editor, you need to make the changes known to
+     * the input method by calling
+     * {@link InputMethodManager#updateSelection(View, int, int, int, int)},
+     * but be careful to wait until the batch edit is over if one is
+     * in progress. Note that this method can set the cursor position
+     * on either edge of the composing text or entirely outside it,
+     * but the IME may also go on to move the cursor position to
+     * within the composing text in a subsequent call so you should
+     * make no assumption at all: the composing text and the selection
+     * are entirely independent.</p>
+     *
      * @param text The composing text with styles if necessary. If no style
      *        object attached to the text, the default style for composing text
-     *        is used. See {#link android.text.Spanned} for how to attach style
-     *        object to the text. {#link android.text.SpannableString} and
-     *        {#link android.text.SpannableStringBuilder} are two
-     *        implementations of the interface {#link android.text.Spanned}.
-     * @param newCursorPosition The new cursor position around the text.  If
+     *        is used. See {@link android.text.Spanned} for how to attach style
+     *        object to the text. {@link android.text.SpannableString} and
+     *        {@link android.text.SpannableStringBuilder} are two
+     *        implementations of the interface {@link android.text.Spanned}.
+     * @param newCursorPosition The new cursor position around the text. If
      *        > 0, this is relative to the end of the text - 1; if <= 0, this
-     *        is relative to the start of the text.  So a value of 1 will
+     *        is relative to the start of the text. So a value of 1 will
      *        always advance you to the position after the full text being
-     *        inserted.  Note that this means you can't position the cursor
+     *        inserted. Note that this means you can't position the cursor
      *        within the text, because the editor can make modifications to
      *        the text you are providing so it is not possible to correctly
      *        specify locations there.
-     * 
-     * @return Returns true on success, false if the input connection is no longer
+     * @return true on success, false if the input connection is no longer
      * valid.
      */
     public boolean setComposingText(CharSequence text, int newCursorPosition);
 
     /**
-     * Mark a certain region of text as composing text. Any composing text set
-     * previously will be removed automatically. The default style for composing
-     * text is used.
+     * Mark a certain region of text as composing text. If there was a
+     * composing region, the characters are left as they were and the
+     * composing span removed, as if {@link #finishComposingText()}
+     * has been called. The default style for composing text is used.
+     *
+     * <p>The passed indices are clipped to the contents bounds. If
+     * the resulting region is zero-sized, no region is marked and the
+     * effect is the same as that of calling {@link #finishComposingText()}.
+     * The order of start and end is not important. In effect, the
+     * region from start to end and the region from end to start is
+     * the same. Editor authors, be ready to accept a start that is
+     * greater than end.</p>
+     *
+     * <p>Since this does not change the contents of the text, editors should not call
+     * {@link InputMethodManager#updateSelection(View, int, int, int, int)} and
+     * IMEs should not receive
+     * {@link android.inputmethodservice.InputMethodService#onUpdateSelection(int, int, int, int, int, int)}.
+     * </p>
+     *
+     * <p>This has no impact on the cursor/selection position. It may
+     * result in the cursor being anywhere inside or outside the
+     * composing region, including cases where the selection and the
+     * composing region overlap partially or entirely.</p>
      *
      * @param start the position in the text at which the composing region begins
      * @param end the position in the text at which the composing region ends
-     * @return Returns true on success, false if the input connection is no longer
+     * @return true on success, false if the input connection is no longer
      * valid.
      */
     public boolean setComposingRegion(int start, int end);
 
     /**
-     * Have the text editor finish whatever composing text is currently
-     * active.  This simply leaves the text as-is, removing any special
-     * composing styling or other state that was around it.  The cursor
-     * position remains unchanged.
+     * Have the text editor finish whatever composing text is
+     * currently active. This simply leaves the text as-is, removing
+     * any special composing styling or other state that was around
+     * it. The cursor position remains unchanged.
+     *
+     * <p><strong>IME authors:</strong> be aware that this call may be
+     * expensive with some editors.</p>
+     *
+     * <p><strong>Editor authors:</strong> please note that the cursor
+     * may be anywhere in the contents when this is called, including
+     * in the middle of the composing span or in a completely
+     * unrelated place. It must not move.</p>
+     *
+     * @return true on success, false if the input connection
+     * is no longer valid.
      */
     public boolean finishComposingText();
-    
+
     /**
      * Commit text to the text box and set the new cursor position.
-     * Any composing text set previously will be removed
-     * automatically.
-     * 
-     * @param text The committed text.
-     * @param newCursorPosition The new cursor position around the text.  If
+     *
+     * <p>This method removes the contents of the currently composing
+     * text and replaces it with the passed CharSequence, and then
+     * moves the cursor according to {@code newCursorPosition}.
+     * This behaves like calling
+     * {@link #setComposingText(CharSequence, int) setComposingText(text, newCursorPosition)}
+     * then {@link #finishComposingText()}.</p>
+     *
+     * <p>Calling this method will cause the editor to call
+     * {@link android.inputmethodservice.InputMethodService#onUpdateSelection(int, int, int, int, int, int)}
+     * on the current IME after the batch input is over.
+     * <strong>Editor authors</strong>, for this to happen you need to
+     * make the changes known to the input method by calling
+     * {@link InputMethodManager#updateSelection(View, int, int, int, int)},
+     * but be careful to wait until the batch edit is over if one is
+     * in progress.</p>
+     *
+     * @param text The committed text. This may include styles.
+     * @param newCursorPosition The new cursor position around the text. If
      *        > 0, this is relative to the end of the text - 1; if <= 0, this
-     *        is relative to the start of the text.  So a value of 1 will
+     *        is relative to the start of the text. So a value of 1 will
      *        always advance you to the position after the full text being
-     *        inserted.  Note that this means you can't position the cursor
+     *        inserted. Note that this means you can't position the cursor
      *        within the text, because the editor can make modifications to
      *        the text you are providing so it is not possible to correctly
      *        specify locations there.
-     * 
-     *        
-     * @return Returns true on success, false if the input connection is no longer
+     * @return true on success, false if the input connection is no longer
      * valid.
      */
     public boolean commitText(CharSequence text, int newCursorPosition);
@@ -223,49 +478,102 @@
     /**
      * Commit a completion the user has selected from the possible ones
      * previously reported to {@link InputMethodSession#displayCompletions
-     * InputMethodSession.displayCompletions()}.  This will result in the
-     * same behavior as if the user had selected the completion from the
-     * actual UI.
-     * 
+     * InputMethodSession#displayCompletions(CompletionInfo[])} or
+     * {@link InputMethodManager#displayCompletions
+     * InputMethodManager#displayCompletions(View, CompletionInfo[])}.
+     * This will result in the same behavior as if the user had
+     * selected the completion from the actual UI. In all other
+     * respects, this behaves like {@link #commitText(CharSequence, int)}.
+     *
+     * <p><strong>IME authors:</strong> please take care to send the
+     * same object that you received through
+     * {@link android.inputmethodservice.InputMethodService#onDisplayCompletions(CompletionInfo[])}.
+     * </p>
+     *
+     * <p><strong>Editor authors:</strong> if you never call
+     * {@link InputMethodSession#displayCompletions(CompletionInfo[])} or
+     * {@link InputMethodManager#displayCompletions(View, CompletionInfo[])} then
+     * a well-behaved IME should never call this on your input
+     * connection, but be ready to deal with misbehaving IMEs without
+     * crashing.</p>
+     *
+     * <p>Calling this method (with a valid {@link CompletionInfo} object)
+     * will cause the editor to call
+     * {@link android.inputmethodservice.InputMethodService#onUpdateSelection(int, int, int, int, int, int)}
+     * on the current IME after the batch input is over.
+     * <strong>Editor authors</strong>, for this to happen you need to
+     * make the changes known to the input method by calling
+     * {@link InputMethodManager#updateSelection(View, int, int, int, int)},
+     * but be careful to wait until the batch edit is over if one is
+     * in progress.</p>
+     *
      * @param text The committed completion.
-     *        
-     * @return Returns true on success, false if the input connection is no longer
+     * @return true on success, false if the input connection is no longer
      * valid.
      */
     public boolean commitCompletion(CompletionInfo text);
 
     /**
-     * Commit a correction automatically performed on the raw user's input. A typical example would
-     * be to correct typos using a dictionary.
+     * Commit a correction automatically performed on the raw user's input. A
+     * typical example would be to correct typos using a dictionary.
+     *
+     * <p>Calling this method will cause the editor to call
+     * {@link android.inputmethodservice.InputMethodService#onUpdateSelection(int, int, int, int, int, int)}
+     * on the current IME after the batch input is over.
+     * <strong>Editor authors</strong>, for this to happen you need to
+     * make the changes known to the input method by calling
+     * {@link InputMethodManager#updateSelection(View, int, int, int, int)},
+     * but be careful to wait until the batch edit is over if one is
+     * in progress.</p>
      *
      * @param correctionInfo Detailed information about the correction.
-     *
-     * @return True on success, false if the input connection is no longer valid.
+     * @return true on success, false if the input connection is no longer valid.
      */
     public boolean commitCorrection(CorrectionInfo correctionInfo);
 
     /**
-     * Set the selection of the text editor.  To set the cursor position,
-     * start and end should have the same value.
-     * @return Returns true on success, false if the input connection is no longer
+     * Set the selection of the text editor. To set the cursor
+     * position, start and end should have the same value.
+     *
+     * <p>Since this moves the cursor, calling this method will cause
+     * the editor to call
+     * {@link android.inputmethodservice.InputMethodService#onUpdateSelection(int, int, int, int, int, int)}
+     * on the current IME after the batch input is over.
+     * <strong>Editor authors</strong>, for this to happen you need to
+     * make the changes known to the input method by calling
+     * {@link InputMethodManager#updateSelection(View, int, int, int, int)},
+     * but be careful to wait until the batch edit is over if one is
+     * in progress.</p>
+     *
+     * <p>This has no effect on the composing region which must stay
+     * unchanged. The order of start and end is not important. In
+     * effect, the region from start to end and the region from end to
+     * start is the same. Editor authors, be ready to accept a start
+     * that is greater than end.</p>
+     *
+     * @param start the character index where the selection should start.
+     * @param end the character index where the selection should end.
+     * @return true on success, false if the input connection is no longer
      * valid.
      */
     public boolean setSelection(int start, int end);
-    
+
     /**
      * Have the editor perform an action it has said it can do.
-     * 
+     *
+     * <p>This is typically used by IMEs when the user presses the key
+     * associated with the action.</p>
+     *
      * @param editorAction This must be one of the action constants for
      * {@link EditorInfo#imeOptions EditorInfo.editorType}, such as
      * {@link EditorInfo#IME_ACTION_GO EditorInfo.EDITOR_ACTION_GO}.
-     * 
-     * @return Returns true on success, false if the input connection is no longer
+     * @return true on success, false if the input connection is no longer
      * valid.
      */
     public boolean performEditorAction(int editorAction);
-    
+
     /**
-     * Perform a context menu action on the field.  The given id may be one of:
+     * Perform a context menu action on the field. The given id may be one of:
      * {@link android.R.id#selectAll},
      * {@link android.R.id#startSelectingText}, {@link android.R.id#stopSelectingText},
      * {@link android.R.id#cut}, {@link android.R.id#copy},
@@ -273,50 +581,82 @@
      * or {@link android.R.id#switchInputMethod}
      */
     public boolean performContextMenuAction(int id);
-    
+
     /**
-     * Tell the editor that you are starting a batch of editor operations.
-     * The editor will try to avoid sending you updates about its state
-     * until {@link #endBatchEdit} is called.
+     * Tell the editor that you are starting a batch of editor
+     * operations. The editor will try to avoid sending you updates
+     * about its state until {@link #endBatchEdit} is called. Batch
+     * edits nest.
+     *
+     * <p><strong>IME authors:</strong> use this to avoid getting
+     * calls to
+     * {@link android.inputmethodservice.InputMethodService#onUpdateSelection(int, int, int, int, int, int)}
+     * corresponding to intermediate state. Also, use this to avoid
+     * flickers that may arise from displaying intermediate state. Be
+     * sure to call {@link #endBatchEdit} for each call to this, or
+     * you may block updates in the editor.</p>
+     *
+     * <p><strong>Editor authors:</strong> while a batch edit is in
+     * progress, take care not to send updates to the input method and
+     * not to update the display. IMEs use this intensively to this
+     * effect. Also please note that batch edits need to nest
+     * correctly.</p>
+     *
+     * @return true if a batch edit is now in progress, false otherwise. Since
+     * this method starts a batch edit, that means it will always return true
+     * unless the input connection is no longer valid.
      */
     public boolean beginBatchEdit();
-    
+
     /**
      * Tell the editor that you are done with a batch edit previously
-     * initiated with {@link #beginBatchEdit}.
+     * initiated with {@link #beginBatchEdit}. This ends the latest
+     * batch only.
+     *
+     * <p><strong>IME authors:</strong> make sure you call this
+     * exactly once for each call to {@link #beginBatchEdit}.</p>
+     *
+     * <p><strong>Editor authors:</strong> please be careful about
+     * batch edit nesting. Updates still to be held back until the end
+     * of the last batch edit.</p>
+     *
+     * @return true if there is still a batch edit in progress after closing
+     * the latest one (in other words, if the nesting count is > 0), false
+     * otherwise or if the input connection is no longer valid.
      */
     public boolean endBatchEdit();
-    
+
     /**
-     * Send a key event to the process that is currently attached through
-     * this input connection.  The event will be dispatched like a normal
-     * key event, to the currently focused; this generally is the view that
-     * is providing this InputConnection, but due to the asynchronous nature
-     * of this protocol that can not be guaranteed and the focus may have
-     * changed by the time the event is received.
-     * 
-     * <p>
-     * This method can be used to send key events to the application. For
-     * example, an on-screen keyboard may use this method to simulate a hardware
-     * keyboard. There are three types of standard keyboards, numeric (12-key),
-     * predictive (20-key) and ALPHA (QWERTY). You can specify the keyboard type
-     * by specify the device id of the key event.
-     * 
-     * <p>
-     * You will usually want to set the flag
-     * {@link KeyEvent#FLAG_SOFT_KEYBOARD KeyEvent.FLAG_SOFT_KEYBOARD} on all
-     * key event objects you give to this API; the flag will not be set
-     * for you.
+     * Send a key event to the process that is currently attached
+     * through this input connection. The event will be dispatched
+     * like a normal key event, to the currently focused view; this
+     * generally is the view that is providing this InputConnection,
+     * but due to the asynchronous nature of this protocol that can
+     * not be guaranteed and the focus may have changed by the time
+     * the event is received.
      *
-     * <p>Note that it's discouraged to send such key events in normal operation;
-     * this is mainly for use with {@link android.text.InputType#TYPE_NULL} type
-     * text fields. Use the {@link #commitText} family of methods to send text
-     * to the application instead.
+     * <p>This method can be used to send key events to the
+     * application. For example, an on-screen keyboard may use this
+     * method to simulate a hardware keyboard. There are three types
+     * of standard keyboards, numeric (12-key), predictive (20-key)
+     * and ALPHA (QWERTY). You can specify the keyboard type by
+     * specify the device id of the key event.</p>
+     *
+     * <p>You will usually want to set the flag
+     * {@link KeyEvent#FLAG_SOFT_KEYBOARD KeyEvent.FLAG_SOFT_KEYBOARD}
+     * on all key event objects you give to this API; the flag will
+     * not be set for you.</p>
+     *
+     * <p>Note that it's discouraged to send such key events in normal
+     * operation; this is mainly for use with
+     * {@link android.text.InputType#TYPE_NULL} type text fields. Use
+     * the {@link #commitText} family of methods to send text to the
+     * application instead.</p>
+     *
      * @param event The key event.
-     *        
-     * @return Returns true on success, false if the input connection is no longer
+     * @return true on success, false if the input connection is no longer
      * valid.
-     * 
+     *
      * @see KeyEvent
      * @see KeyCharacterMap#NUMERIC
      * @see KeyCharacterMap#PREDICTIVE
@@ -325,37 +665,46 @@
     public boolean sendKeyEvent(KeyEvent event);
 
     /**
-     * Clear the given meta key pressed states in the given input connection.
-     * 
+     * Clear the given meta key pressed states in the given input
+     * connection.
+     *
+     * <p>This can be used by the IME to clear the meta key states set
+     * by a hardware keyboard with latched meta keys, if the editor
+     * keeps track of these.</p>
+     *
      * @param states The states to be cleared, may be one or more bits as
      * per {@link KeyEvent#getMetaState() KeyEvent.getMetaState()}.
-     * 
-     * @return Returns true on success, false if the input connection is no longer
+     * @return true on success, false if the input connection is no longer
      * valid.
      */
     public boolean clearMetaKeyStates(int states);
-    
+
     /**
-     * Called by the IME to tell the client when it switches between fullscreen
-     * and normal modes.  This will normally be called for you by the standard
-     * implementation of {@link android.inputmethodservice.InputMethodService}.
+     * Called by the IME to tell the client when it switches between
+     * fullscreen and normal modes. This will normally be called for
+     * you by the standard implementation of
+     * {@link android.inputmethodservice.InputMethodService}.
+     *
+     * @return true on success, false if the input connection is no longer
+     * valid.
      */
     public boolean reportFullscreenMode(boolean enabled);
-    
+
     /**
-     * API to send private commands from an input method to its connected
-     * editor.  This can be used to provide domain-specific features that are
-     * only known between certain input methods and their clients.  Note that
-     * because the InputConnection protocol is asynchronous, you have no way
-     * to get a result back or know if the client understood the command; you
-     * can use the information in {@link EditorInfo} to determine if
-     * a client supports a particular command.
-     * 
-     * @param action Name of the command to be performed.  This <em>must</em>
+     * API to send private commands from an input method to its
+     * connected editor. This can be used to provide domain-specific
+     * features that are only known between certain input methods and
+     * their clients. Note that because the InputConnection protocol
+     * is asynchronous, you have no way to get a result back or know
+     * if the client understood the command; you can use the
+     * information in {@link EditorInfo} to determine if a client
+     * supports a particular command.
+     *
+     * @param action Name of the command to be performed. This <em>must</em>
      * be a scoped name, i.e. prefixed with a package name you own, so that
      * different developers will not create conflicting commands.
      * @param data Any data to include with the command.
-     * @return Returns true if the command was sent (whether or not the
+     * @return true if the command was sent (whether or not the
      * associated editor understood it), false if the input connection is no longer
      * valid.
      */
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index 8ae0021..19492c2 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -500,6 +500,12 @@
      * Sets the default zoom density of the page. This must be called from the UI
      * thread. The default is {@link ZoomDensity#MEDIUM}.
      *
+     * This setting is not recommended for use in new applications.  If the WebView
+     * is utilized to display mobile-oriented pages, the desired effect can be achieved by
+     * adjusting 'width' and 'initial-scale' attributes of page's 'meta viewport'
+     * tag. For pages lacking the tag, {@link android.webkit.WebView#setInitialScale}
+     * and {@link #setUseWideViewPort} can be used.
+     *
      * @param zoom the zoom density
      */
     public void setDefaultZoom(ZoomDensity zoom) {
@@ -510,6 +516,8 @@
      * Gets the default zoom density of the page. This should be called from
      * the UI thread.
      *
+     * This setting is not recommended for use in new applications.
+     *
      * @return the zoom density
      * @see #setDefaultZoom
      */
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 4c0ccca..ba85c1a 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -1615,10 +1615,12 @@
 
         public static final Parcelable.Creator<SavedState> CREATOR
                 = new Parcelable.Creator<SavedState>() {
+            @Override
             public SavedState createFromParcel(Parcel in) {
                 return new SavedState(in);
             }
 
+            @Override
             public SavedState[] newArray(int size) {
                 return new SavedState[size];
             }
@@ -1943,8 +1945,8 @@
             }
 
             final int top = getChildAt(0).getTop();
-            final float fadeLength = (float) getVerticalFadingEdgeLength();
-            return top < mPaddingTop ? (float) -(top - mPaddingTop) / fadeLength : fadeEdge;
+            final float fadeLength = getVerticalFadingEdgeLength();
+            return top < mPaddingTop ? -(top - mPaddingTop) / fadeLength : fadeEdge;
         }
     }
 
@@ -1961,9 +1963,9 @@
 
             final int bottom = getChildAt(count - 1).getBottom();
             final int height = getHeight();
-            final float fadeLength = (float) getVerticalFadingEdgeLength();
+            final float fadeLength = getVerticalFadingEdgeLength();
             return bottom > height - mPaddingBottom ?
-                    (float) (bottom - height + mPaddingBottom) / fadeLength : fadeEdge;
+                    (bottom - height + mPaddingBottom) / fadeLength : fadeEdge;
         }
     }
 
@@ -2771,6 +2773,7 @@
     private class PerformClick extends WindowRunnnable implements Runnable {
         int mClickMotionPosition;
 
+        @Override
         public void run() {
             // The data has changed since we posted this action in the event queue,
             // bail out before bad things happen
@@ -2792,6 +2795,7 @@
     }
 
     private class CheckForLongPress extends WindowRunnnable implements Runnable {
+        @Override
         public void run() {
             final int motionPosition = mMotionPosition;
             final View child = getChildAt(motionPosition - mFirstPosition);
@@ -2815,6 +2819,7 @@
     }
 
     private class CheckForKeyLongPress extends WindowRunnnable implements Runnable {
+        @Override
         public void run() {
             if (isPressed() && mSelectedPosition >= 0) {
                 int index = mSelectedPosition - mFirstPosition;
@@ -2989,6 +2994,7 @@
     }
 
     final class CheckForTap implements Runnable {
+        @Override
         public void run() {
             if (mTouchMode == TOUCH_MODE_DOWN) {
                 mTouchMode = TOUCH_MODE_TAP;
@@ -3239,6 +3245,7 @@
         }
     }
 
+    @Override
     public void onTouchModeChanged(boolean isInTouchMode) {
         if (isInTouchMode) {
             // Get rid of the selection when we enter touch mode
@@ -3299,95 +3306,153 @@
             }
         }
 
-        final int action = ev.getAction();
-
-        View v;
-
         initVelocityTrackerIfNotExists();
         mVelocityTracker.addMovement(ev);
 
-        switch (action & MotionEvent.ACTION_MASK) {
-        case MotionEvent.ACTION_DOWN: {
-            switch (mTouchMode) {
-            case TOUCH_MODE_OVERFLING: {
-                mFlingRunnable.endFling();
-                if (mPositionScroller != null) {
-                    mPositionScroller.stop();
-                }
-                mTouchMode = TOUCH_MODE_OVERSCROLL;
-                mMotionX = (int) ev.getX();
-                mMotionY = mLastY = (int) ev.getY();
-                mMotionCorrection = 0;
-                mActivePointerId = ev.getPointerId(0);
-                mDirection = 0;
+        final int actionMasked = ev.getActionMasked();
+        switch (actionMasked) {
+            case MotionEvent.ACTION_DOWN: {
+                onTouchDown(ev);
                 break;
             }
 
-            default: {
-                mActivePointerId = ev.getPointerId(0);
-                final int x = (int) ev.getX();
-                final int y = (int) ev.getY();
-                int motionPosition = pointToPosition(x, y);
-                if (!mDataChanged) {
-                    if ((mTouchMode != TOUCH_MODE_FLING) && (motionPosition >= 0)
-                            && (getAdapter().isEnabled(motionPosition))) {
-                        // User clicked on an actual view (and was not stopping a fling).
-                        // It might be a click or a scroll. Assume it is a click until
-                        // proven otherwise
-                        mTouchMode = TOUCH_MODE_DOWN;
-                        // FIXME Debounce
-                        if (mPendingCheckForTap == null) {
-                            mPendingCheckForTap = new CheckForTap();
-                        }
-                        postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
-                    } else {
-                        if (mTouchMode == TOUCH_MODE_FLING) {
-                            // Stopped a fling. It is a scroll.
-                            createScrollingCache();
-                            mTouchMode = TOUCH_MODE_SCROLL;
-                            mMotionCorrection = 0;
-                            motionPosition = findMotionRow(y);
-                            mFlingRunnable.flywheelTouch();
-                        }
-                    }
-                }
+            case MotionEvent.ACTION_MOVE: {
+                onTouchMove(ev);
+                break;
+            }
 
+            case MotionEvent.ACTION_UP: {
+                onTouchUp(ev);
+                break;
+            }
+
+            case MotionEvent.ACTION_CANCEL: {
+                onTouchCancel();
+                break;
+            }
+
+            case MotionEvent.ACTION_POINTER_UP: {
+                onSecondaryPointerUp(ev);
+                final int x = mMotionX;
+                final int y = mMotionY;
+                final int motionPosition = pointToPosition(x, y);
                 if (motionPosition >= 0) {
                     // Remember where the motion event started
-                    v = getChildAt(motionPosition - mFirstPosition);
-                    mMotionViewOriginalTop = v.getTop();
+                    final View child = getChildAt(motionPosition - mFirstPosition);
+                    mMotionViewOriginalTop = child.getTop();
+                    mMotionPosition = motionPosition;
                 }
-                mMotionX = x;
-                mMotionY = y;
-                mMotionPosition = motionPosition;
-                mLastY = Integer.MIN_VALUE;
+                mLastY = y;
                 break;
             }
-            }
 
-            if (performButtonActionOnTouchDown(ev)) {
-                if (mTouchMode == TOUCH_MODE_DOWN) {
-                    removeCallbacks(mPendingCheckForTap);
+            case MotionEvent.ACTION_POINTER_DOWN: {
+                // New pointers take over dragging duties
+                final int index = ev.getActionIndex();
+                final int id = ev.getPointerId(index);
+                final int x = (int) ev.getX(index);
+                final int y = (int) ev.getY(index);
+                mMotionCorrection = 0;
+                mActivePointerId = id;
+                mMotionX = x;
+                mMotionY = y;
+                final int motionPosition = pointToPosition(x, y);
+                if (motionPosition >= 0) {
+                    // Remember where the motion event started
+                    final View child = getChildAt(motionPosition - mFirstPosition);
+                    mMotionViewOriginalTop = child.getTop();
+                    mMotionPosition = motionPosition;
                 }
+                mLastY = y;
+                break;
             }
+        }
+
+        return true;
+    }
+
+    private void onTouchDown(MotionEvent ev) {
+        View v;
+        switch (mTouchMode) {
+        case TOUCH_MODE_OVERFLING: {
+            mFlingRunnable.endFling();
+            if (mPositionScroller != null) {
+                mPositionScroller.stop();
+            }
+            mTouchMode = TOUCH_MODE_OVERSCROLL;
+            mMotionX = (int) ev.getX();
+            mMotionY = mLastY = (int) ev.getY();
+            mMotionCorrection = 0;
+            mActivePointerId = ev.getPointerId(0);
+            mDirection = 0;
             break;
         }
 
-        case MotionEvent.ACTION_MOVE: {
-            int pointerIndex = ev.findPointerIndex(mActivePointerId);
-            if (pointerIndex == -1) {
-                pointerIndex = 0;
-                mActivePointerId = ev.getPointerId(pointerIndex);
-            }
-            final int y = (int) ev.getY(pointerIndex);
-
-            if (mDataChanged) {
-                // Re-sync everything if data has been changed
-                // since the scroll operation can query the adapter.
-                layoutChildren();
+        default: {
+            mActivePointerId = ev.getPointerId(0);
+            final int x = (int) ev.getX();
+            final int y = (int) ev.getY();
+            int motionPosition = pointToPosition(x, y);
+            if (!mDataChanged) {
+                if ((mTouchMode != TOUCH_MODE_FLING) && (motionPosition >= 0)
+                        && (getAdapter().isEnabled(motionPosition))) {
+                    // User clicked on an actual view (and was not stopping a fling).
+                    // It might be a click or a scroll. Assume it is a click until
+                    // proven otherwise
+                    mTouchMode = TOUCH_MODE_DOWN;
+                    // FIXME Debounce
+                    if (mPendingCheckForTap == null) {
+                        mPendingCheckForTap = new CheckForTap();
+                    }
+                    postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
+                } else {
+                    if (mTouchMode == TOUCH_MODE_FLING) {
+                        // Stopped a fling. It is a scroll.
+                        createScrollingCache();
+                        mTouchMode = TOUCH_MODE_SCROLL;
+                        mMotionCorrection = 0;
+                        motionPosition = findMotionRow(y);
+                        mFlingRunnable.flywheelTouch();
+                    }
+                }
             }
 
-            switch (mTouchMode) {
+            if (motionPosition >= 0) {
+                // Remember where the motion event started
+                v = getChildAt(motionPosition - mFirstPosition);
+                mMotionViewOriginalTop = v.getTop();
+            }
+            mMotionX = x;
+            mMotionY = y;
+            mMotionPosition = motionPosition;
+            mLastY = Integer.MIN_VALUE;
+            break;
+        }
+        }
+
+        if (performButtonActionOnTouchDown(ev)) {
+            if (mTouchMode == TOUCH_MODE_DOWN) {
+                removeCallbacks(mPendingCheckForTap);
+            }
+        }
+    }
+
+    private void onTouchMove(MotionEvent ev) {
+        int pointerIndex = ev.findPointerIndex(mActivePointerId);
+        if (pointerIndex == -1) {
+            pointerIndex = 0;
+            mActivePointerId = ev.getPointerId(pointerIndex);
+        }
+
+        if (mDataChanged) {
+            // Re-sync everything if data has been changed
+            // since the scroll operation can query the adapter.
+            layoutChildren();
+        }
+
+        final int y = (int) ev.getY(pointerIndex);
+
+        switch (mTouchMode) {
             case TOUCH_MODE_DOWN:
             case TOUCH_MODE_TAP:
             case TOUCH_MODE_DONE_WAITING:
@@ -3399,162 +3464,205 @@
             case TOUCH_MODE_OVERSCROLL:
                 scrollIfNeeded(y);
                 break;
+        }
+    }
+
+    private void onTouchUp(MotionEvent ev) {
+        switch (mTouchMode) {
+        case TOUCH_MODE_DOWN:
+        case TOUCH_MODE_TAP:
+        case TOUCH_MODE_DONE_WAITING:
+            final int motionPosition = mMotionPosition;
+            final View child = getChildAt(motionPosition - mFirstPosition);
+
+            final float x = ev.getX();
+            final boolean inList = x > mListPadding.left && x < getWidth() - mListPadding.right;
+
+            if (child != null && !child.hasFocusable() && inList) {
+                if (mTouchMode != TOUCH_MODE_DOWN) {
+                    child.setPressed(false);
+                }
+
+                if (mPerformClick == null) {
+                    mPerformClick = new PerformClick();
+                }
+
+                final AbsListView.PerformClick performClick = mPerformClick;
+                performClick.mClickMotionPosition = motionPosition;
+                performClick.rememberWindowAttachCount();
+
+                mResurrectToPosition = motionPosition;
+
+                if (mTouchMode == TOUCH_MODE_DOWN || mTouchMode == TOUCH_MODE_TAP) {
+                    final Handler handler = getHandler();
+                    if (handler != null) {
+                        handler.removeCallbacks(mTouchMode == TOUCH_MODE_DOWN ?
+                                mPendingCheckForTap : mPendingCheckForLongPress);
+                    }
+                    mLayoutMode = LAYOUT_NORMAL;
+                    if (!mDataChanged && mAdapter.isEnabled(motionPosition)) {
+                        mTouchMode = TOUCH_MODE_TAP;
+                        setSelectedPositionInt(mMotionPosition);
+                        layoutChildren();
+                        child.setPressed(true);
+                        positionSelector(mMotionPosition, child);
+                        setPressed(true);
+                        if (mSelector != null) {
+                            Drawable d = mSelector.getCurrent();
+                            if (d != null && d instanceof TransitionDrawable) {
+                                ((TransitionDrawable) d).resetTransition();
+                            }
+                        }
+                        if (mTouchModeReset != null) {
+                            removeCallbacks(mTouchModeReset);
+                        }
+                        mTouchModeReset = new Runnable() {
+                            @Override
+                            public void run() {
+                                mTouchModeReset = null;
+                                mTouchMode = TOUCH_MODE_REST;
+                                child.setPressed(false);
+                                setPressed(false);
+                                if (!mDataChanged) {
+                                    performClick.run();
+                                }
+                            }
+                        };
+                        postDelayed(mTouchModeReset,
+                                ViewConfiguration.getPressedStateDuration());
+                    } else {
+                        mTouchMode = TOUCH_MODE_REST;
+                        updateSelectorState();
+                    }
+                    return;
+                } else if (!mDataChanged && mAdapter.isEnabled(motionPosition)) {
+                    performClick.run();
+                }
             }
+            mTouchMode = TOUCH_MODE_REST;
+            updateSelectorState();
+            break;
+        case TOUCH_MODE_SCROLL:
+            final int childCount = getChildCount();
+            if (childCount > 0) {
+                final int firstChildTop = getChildAt(0).getTop();
+                final int lastChildBottom = getChildAt(childCount - 1).getBottom();
+                final int contentTop = mListPadding.top;
+                final int contentBottom = getHeight() - mListPadding.bottom;
+                if (mFirstPosition == 0 && firstChildTop >= contentTop &&
+                        mFirstPosition + childCount < mItemCount &&
+                        lastChildBottom <= getHeight() - contentBottom) {
+                    mTouchMode = TOUCH_MODE_REST;
+                    reportScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE);
+                } else {
+                    final VelocityTracker velocityTracker = mVelocityTracker;
+                    velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
+
+                    final int initialVelocity = (int)
+                            (velocityTracker.getYVelocity(mActivePointerId) * mVelocityScale);
+                    // Fling if we have enough velocity and we aren't at a boundary.
+                    // Since we can potentially overfling more than we can overscroll, don't
+                    // allow the weird behavior where you can scroll to a boundary then
+                    // fling further.
+                    if (Math.abs(initialVelocity) > mMinimumVelocity &&
+                            !((mFirstPosition == 0 &&
+                                    firstChildTop == contentTop - mOverscrollDistance) ||
+                              (mFirstPosition + childCount == mItemCount &&
+                                    lastChildBottom == contentBottom + mOverscrollDistance))) {
+                        if (mFlingRunnable == null) {
+                            mFlingRunnable = new FlingRunnable();
+                        }
+                        reportScrollStateChange(OnScrollListener.SCROLL_STATE_FLING);
+
+                        mFlingRunnable.start(-initialVelocity);
+                    } else {
+                        mTouchMode = TOUCH_MODE_REST;
+                        reportScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE);
+                        if (mFlingRunnable != null) {
+                            mFlingRunnable.endFling();
+                        }
+                        if (mPositionScroller != null) {
+                            mPositionScroller.stop();
+                        }
+                    }
+                }
+            } else {
+                mTouchMode = TOUCH_MODE_REST;
+                reportScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE);
+            }
+            break;
+
+        case TOUCH_MODE_OVERSCROLL:
+            if (mFlingRunnable == null) {
+                mFlingRunnable = new FlingRunnable();
+            }
+            final VelocityTracker velocityTracker = mVelocityTracker;
+            velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
+            final int initialVelocity = (int) velocityTracker.getYVelocity(mActivePointerId);
+
+            reportScrollStateChange(OnScrollListener.SCROLL_STATE_FLING);
+            if (Math.abs(initialVelocity) > mMinimumVelocity) {
+                mFlingRunnable.startOverfling(-initialVelocity);
+            } else {
+                mFlingRunnable.startSpringback();
+            }
+
             break;
         }
 
-        case MotionEvent.ACTION_UP: {
-            switch (mTouchMode) {
-            case TOUCH_MODE_DOWN:
-            case TOUCH_MODE_TAP:
-            case TOUCH_MODE_DONE_WAITING:
-                final int motionPosition = mMotionPosition;
-                final View child = getChildAt(motionPosition - mFirstPosition);
+        setPressed(false);
 
-                final float x = ev.getX();
-                final boolean inList = x > mListPadding.left && x < getWidth() - mListPadding.right;
+        if (mEdgeGlowTop != null) {
+            mEdgeGlowTop.onRelease();
+            mEdgeGlowBottom.onRelease();
+        }
 
-                if (child != null && !child.hasFocusable() && inList) {
-                    if (mTouchMode != TOUCH_MODE_DOWN) {
-                        child.setPressed(false);
-                    }
+        // Need to redraw since we probably aren't drawing the selector anymore
+        invalidate();
 
-                    if (mPerformClick == null) {
-                        mPerformClick = new PerformClick();
-                    }
+        final Handler handler = getHandler();
+        if (handler != null) {
+            handler.removeCallbacks(mPendingCheckForLongPress);
+        }
 
-                    final AbsListView.PerformClick performClick = mPerformClick;
-                    performClick.mClickMotionPosition = motionPosition;
-                    performClick.rememberWindowAttachCount();
+        recycleVelocityTracker();
 
-                    mResurrectToPosition = motionPosition;
+        mActivePointerId = INVALID_POINTER;
 
-                    if (mTouchMode == TOUCH_MODE_DOWN || mTouchMode == TOUCH_MODE_TAP) {
-                        final Handler handler = getHandler();
-                        if (handler != null) {
-                            handler.removeCallbacks(mTouchMode == TOUCH_MODE_DOWN ?
-                                    mPendingCheckForTap : mPendingCheckForLongPress);
-                        }
-                        mLayoutMode = LAYOUT_NORMAL;
-                        if (!mDataChanged && mAdapter.isEnabled(motionPosition)) {
-                            mTouchMode = TOUCH_MODE_TAP;
-                            setSelectedPositionInt(mMotionPosition);
-                            layoutChildren();
-                            child.setPressed(true);
-                            positionSelector(mMotionPosition, child);
-                            setPressed(true);
-                            if (mSelector != null) {
-                                Drawable d = mSelector.getCurrent();
-                                if (d != null && d instanceof TransitionDrawable) {
-                                    ((TransitionDrawable) d).resetTransition();
-                                }
-                            }
-                            if (mTouchModeReset != null) {
-                                removeCallbacks(mTouchModeReset);
-                            }
-                            mTouchModeReset = new Runnable() {
-                                @Override
-                                public void run() {
-                                    mTouchModeReset = null;
-                                    mTouchMode = TOUCH_MODE_REST;
-                                    child.setPressed(false);
-                                    setPressed(false);
-                                    if (!mDataChanged) {
-                                        performClick.run();
-                                    }
-                                }
-                            };
-                            postDelayed(mTouchModeReset,
-                                    ViewConfiguration.getPressedStateDuration());
-                        } else {
-                            mTouchMode = TOUCH_MODE_REST;
-                            updateSelectorState();
-                        }
-                        return true;
-                    } else if (!mDataChanged && mAdapter.isEnabled(motionPosition)) {
-                        performClick.run();
-                    }
-                }
-                mTouchMode = TOUCH_MODE_REST;
-                updateSelectorState();
-                break;
-            case TOUCH_MODE_SCROLL:
-                final int childCount = getChildCount();
-                if (childCount > 0) {
-                    final int firstChildTop = getChildAt(0).getTop();
-                    final int lastChildBottom = getChildAt(childCount - 1).getBottom();
-                    final int contentTop = mListPadding.top;
-                    final int contentBottom = getHeight() - mListPadding.bottom;
-                    if (mFirstPosition == 0 && firstChildTop >= contentTop &&
-                            mFirstPosition + childCount < mItemCount &&
-                            lastChildBottom <= getHeight() - contentBottom) {
-                        mTouchMode = TOUCH_MODE_REST;
-                        reportScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE);
-                    } else {
-                        final VelocityTracker velocityTracker = mVelocityTracker;
-                        velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
-
-                        final int initialVelocity = (int)
-                                (velocityTracker.getYVelocity(mActivePointerId) * mVelocityScale);
-                        // Fling if we have enough velocity and we aren't at a boundary.
-                        // Since we can potentially overfling more than we can overscroll, don't
-                        // allow the weird behavior where you can scroll to a boundary then
-                        // fling further.
-                        if (Math.abs(initialVelocity) > mMinimumVelocity &&
-                                !((mFirstPosition == 0 &&
-                                        firstChildTop == contentTop - mOverscrollDistance) ||
-                                  (mFirstPosition + childCount == mItemCount &&
-                                        lastChildBottom == contentBottom + mOverscrollDistance))) {
-                            if (mFlingRunnable == null) {
-                                mFlingRunnable = new FlingRunnable();
-                            }
-                            reportScrollStateChange(OnScrollListener.SCROLL_STATE_FLING);
-
-                            mFlingRunnable.start(-initialVelocity);
-                        } else {
-                            mTouchMode = TOUCH_MODE_REST;
-                            reportScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE);
-                            if (mFlingRunnable != null) {
-                                mFlingRunnable.endFling();
-                            }
-                            if (mPositionScroller != null) {
-                                mPositionScroller.stop();
-                            }
-                        }
-                    }
-                } else {
-                    mTouchMode = TOUCH_MODE_REST;
-                    reportScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE);
-                }
-                break;
-
-            case TOUCH_MODE_OVERSCROLL:
-                if (mFlingRunnable == null) {
-                    mFlingRunnable = new FlingRunnable();
-                }
-                final VelocityTracker velocityTracker = mVelocityTracker;
-                velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
-                final int initialVelocity = (int) velocityTracker.getYVelocity(mActivePointerId);
-
-                reportScrollStateChange(OnScrollListener.SCROLL_STATE_FLING);
-                if (Math.abs(initialVelocity) > mMinimumVelocity) {
-                    mFlingRunnable.startOverfling(-initialVelocity);
-                } else {
-                    mFlingRunnable.startSpringback();
-                }
-
-                break;
+        if (PROFILE_SCROLLING) {
+            if (mScrollProfilingStarted) {
+                Debug.stopMethodTracing();
+                mScrollProfilingStarted = false;
             }
+        }
 
+        if (mScrollStrictSpan != null) {
+            mScrollStrictSpan.finish();
+            mScrollStrictSpan = null;
+        }
+    }
+
+    private void onTouchCancel() {
+        switch (mTouchMode) {
+        case TOUCH_MODE_OVERSCROLL:
+            if (mFlingRunnable == null) {
+                mFlingRunnable = new FlingRunnable();
+            }
+            mFlingRunnable.startSpringback();
+            break;
+
+        case TOUCH_MODE_OVERFLING:
+            // Do nothing - let it play out.
+            break;
+
+        default:
+            mTouchMode = TOUCH_MODE_REST;
             setPressed(false);
-
-            if (mEdgeGlowTop != null) {
-                mEdgeGlowTop.onRelease();
-                mEdgeGlowBottom.onRelease();
+            View motionView = this.getChildAt(mMotionPosition - mFirstPosition);
+            if (motionView != null) {
+                motionView.setPressed(false);
             }
-
-            // Need to redraw since we probably aren't drawing the selector anymore
-            invalidate();
+            clearScrollingCache();
 
             final Handler handler = getHandler();
             if (handler != null) {
@@ -3562,99 +3670,13 @@
             }
 
             recycleVelocityTracker();
-
-            mActivePointerId = INVALID_POINTER;
-
-            if (PROFILE_SCROLLING) {
-                if (mScrollProfilingStarted) {
-                    Debug.stopMethodTracing();
-                    mScrollProfilingStarted = false;
-                }
-            }
-
-            if (mScrollStrictSpan != null) {
-                mScrollStrictSpan.finish();
-                mScrollStrictSpan = null;
-            }
-            break;
         }
 
-        case MotionEvent.ACTION_CANCEL: {
-            switch (mTouchMode) {
-            case TOUCH_MODE_OVERSCROLL:
-                if (mFlingRunnable == null) {
-                    mFlingRunnable = new FlingRunnable();
-                }
-                mFlingRunnable.startSpringback();
-                break;
-
-            case TOUCH_MODE_OVERFLING:
-                // Do nothing - let it play out.
-                break;
-
-            default:
-                mTouchMode = TOUCH_MODE_REST;
-                setPressed(false);
-                View motionView = this.getChildAt(mMotionPosition - mFirstPosition);
-                if (motionView != null) {
-                    motionView.setPressed(false);
-                }
-                clearScrollingCache();
-
-                final Handler handler = getHandler();
-                if (handler != null) {
-                    handler.removeCallbacks(mPendingCheckForLongPress);
-                }
-
-                recycleVelocityTracker();
-            }
-
-            if (mEdgeGlowTop != null) {
-                mEdgeGlowTop.onRelease();
-                mEdgeGlowBottom.onRelease();
-            }
-            mActivePointerId = INVALID_POINTER;
-            break;
+        if (mEdgeGlowTop != null) {
+            mEdgeGlowTop.onRelease();
+            mEdgeGlowBottom.onRelease();
         }
-
-        case MotionEvent.ACTION_POINTER_UP: {
-            onSecondaryPointerUp(ev);
-            final int x = mMotionX;
-            final int y = mMotionY;
-            final int motionPosition = pointToPosition(x, y);
-            if (motionPosition >= 0) {
-                // Remember where the motion event started
-                v = getChildAt(motionPosition - mFirstPosition);
-                mMotionViewOriginalTop = v.getTop();
-                mMotionPosition = motionPosition;
-            }
-            mLastY = y;
-            break;
-        }
-
-        case MotionEvent.ACTION_POINTER_DOWN: {
-            // New pointers take over dragging duties
-            final int index = ev.getActionIndex();
-            final int id = ev.getPointerId(index);
-            final int x = (int) ev.getX(index);
-            final int y = (int) ev.getY(index);
-            mMotionCorrection = 0;
-            mActivePointerId = id;
-            mMotionX = x;
-            mMotionY = y;
-            final int motionPosition = pointToPosition(x, y);
-            if (motionPosition >= 0) {
-                // Remember where the motion event started
-                v = getChildAt(motionPosition - mFirstPosition);
-                mMotionViewOriginalTop = v.getTop();
-                mMotionPosition = motionPosition;
-            }
-            mLastY = y;
-            break;
-        }
-        }
-
-        return true;
+        mActivePointerId = INVALID_POINTER;
     }
 
     @Override
@@ -3733,7 +3755,7 @@
             if (scrollY != 0) {
                 // Pin to the top/bottom during overscroll
                 int restoreCount = canvas.save();
-                canvas.translate(0, (float) scrollY);
+                canvas.translate(0, scrollY);
                 mFastScroller.draw(canvas);
                 canvas.restoreToCount(restoreCount);
             } else {
@@ -3945,6 +3967,7 @@
         private int mLastFlingY;
 
         private final Runnable mCheckFlywheel = new Runnable() {
+            @Override
             public void run() {
                 final int activeId = mActivePointerId;
                 final VelocityTracker vt = mVelocityTracker;
@@ -4066,6 +4089,7 @@
             postDelayed(mCheckFlywheel, FLYWHEEL_TIMEOUT);
         }
 
+        @Override
         public void run() {
             switch (mTouchMode) {
             default:
@@ -4455,6 +4479,7 @@
             removeCallbacks(this);
         }
 
+        @Override
         public void run() {
             final int listHeight = getHeight();
             final int firstPos = mFirstPosition;
@@ -4637,9 +4662,6 @@
     /**
      * The amount of friction applied to flings. The default value
      * is {@link ViewConfiguration#getScrollFriction}.
-     *
-     * @return A scalar dimensionless value representing the coefficient of
-     *         friction.
      */
     public void setFriction(float friction) {
         if (mFlingRunnable == null) {
@@ -4806,6 +4828,7 @@
         if (!isHardwareAccelerated()) {
             if (mClearScrollingCache == null) {
                 mClearScrollingCache = new Runnable() {
+                    @Override
                     public void run() {
                         if (mCachingStarted) {
                             mCachingStarted = mCachingActive = false;
@@ -5083,7 +5106,7 @@
         requestLayout();
         invalidate();
     }
-    
+
     /**
      * If there is a selection returns false.
      * Otherwise resurrects the selection and returns true if resurrected.
@@ -5706,6 +5729,7 @@
         return mFiltered;
     }
 
+    @Override
     public void onGlobalLayout() {
         if (isShown()) {
             // Show the popup if we are filtered
@@ -5725,6 +5749,7 @@
      * For our text watcher that is associated with the text filter.  Does
      * nothing.
      */
+    @Override
     public void beforeTextChanged(CharSequence s, int start, int count, int after) {
     }
 
@@ -5733,6 +5758,7 @@
      * the actual filtering as the text changes, and takes care of hiding and
      * showing the popup displaying the currently entered filter text.
      */
+    @Override
     public void onTextChanged(CharSequence s, int start, int before, int count) {
         if (mPopup != null && isTextFilterEnabled()) {
             int length = s.length();
@@ -5763,9 +5789,11 @@
      * For our text watcher that is associated with the text filter.  Does
      * nothing.
      */
+    @Override
     public void afterTextChanged(Editable s) {
     }
 
+    @Override
     public void onFilterComplete(int count) {
         if (mSelectedPosition < 0 && count > 0) {
             mResurrectToPosition = INVALID_POSITION;
@@ -5934,6 +5962,7 @@
      * This defers a notifyDataSetChanged on the pending RemoteViewsAdapter if it has not
      * connected yet.
      */
+    @Override
     public void deferNotifyDataSetChanged() {
         mDeferNotifyDataSetChanged = true;
     }
@@ -5941,6 +5970,7 @@
     /**
      * Called back when the adapter connects to the RemoteViewsService.
      */
+    @Override
     public boolean onRemoteAdapterConnected() {
         if (mRemoteAdapter != mAdapter) {
             setAdapter(mRemoteAdapter);
@@ -5959,6 +5989,7 @@
     /**
      * Called back when the adapter disconnects from the RemoteViewsService.
      */
+    @Override
     public void onRemoteAdapterDisconnected() {
         // If the remote adapter disconnects, we keep it around
         // since the currently displayed items are still cached.
@@ -6041,6 +6072,7 @@
             return mWrapped != null;
         }
 
+        @Override
         public boolean onCreateActionMode(ActionMode mode, Menu menu) {
             if (mWrapped.onCreateActionMode(mode, menu)) {
                 // Initialize checked graphic state?
@@ -6050,14 +6082,17 @@
             return false;
         }
 
+        @Override
         public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
             return mWrapped.onPrepareActionMode(mode, menu);
         }
 
+        @Override
         public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
             return mWrapped.onActionItemClicked(mode, item);
         }
 
+        @Override
         public void onDestroyActionMode(ActionMode mode) {
             mWrapped.onDestroyActionMode(mode);
             mChoiceActionMode = null;
@@ -6072,6 +6107,7 @@
             setLongClickable(true);
         }
 
+        @Override
         public void onItemCheckedStateChanged(ActionMode mode,
                 int position, long id, boolean checked) {
             mWrapped.onItemCheckedStateChanged(mode, position, id, checked);
diff --git a/core/java/android/widget/CalendarView.java b/core/java/android/widget/CalendarView.java
index a19c6a8..6970cde 100644
--- a/core/java/android/widget/CalendarView.java
+++ b/core/java/android/widget/CalendarView.java
@@ -1248,17 +1248,14 @@
      * @param calendar A day in the new focus month.
      */
     private void setMonthDisplayed(Calendar calendar) {
-        final int newMonthDisplayed = calendar.get(Calendar.MONTH);
-        if (mCurrentMonthDisplayed != newMonthDisplayed) {
-            mCurrentMonthDisplayed = newMonthDisplayed;
-            mAdapter.setFocusMonth(mCurrentMonthDisplayed);
-            final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_NO_MONTH_DAY
-                    | DateUtils.FORMAT_SHOW_YEAR;
-            final long millis = calendar.getTimeInMillis();
-            String newMonthName = DateUtils.formatDateRange(mContext, millis, millis, flags);
-            mMonthName.setText(newMonthName);
-            mMonthName.invalidate();
-        }
+        mCurrentMonthDisplayed = calendar.get(Calendar.MONTH);
+        mAdapter.setFocusMonth(mCurrentMonthDisplayed);
+        final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_NO_MONTH_DAY
+                | DateUtils.FORMAT_SHOW_YEAR;
+        final long millis = calendar.getTimeInMillis();
+        String newMonthName = DateUtils.formatDateRange(mContext, millis, millis, flags);
+        mMonthName.setText(newMonthName);
+        mMonthName.invalidate();
     }
 
     /**
diff --git a/core/java/com/android/internal/app/ActionBarImpl.java b/core/java/com/android/internal/app/ActionBarImpl.java
index acbb2b1..e092fff 100644
--- a/core/java/com/android/internal/app/ActionBarImpl.java
+++ b/core/java/com/android/internal/app/ActionBarImpl.java
@@ -1210,6 +1210,10 @@
         mActionView.setIcon(icon);
     }
 
+    public boolean hasIcon() {
+        return mActionView.hasIcon();
+    }
+
     @Override
     public void setLogo(int resId) {
         mActionView.setLogo(resId);
@@ -1220,6 +1224,10 @@
         mActionView.setLogo(logo);
     }
 
+    public boolean hasLogo() {
+        return mActionView.hasLogo();
+    }
+
     public void setDefaultDisplayHomeAsUpEnabled(boolean enable) {
         if (!mDisplayHomeAsUpSet) {
             setDisplayHomeAsUpEnabled(enable);
diff --git a/core/java/com/android/internal/app/MediaRouteChooserDialogFragment.java b/core/java/com/android/internal/app/MediaRouteChooserDialogFragment.java
index cf797bb..e300021 100644
--- a/core/java/com/android/internal/app/MediaRouteChooserDialogFragment.java
+++ b/core/java/com/android/internal/app/MediaRouteChooserDialogFragment.java
@@ -97,7 +97,7 @@
     public void onAttach(Activity activity) {
         super.onAttach(activity);
         mRouter = (MediaRouter) activity.getSystemService(Context.MEDIA_ROUTER_SERVICE);
-        mRouter.addCallback(mRouteTypes, mCallback, MediaRouter.CALLBACK_FLAG_ACTIVE_SCAN);
+        mRouter.addCallback(mRouteTypes, mCallback, MediaRouter.CALLBACK_FLAG_PERFORM_ACTIVE_SCAN);
     }
 
     @Override
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index c22cd26..a674776 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -16,6 +16,7 @@
 
 package com.android.internal.app;
 
+import android.os.AsyncTask;
 import com.android.internal.R;
 import com.android.internal.content.PackageMonitor;
 
@@ -621,9 +622,11 @@
                 view = mInflater.inflate(
                         com.android.internal.R.layout.resolve_list_item, parent, false);
 
+                final ViewHolder holder = new ViewHolder(view);
+                view.setTag(holder);
+
                 // Fix the icon size even if we have different sized resources
-                ImageView icon = (ImageView)view.findViewById(R.id.icon);
-                ViewGroup.LayoutParams lp = (ViewGroup.LayoutParams) icon.getLayoutParams();
+                ViewGroup.LayoutParams lp = holder.icon.getLayoutParams();
                 lp.width = lp.height = mIconSize;
             } else {
                 view = convertView;
@@ -633,20 +636,30 @@
         }
 
         private final void bindView(View view, DisplayResolveInfo info) {
-            TextView text = (TextView)view.findViewById(com.android.internal.R.id.text1);
-            TextView text2 = (TextView)view.findViewById(com.android.internal.R.id.text2);
-            ImageView icon = (ImageView)view.findViewById(R.id.icon);
-            text.setText(info.displayLabel);
+            final ViewHolder holder = (ViewHolder) view.getTag();
+            holder.text.setText(info.displayLabel);
             if (mShowExtended) {
-                text2.setVisibility(View.VISIBLE);
-                text2.setText(info.extendedInfo);
+                holder.text2.setVisibility(View.VISIBLE);
+                holder.text2.setText(info.extendedInfo);
             } else {
-                text2.setVisibility(View.GONE);
+                holder.text2.setVisibility(View.GONE);
             }
             if (info.displayIcon == null) {
-                info.displayIcon = loadIconForResolveInfo(info.ri);
+                new LoadIconTask().execute(info);
             }
-            icon.setImageDrawable(info.displayIcon);
+            holder.icon.setImageDrawable(info.displayIcon);
+        }
+    }
+
+    static class ViewHolder {
+        public TextView text;
+        public TextView text2;
+        public ImageView icon;
+
+        public ViewHolder(View view) {
+            text = (TextView) view.findViewById(com.android.internal.R.id.text1);
+            text2 = (TextView) view.findViewById(com.android.internal.R.id.text2);
+            icon = (ImageView) view.findViewById(R.id.icon);
         }
     }
 
@@ -660,5 +673,21 @@
         }
 
     }
+
+    class LoadIconTask extends AsyncTask<DisplayResolveInfo, Void, DisplayResolveInfo> {
+        @Override
+        protected DisplayResolveInfo doInBackground(DisplayResolveInfo... params) {
+            final DisplayResolveInfo info = params[0];
+            if (info.displayIcon == null) {
+                info.displayIcon = loadIconForResolveInfo(info.ri);
+            }
+            return info;
+        }
+
+        @Override
+        protected void onPostExecute(DisplayResolveInfo info) {
+            mAdapter.notifyDataSetChanged();
+        }
+    }
 }
 
diff --git a/core/java/com/android/internal/view/RotationPolicy.java b/core/java/com/android/internal/view/RotationPolicy.java
index 95130c8..70e2bfc 100644
--- a/core/java/com/android/internal/view/RotationPolicy.java
+++ b/core/java/com/android/internal/view/RotationPolicy.java
@@ -17,12 +17,13 @@
 package com.android.internal.view;
 
 import android.content.Context;
+import android.content.pm.PackageManager;
 import android.database.ContentObserver;
 import android.net.Uri;
 import android.os.AsyncTask;
+import android.os.Build;
 import android.os.Handler;
 import android.os.RemoteException;
-import android.os.ServiceManager;
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.util.Log;
@@ -40,6 +41,21 @@
     }
 
     /**
+     * Gets whether the device supports rotation. In general such a
+     * device has an accelerometer and has the portrait and landscape
+     * features.
+     *
+     * @param context Context for accessing system resources.
+     * @return Whether the device supports rotation.
+     */
+    public static boolean isRotationSupported(Context context) {
+        PackageManager pm = context.getPackageManager();
+        return pm.hasSystemFeature(PackageManager.FEATURE_SENSOR_ACCELEROMETER)
+                && pm.hasSystemFeature(PackageManager.FEATURE_SCREEN_PORTRAIT)
+                && pm.hasSystemFeature(PackageManager.FEATURE_SCREEN_LANDSCAPE);
+    }
+
+    /**
      * Returns true if the device supports the rotation-lock toggle feature
      * in the system UI or system bar.
      *
@@ -48,7 +64,8 @@
      * settings.
      */
     public static boolean isRotationLockToggleSupported(Context context) {
-        return context.getResources().getConfiguration().smallestScreenWidthDp >= 600;
+        return isRotationSupported(context)
+                && context.getResources().getConfiguration().smallestScreenWidthDp >= 600;
     }
 
     /**
diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java
index dda1a10..f2bd522 100644
--- a/core/java/com/android/internal/widget/ActionBarView.java
+++ b/core/java/com/android/internal/widget/ActionBarView.java
@@ -16,24 +16,12 @@
 
 package com.android.internal.widget;
 
-import com.android.internal.R;
-import com.android.internal.view.menu.ActionMenuItem;
-import com.android.internal.view.menu.ActionMenuPresenter;
-import com.android.internal.view.menu.ActionMenuView;
-import com.android.internal.view.menu.MenuBuilder;
-import com.android.internal.view.menu.MenuItemImpl;
-import com.android.internal.view.menu.MenuPresenter;
-import com.android.internal.view.menu.MenuView;
-import com.android.internal.view.menu.SubMenuBuilder;
-
 import android.animation.LayoutTransition;
 import android.app.ActionBar;
 import android.app.ActionBar.OnNavigationListener;
-import android.app.Activity;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.res.Configuration;
 import android.content.res.TypedArray;
 import android.graphics.drawable.Drawable;
@@ -42,7 +30,6 @@
 import android.text.Layout;
 import android.text.TextUtils;
 import android.util.AttributeSet;
-import android.util.Log;
 import android.view.CollapsibleActionView;
 import android.view.Gravity;
 import android.view.LayoutInflater;
@@ -62,6 +49,15 @@
 import android.widget.Spinner;
 import android.widget.SpinnerAdapter;
 import android.widget.TextView;
+import com.android.internal.R;
+import com.android.internal.view.menu.ActionMenuItem;
+import com.android.internal.view.menu.ActionMenuPresenter;
+import com.android.internal.view.menu.ActionMenuView;
+import com.android.internal.view.menu.MenuBuilder;
+import com.android.internal.view.menu.MenuItemImpl;
+import com.android.internal.view.menu.MenuPresenter;
+import com.android.internal.view.menu.MenuView;
+import com.android.internal.view.menu.SubMenuBuilder;
 
 /**
  * @hide
@@ -188,34 +184,8 @@
                 ActionBar.NAVIGATION_MODE_STANDARD);
         mTitle = a.getText(R.styleable.ActionBar_title);
         mSubtitle = a.getText(R.styleable.ActionBar_subtitle);
-
         mLogo = a.getDrawable(R.styleable.ActionBar_logo);
-        if (mLogo == null) {
-            if (context instanceof Activity) {
-                try {
-                    mLogo = pm.getActivityLogo(((Activity) context).getComponentName());
-                } catch (NameNotFoundException e) {
-                    Log.e(TAG, "Activity component name not found!", e);
-                }
-            }
-            if (mLogo == null) {
-                mLogo = appInfo.loadLogo(pm);
-            }
-        }
-
         mIcon = a.getDrawable(R.styleable.ActionBar_icon);
-        if (mIcon == null) {
-            if (context instanceof Activity) {
-                try {
-                    mIcon = pm.getActivityIcon(((Activity) context).getComponentName());
-                } catch (NameNotFoundException e) {
-                    Log.e(TAG, "Activity component name not found!", e);
-                }
-            }
-            if (mIcon == null) {
-                mIcon = appInfo.loadIcon(pm);
-            }
-        }
 
         final LayoutInflater inflater = LayoutInflater.from(context);
 
@@ -729,7 +699,11 @@
     }
 
     public void setIcon(int resId) {
-        setIcon(mContext.getResources().getDrawable(resId));
+        setIcon(resId != 0 ? mContext.getResources().getDrawable(resId) : null);
+    }
+
+    public boolean hasIcon() {
+        return mIcon != null;
     }
 
     public void setLogo(Drawable logo) {
@@ -740,7 +714,11 @@
     }
 
     public void setLogo(int resId) {
-        setLogo(mContext.getResources().getDrawable(resId));
+        setLogo(resId != 0 ? mContext.getResources().getDrawable(resId) : null);
+    }
+
+    public boolean hasLogo() {
+        return mLogo != null;
     }
 
     public void setNavigationMode(int mode) {
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index febccb4..188941b 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -17,6 +17,10 @@
 
 LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
 
+# When built as part of the system image we can enable certian non-NDK compliant
+# Skia optimizations.
+LOCAL_CFLAGS += -DSK_BUILD_FOR_ANDROID_FRAMEWORK
+
 LOCAL_SRC_FILES:= \
 	AndroidRuntime.cpp \
 	Time.cpp \
@@ -159,10 +163,6 @@
 	$(call include-path-for, libhardware)/hardware \
 	$(call include-path-for, libhardware_legacy)/hardware_legacy \
 	$(TOP)/frameworks/av/include \
-	external/skia/include/core \
-	external/skia/include/effects \
-	external/skia/include/images \
-	external/skia/include/ports \
 	external/skia/src/core \
 	external/skia/src/images \
 	external/skia/include/utils \
diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp
index 5454c08..380f061 100644
--- a/core/jni/android/graphics/Paint.cpp
+++ b/core/jni/android/graphics/Paint.cpp
@@ -58,6 +58,10 @@
 static void defaultSettingsForAndroid(SkPaint* paint) {
     // GlyphID encoding is required because we are using Harfbuzz shaping
     paint->setTextEncoding(SkPaint::kGlyphID_TextEncoding);
+
+    SkPaintOptionsAndroid paintOpts = paint->getPaintOptionsAndroid();
+    paintOpts.setUseFontFallbacks(true);
+    paint->setPaintOptionsAndroid(paintOpts);
 }
 
 class SkPaintGlue {
@@ -300,7 +304,10 @@
         ScopedUtfChars localeChars(env, locale);
         char langTag[ULOC_FULLNAME_CAPACITY];
         toLanguageTag(langTag, ULOC_FULLNAME_CAPACITY, localeChars.c_str());
-        obj->setLanguage(SkLanguage(langTag));
+
+        SkPaintOptionsAndroid paintOpts = obj->getPaintOptionsAndroid();
+        paintOpts.setLanguage(langTag);
+        obj->setPaintOptionsAndroid(paintOpts);
     }
 
     static jfloat getTextSize(JNIEnv* env, jobject paint) {
diff --git a/core/jni/android/graphics/TextLayoutCache.cpp b/core/jni/android/graphics/TextLayoutCache.cpp
index cd84fff..73f3639 100644
--- a/core/jni/android/graphics/TextLayoutCache.cpp
+++ b/core/jni/android/graphics/TextLayoutCache.cpp
@@ -218,7 +218,8 @@
  */
 TextLayoutCacheKey::TextLayoutCacheKey(): start(0), count(0), contextCount(0),
         dirFlags(0), typeface(NULL), textSize(0), textSkewX(0), textScaleX(0), flags(0),
-        hinting(SkPaint::kNo_Hinting), variant(SkPaint::kDefault_Variant), language()  {
+        hinting(SkPaint::kNo_Hinting) {
+    paintOpts.setUseFontFallbacks(true);
 }
 
 TextLayoutCacheKey::TextLayoutCacheKey(const SkPaint* paint, const UChar* text,
@@ -232,8 +233,7 @@
     textScaleX = paint->getTextScaleX();
     flags = paint->getFlags();
     hinting = paint->getHinting();
-    variant = paint->getFontVariant();
-    language = paint->getLanguage();
+    paintOpts = paint->getPaintOptionsAndroid();
 }
 
 TextLayoutCacheKey::TextLayoutCacheKey(const TextLayoutCacheKey& other) :
@@ -248,8 +248,7 @@
         textScaleX(other.textScaleX),
         flags(other.flags),
         hinting(other.hinting),
-        variant(other.variant),
-        language(other.language) {
+        paintOpts(other.paintOpts) {
 }
 
 int TextLayoutCacheKey::compare(const TextLayoutCacheKey& lhs, const TextLayoutCacheKey& rhs) {
@@ -283,11 +282,8 @@
     deltaInt = lhs.dirFlags - rhs.dirFlags;
     if (deltaInt) return (deltaInt);
 
-    deltaInt = lhs.variant - rhs.variant;
-    if (deltaInt) return (deltaInt);
-
-    if (lhs.language < rhs.language) return -1;
-    if (lhs.language > rhs.language) return +1;
+    if (lhs.paintOpts != rhs.paintOpts)
+        return memcmp(&lhs.paintOpts, &rhs.paintOpts, sizeof(SkPaintOptionsAndroid));
 
     return memcmp(lhs.getText(), rhs.getText(), lhs.contextCount * sizeof(UChar));
 }
@@ -306,7 +302,7 @@
     hash = JenkinsHashMix(hash, hash_type(textScaleX));
     hash = JenkinsHashMix(hash, flags);
     hash = JenkinsHashMix(hash, hinting);
-    hash = JenkinsHashMix(hash, variant);
+    hash = JenkinsHashMix(hash, paintOpts.getFontVariant());
     // Note: leaving out language is not problematic, as equality comparisons
     // are still valid - the only bad thing that could happen is collisions.
     hash = JenkinsHashMixShorts(hash, getText(), contextCount);
@@ -698,8 +694,7 @@
     mShapingPaint.setTextScaleX(paint->getTextScaleX());
     mShapingPaint.setFlags(paint->getFlags());
     mShapingPaint.setHinting(paint->getHinting());
-    mShapingPaint.setFontVariant(paint->getFontVariant());
-    mShapingPaint.setLanguage(paint->getLanguage());
+    mShapingPaint.setPaintOptionsAndroid(paint->getPaintOptionsAndroid());
 
     // Split the BiDi run into Script runs. Harfbuzz will populate the pos, length and script
     // into the shaperItem
diff --git a/core/jni/android/graphics/TextLayoutCache.h b/core/jni/android/graphics/TextLayoutCache.h
index ab6ac72..54704ec 100644
--- a/core/jni/android/graphics/TextLayoutCache.h
+++ b/core/jni/android/graphics/TextLayoutCache.h
@@ -28,7 +28,6 @@
 #include <utils/Singleton.h>
 
 #include <SkAutoKern.h>
-#include <SkLanguage.h>
 #include <SkPaint.h>
 #include <SkTemplates.h>
 #include <SkTypeface.h>
@@ -104,8 +103,7 @@
     SkScalar textScaleX;
     uint32_t flags;
     SkPaint::Hinting hinting;
-    SkPaint::FontVariant variant;
-    SkLanguage language;
+    SkPaintOptionsAndroid paintOpts;
 
 }; // TextLayoutCacheKey
 
diff --git a/core/jni/android_net_wifi_Wifi.cpp b/core/jni/android_net_wifi_Wifi.cpp
index 9537ac4..08962e2 100644
--- a/core/jni/android_net_wifi_Wifi.cpp
+++ b/core/jni/android_net_wifi_Wifi.cpp
@@ -33,11 +33,11 @@
 
 static jint DBG = false;
 
-static int doCommand(const char *ifname, const char *cmd, char *replybuf, int replybuflen)
+static int doCommand(const char *ifname, char *cmd, char *replybuf, int replybuflen)
 {
     size_t reply_len = replybuflen - 1;
 
-    if (::wifi_command(ifname, cmd, replybuf, &reply_len) != 0)
+    if (::wifi_command(ifname, cmd, BUF_SIZE, replybuf, &reply_len) != 0)
         return -1;
     else {
         // Strip off trailing newline
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 3443d6e..6918099 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2298,8 +2298,7 @@
         <activity android:name="android.accounts.CantAddAccountActivity"
                 android:excludeFromRecents="true"
                 android:exported="true"
-                android:theme="@android:style/Theme.Holo.Dialog"
-                android:label="@string/error_message_title"
+                android:theme="@android:style/Theme.Holo.Dialog.NoActionBar"
                 android:process=":ui">
         </activity>
 
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index c3b1ac5..39915f9 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -1498,7 +1498,8 @@
     <string name="user_switched" msgid="3768006783166984410">"Huidige gebruiker <xliff:g id="NAME">%1$s</xliff:g> ."</string>
     <string name="owner_name" msgid="2716755460376028154">"Eienaar"</string>
     <string name="error_message_title" msgid="4510373083082500195">"Fout"</string>
-    <string name="app_no_restricted_accounts" msgid="4011285085817350390">"Hierdie program werk nie met rekeninge vir beperkte profiele nie"</string>
+    <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+    <skip />
     <string name="app_not_found" msgid="3429141853498927379">"Geen program gevind om hierdie handeling te hanteer nie"</string>
     <string name="revoke" msgid="5404479185228271586">"Herroep"</string>
 </resources>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 12cfbf4..327f1cb 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -1498,7 +1498,8 @@
     <string name="user_switched" msgid="3768006783166984410">"የአሁኑ ተጠቃሚ <xliff:g id="NAME">%1$s</xliff:g>።"</string>
     <string name="owner_name" msgid="2716755460376028154">"ባለቤት"</string>
     <string name="error_message_title" msgid="4510373083082500195">"ስህተት"</string>
-    <string name="app_no_restricted_accounts" msgid="4011285085817350390">"ይህ መተግበሪያ የተገደቡ መገለጫዎች መለያዎችን አይደግፍም"</string>
+    <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+    <skip />
     <string name="app_not_found" msgid="3429141853498927379">"ይህን እርምጃ የሚያከናውን ምንም መተግበሪያ አልተገኘም"</string>
     <string name="revoke" msgid="5404479185228271586">"ሻር"</string>
 </resources>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 50c143b..19f2d6a 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -556,7 +556,7 @@
     <string name="permlab_useCredentials" msgid="235481396163877642">"استخدام الحسابات على الجهاز"</string>
     <string name="permdesc_useCredentials" msgid="7984227147403346422">"للسماح للتطبيق بطلب الرموز المميزة للمصادقة."</string>
     <string name="permlab_accessNetworkState" msgid="4951027964348974773">"عرض اتصالات الشبكة"</string>
-    <string name="permdesc_accessNetworkState" msgid="8318964424675960975">"للمساح للتطبيق بعرض معلومات حول اتصالات الشبكة كعرض معلومات عن الشبكات المتوفرة والشبكات المتصلة."</string>
+    <string name="permdesc_accessNetworkState" msgid="8318964424675960975">"للسماح للتطبيق بعرض معلومات حول اتصالات الشبكة كعرض معلومات عن الشبكات المتوفرة والشبكات المتصلة."</string>
     <string name="permlab_createNetworkSockets" msgid="8018758136404323658">"إمكانية دخول كاملة إلى الشبكة"</string>
     <string name="permdesc_createNetworkSockets" msgid="3403062187779724185">"للسماح للتطبيق بإنشاء مقابس شبكات واستخدام بروتوكولات شبكات مخصصة. ويوفر المتصفح وتطبيقات أخرى طرقًا لإرسال البيانات إلى الإنترنت، ولذلك لا يعد هذا الإذن مطلوبًا لإرسال البيانات إلى الإنترنت."</string>
     <string name="permlab_writeApnSettings" msgid="505660159675751896">"تغيير/اعتراض إعدادات الشبكة وحركة المرور"</string>
@@ -572,8 +572,8 @@
     <string name="permlab_changeWifiState" msgid="6550641188749128035">"التوصيل والفصل من Wi-Fi"</string>
     <string name="permdesc_changeWifiState" msgid="7137950297386127533">"للسماح للتطبيق بالاتصال بنقاط الوصول إلى Wi-Fi وقطع الاتصال بها، وإجراء تغييرات على تهيئة الجهاز لشبكات Wi-Fi."</string>
     <string name="permlab_changeWifiMulticastState" msgid="1368253871483254784">"السماح باستقبال بث Wi-Fi متعدد"</string>
-    <string name="permdesc_changeWifiMulticastState" product="tablet" msgid="7969774021256336548">"للمساح للتطبيق بتلقي الحزم التي يتم إرسالها إلى جميع الأجهزة على شبكة Wi-Fi باستخدام عناوين بث متعدد، وليس باستخدام جهازك اللوحي فقط. ويؤدي ذلك إلى استخدام قدر أكبر من الطاقة يفوق وضع البث غير المتعدد."</string>
-    <string name="permdesc_changeWifiMulticastState" product="default" msgid="6851949706025349926">"للمساح للتطبيق بتلقي الحزم التي يتم إرسالها إلى جميع الأجهزة على شبكة Wi-Fi باستخدام عناوين بث متعدد، وليس باستخدام هاتفك فقط. ويؤدي ذلك إلى استخدام قدر أكبر من الطاقة يفوق وضع البث غير المتعدد."</string>
+    <string name="permdesc_changeWifiMulticastState" product="tablet" msgid="7969774021256336548">"للسماح للتطبيق بتلقي الحزم التي يتم إرسالها إلى جميع الأجهزة على شبكة Wi-Fi باستخدام عناوين بث متعدد، وليس باستخدام جهازك اللوحي فقط. ويؤدي ذلك إلى استخدام قدر أكبر من الطاقة يفوق وضع البث غير المتعدد."</string>
+    <string name="permdesc_changeWifiMulticastState" product="default" msgid="6851949706025349926">"للسماح للتطبيق بتلقي الحزم التي يتم إرسالها إلى جميع الأجهزة على شبكة Wi-Fi باستخدام عناوين بث متعدد، وليس باستخدام هاتفك فقط. ويؤدي ذلك إلى استخدام قدر أكبر من الطاقة يفوق وضع البث غير المتعدد."</string>
     <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"الدخول إلى إعدادات بلوتوث"</string>
     <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"للسماح للتطبيق بتهيئة لوحة البلوتوث المحلي، واكتشاف أجهزة التحكم عن بعد والاقتران بها."</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"للسماح للتطبيق بتهيئة هاتف البلوتوث المحلي، واكتشاف أجهزة التحكم عن بعد والاقتران بها."</string>
@@ -1498,7 +1498,7 @@
     <string name="user_switched" msgid="3768006783166984410">"المستخدم الحالي <xliff:g id="NAME">%1$s</xliff:g>."</string>
     <string name="owner_name" msgid="2716755460376028154">"المالك"</string>
     <string name="error_message_title" msgid="4510373083082500195">"خطأ"</string>
-    <string name="app_no_restricted_accounts" msgid="4011285085817350390">"هذا التطبيق لا يتوافق مع حسابات الملفات الشخصية المقيدة"</string>
+    <string name="app_no_restricted_accounts" msgid="5739463249673727736">"لا يتوافق هذا التطبيق مع حسابات الملفات الشخصية المقيدة"</string>
     <string name="app_not_found" msgid="3429141853498927379">"لم يتم العثور على تطبيق يمكنه التعامل مع هذا الإجراء."</string>
     <string name="revoke" msgid="5404479185228271586">"إلغاء"</string>
 </resources>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 5cb4c43..ab0db23 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -1498,7 +1498,7 @@
     <string name="user_switched" msgid="3768006783166984410">"Бягучы карыстальнік <xliff:g id="NAME">%1$s</xliff:g>."</string>
     <string name="owner_name" msgid="2716755460376028154">"Уладальнік"</string>
     <string name="error_message_title" msgid="4510373083082500195">"Памылка"</string>
-    <string name="app_no_restricted_accounts" msgid="4011285085817350390">"Гэтае прыкладанне не падтрымлівае уліковыя запісы для карыстальнікаў з абмежаваннямi"</string>
+    <string name="app_no_restricted_accounts" msgid="5739463249673727736">"Гэта прыкладанне не падтрымлівае ўліковыя запісы для профiляў з абмежаваннямі"</string>
     <string name="app_not_found" msgid="3429141853498927379">"Прыкладанне для гэтага дзеяння не знойдзенае"</string>
     <string name="revoke" msgid="5404479185228271586">"Ануляваць"</string>
 </resources>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index afa6c11..4d8a5cc 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -1498,7 +1498,8 @@
     <string name="user_switched" msgid="3768006783166984410">"Текущ потребител <xliff:g id="NAME">%1$s</xliff:g>."</string>
     <string name="owner_name" msgid="2716755460376028154">"Собственик"</string>
     <string name="error_message_title" msgid="4510373083082500195">"Грешка"</string>
-    <string name="app_no_restricted_accounts" msgid="4011285085817350390">"Това приложение не поддържа профили за потребителски профили с ограничена функционалност"</string>
+    <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+    <skip />
     <string name="app_not_found" msgid="3429141853498927379">"Няма намерено приложение за извършване на това действие"</string>
     <string name="revoke" msgid="5404479185228271586">"Отмяна"</string>
 </resources>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index aaa911d..4eaf068 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -565,8 +565,8 @@
     <string name="permdesc_changeNetworkState" msgid="6789123912476416214">"Permet que l\'aplicació pugui canviar l\'estat de connectivitat de la xarxa."</string>
     <string name="permlab_changeTetherState" msgid="5952584964373017960">"Canvia la connectivitat d\'ancoratge a xarxa"</string>
     <string name="permdesc_changeTetherState" msgid="1524441344412319780">"Permet que l\'aplicació canviï l\'estat de la connectivitat de la xarxa d\'ancoratge."</string>
-    <string name="permlab_changeBackgroundDataSetting" msgid="1400666012671648741">"canviar la configuració d\'ús de dades de referència"</string>
-    <string name="permdesc_changeBackgroundDataSetting" msgid="5347729578468744379">"Permet que l\'aplicació canviï la configuració d\'ús de les dades de fons."</string>
+    <string name="permlab_changeBackgroundDataSetting" msgid="1400666012671648741">"canviar la configuració d\'ús de dades en segon pla"</string>
+    <string name="permdesc_changeBackgroundDataSetting" msgid="5347729578468744379">"Permet que l\'aplicació canviï la configuració d\'ús de les dades en segon pla."</string>
     <string name="permlab_accessWifiState" msgid="5202012949247040011">"veure connexions Wi-Fi"</string>
     <string name="permdesc_accessWifiState" msgid="5002798077387803726">"Permet que l\'aplicació visualitzi informació sobre les xarxes Wi-Fi, com ara si la Wi-Fi està activada i el nom dels dispositius Wi-Fi connectats."</string>
     <string name="permlab_changeWifiState" msgid="6550641188749128035">"connectar-se a xarxes Wi-Fi i desconnectar-se"</string>
@@ -1406,7 +1406,7 @@
     <string name="data_usage_mobile_limit_snoozed_title" msgid="279240572165412168">"S\'ha superat el límit de dades mòbils"</string>
     <string name="data_usage_wifi_limit_snoozed_title" msgid="8743856006384825974">"S\'ha superat el límit de dades Wi-Fi"</string>
     <string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<xliff:g id="SIZE">%s</xliff:g> per sobre del límit especif."</string>
-    <string name="data_usage_restricted_title" msgid="5965157361036321914">"Dades de referència restringides"</string>
+    <string name="data_usage_restricted_title" msgid="5965157361036321914">"Dades en segon pla restringides"</string>
     <string name="data_usage_restricted_body" msgid="6741521330997452990">"Toca per eliminar la restricció."</string>
     <string name="ssl_certificate" msgid="6510040486049237639">"Certificat de seguretat"</string>
     <string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Aquest certificat és vàlid."</string>
@@ -1498,7 +1498,8 @@
     <string name="user_switched" msgid="3768006783166984410">"Usuari actual: <xliff:g id="NAME">%1$s</xliff:g>."</string>
     <string name="owner_name" msgid="2716755460376028154">"Propietari"</string>
     <string name="error_message_title" msgid="4510373083082500195">"Error"</string>
-    <string name="app_no_restricted_accounts" msgid="4011285085817350390">"L\'aplicació no és compatible amb comptes de perfils restringits."</string>
+    <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+    <skip />
     <string name="app_not_found" msgid="3429141853498927379">"No s\'ha trobat cap aplicació per processar aquesta acció"</string>
     <string name="revoke" msgid="5404479185228271586">"Revoca"</string>
 </resources>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index abe6dad..91498cd 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -1498,7 +1498,8 @@
     <string name="user_switched" msgid="3768006783166984410">"Aktuální uživatel je <xliff:g id="NAME">%1$s</xliff:g>."</string>
     <string name="owner_name" msgid="2716755460376028154">"Vlastník"</string>
     <string name="error_message_title" msgid="4510373083082500195">"Chyba"</string>
-    <string name="app_no_restricted_accounts" msgid="4011285085817350390">"Tato aplikace nepodporuje účty pro omezené profily."</string>
+    <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+    <skip />
     <string name="app_not_found" msgid="3429141853498927379">"Aplikace potřebná k provedení této akce nebyla nalezena"</string>
     <string name="revoke" msgid="5404479185228271586">"Zrušit"</string>
 </resources>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index e00597a..081fd2a 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -1498,7 +1498,8 @@
     <string name="user_switched" msgid="3768006783166984410">"Nuværende bruger <xliff:g id="NAME">%1$s</xliff:g>."</string>
     <string name="owner_name" msgid="2716755460376028154">"Ejer"</string>
     <string name="error_message_title" msgid="4510373083082500195">"Fejl"</string>
-    <string name="app_no_restricted_accounts" msgid="4011285085817350390">"Denne applikation understøtter ikke konti for begrænsede profiler"</string>
+    <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+    <skip />
     <string name="app_not_found" msgid="3429141853498927379">"Der blev ikke fundet nogen applikation, der kan håndtere denne handling"</string>
     <string name="revoke" msgid="5404479185228271586">"Tilbagekald"</string>
 </resources>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 655d5d0..53db449 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -940,7 +940,7 @@
     <string name="oneMonthDurationPast" msgid="7396384508953779925">"Vor 1 Monat"</string>
     <string name="beforeOneMonthDurationPast" msgid="909134546836499826">"Vor mehr als 1 Monat"</string>
   <plurals name="num_seconds_ago">
-    <item quantity="one" msgid="4869870056547896011">"Vor 1 Sekunde"</item>
+    <item quantity="one" msgid="4869870056547896011">"vor 1 Sekunde"</item>
     <item quantity="other" msgid="3903706804349556379">"vor <xliff:g id="COUNT">%d</xliff:g> Sekunden"</item>
   </plurals>
   <plurals name="num_minutes_ago">
@@ -1498,7 +1498,8 @@
     <string name="user_switched" msgid="3768006783166984410">"Aktueller Nutzer <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="owner_name" msgid="2716755460376028154">"Eigentümer"</string>
     <string name="error_message_title" msgid="4510373083082500195">"Fehler"</string>
-    <string name="app_no_restricted_accounts" msgid="4011285085817350390">"Diese App unterstützt keine Konten für eingeschränkte Profile."</string>
+    <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+    <skip />
     <string name="app_not_found" msgid="3429141853498927379">"Für diese Aktion wurde keine App gefunden."</string>
     <string name="revoke" msgid="5404479185228271586">"Aufheben"</string>
 </resources>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 5135847..78a707f 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -1498,7 +1498,8 @@
     <string name="user_switched" msgid="3768006783166984410">"Τρέχων χρήστης <xliff:g id="NAME">%1$s</xliff:g>."</string>
     <string name="owner_name" msgid="2716755460376028154">"Κάτοχος"</string>
     <string name="error_message_title" msgid="4510373083082500195">"Σφάλμα"</string>
-    <string name="app_no_restricted_accounts" msgid="4011285085817350390">"Αυτή η εφαρμογή δεν υποστηρίζει λογαριασμούς για περιορισμένα προφίλ"</string>
+    <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+    <skip />
     <string name="app_not_found" msgid="3429141853498927379">"Δεν υπάρχει εφαρμογή για τη διαχείριση αυτής της ενέργειας"</string>
     <string name="revoke" msgid="5404479185228271586">"Ανάκληση"</string>
 </resources>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 2d5e70c..b8c0d50 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -1498,7 +1498,7 @@
     <string name="user_switched" msgid="3768006783166984410">"Current user <xliff:g id="NAME">%1$s</xliff:g>."</string>
     <string name="owner_name" msgid="2716755460376028154">"Owner"</string>
     <string name="error_message_title" msgid="4510373083082500195">"Error"</string>
-    <string name="app_no_restricted_accounts" msgid="4011285085817350390">"This application does not support accounts for restricted profiles"</string>
+    <string name="app_no_restricted_accounts" msgid="5739463249673727736">"This app doesn\'t support accounts for restricted profiles"</string>
     <string name="app_not_found" msgid="3429141853498927379">"No application found to handle this action"</string>
     <string name="revoke" msgid="5404479185228271586">"Revoke"</string>
 </resources>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 501d56f..49f6e1f 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -1498,7 +1498,8 @@
     <string name="user_switched" msgid="3768006783166984410">"Usuario actual: <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="owner_name" msgid="2716755460376028154">"Propietario"</string>
     <string name="error_message_title" msgid="4510373083082500195">"Error"</string>
-    <string name="app_no_restricted_accounts" msgid="4011285085817350390">"Esta aplicación no admite cuentas de perfiles restringidos."</string>
+    <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+    <skip />
     <string name="app_not_found" msgid="3429141853498927379">"No se encontró una aplicación para manejar esta acción."</string>
     <string name="revoke" msgid="5404479185228271586">"Revocar"</string>
 </resources>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 0685e66..0a704c3 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -1498,7 +1498,8 @@
     <string name="user_switched" msgid="3768006783166984410">"Usuario actual: <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="owner_name" msgid="2716755460376028154">"Propietario"</string>
     <string name="error_message_title" msgid="4510373083082500195">"Error"</string>
-    <string name="app_no_restricted_accounts" msgid="4011285085817350390">"Esta aplicación no admite cuentas de perfiles restringidos"</string>
+    <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+    <skip />
     <string name="app_not_found" msgid="3429141853498927379">"No se ha encontrado ninguna aplicación que pueda realizar esta acción."</string>
     <string name="revoke" msgid="5404479185228271586">"Revocar"</string>
 </resources>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index b1997d1..8f6911c 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -1498,7 +1498,8 @@
     <string name="user_switched" msgid="3768006783166984410">"Praegune kasutaja <xliff:g id="NAME">%1$s</xliff:g>."</string>
     <string name="owner_name" msgid="2716755460376028154">"Omanik"</string>
     <string name="error_message_title" msgid="4510373083082500195">"Viga"</string>
-    <string name="app_no_restricted_accounts" msgid="4011285085817350390">"See rakendus ei toeta piiratud profiilide kontosid"</string>
+    <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+    <skip />
     <string name="app_not_found" msgid="3429141853498927379">"Selle toimingu käsitlemiseks ei leitud ühtegi rakendust"</string>
     <string name="revoke" msgid="5404479185228271586">"Tühista"</string>
 </resources>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index b47bf9f..170e9ae 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -1498,7 +1498,7 @@
     <string name="user_switched" msgid="3768006783166984410">"کاربر کنونی <xliff:g id="NAME">%1$s</xliff:g>."</string>
     <string name="owner_name" msgid="2716755460376028154">"دارنده"</string>
     <string name="error_message_title" msgid="4510373083082500195">"خطا"</string>
-    <string name="app_no_restricted_accounts" msgid="4011285085817350390">"این برنامه از حساب‌های متعلق به نمایه‌های محدود پشتیبانی نمی‌کند"</string>
+    <string name="app_no_restricted_accounts" msgid="5739463249673727736">"این برنامه از حساب‌های متعلق به نمایه‌های محدود پشتیبانی نمی‌کند"</string>
     <string name="app_not_found" msgid="3429141853498927379">"برنامه‌ای برای انجام این عملکرد موجود نیست"</string>
     <string name="revoke" msgid="5404479185228271586">"لغو"</string>
 </resources>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index feeed53..15a5f95 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -1498,7 +1498,8 @@
     <string name="user_switched" msgid="3768006783166984410">"Nykyinen käyttäjä: <xliff:g id="NAME">%1$s</xliff:g>."</string>
     <string name="owner_name" msgid="2716755460376028154">"Omistaja"</string>
     <string name="error_message_title" msgid="4510373083082500195">"Virhe"</string>
-    <string name="app_no_restricted_accounts" msgid="4011285085817350390">"Tämä sovellus ei tue rajoitettujen profiilien tilejä"</string>
+    <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+    <skip />
     <string name="app_not_found" msgid="3429141853498927379">"Tätä toimintoa käsittelevää sovellusta ei löydy"</string>
     <string name="revoke" msgid="5404479185228271586">"Peruuta"</string>
 </resources>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 97e0a82..9afa938 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -1498,7 +1498,8 @@
     <string name="user_switched" msgid="3768006783166984410">"Utilisateur actuel : <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="owner_name" msgid="2716755460376028154">"Propriétaire"</string>
     <string name="error_message_title" msgid="4510373083082500195">"Erreur"</string>
-    <string name="app_no_restricted_accounts" msgid="4011285085817350390">"Les comptes des profils limités ne sont pas acceptés pour cette application."</string>
+    <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+    <skip />
     <string name="app_not_found" msgid="3429141853498927379">"Aucune application trouvée pour gérer cette action."</string>
     <string name="revoke" msgid="5404479185228271586">"Révoquer"</string>
 </resources>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index b135c2e..4df3a5b 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -1498,7 +1498,8 @@
     <string name="user_switched" msgid="3768006783166984410">"वर्तमान उपयोगकर्ता <xliff:g id="NAME">%1$s</xliff:g>."</string>
     <string name="owner_name" msgid="2716755460376028154">"स्वामी"</string>
     <string name="error_message_title" msgid="4510373083082500195">"त्रुटि"</string>
-    <string name="app_no_restricted_accounts" msgid="4011285085817350390">"यह एप्लिकेशन प्रतिबंधित प्रोफ़ाइल के खातों का समर्थन नहीं करता है"</string>
+    <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+    <skip />
     <string name="app_not_found" msgid="3429141853498927379">"इस कार्यवाही को प्रबंधित करने के लिए कोई एप्लिकेशन नहीं मिला"</string>
     <string name="revoke" msgid="5404479185228271586">"निरस्‍त करें"</string>
 </resources>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index f033a16..a7208ee 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -1498,7 +1498,8 @@
     <string name="user_switched" msgid="3768006783166984410">"Trenutačni korisnik <xliff:g id="NAME">%1$s</xliff:g>."</string>
     <string name="owner_name" msgid="2716755460376028154">"Vlasnik"</string>
     <string name="error_message_title" msgid="4510373083082500195">"Pogreška"</string>
-    <string name="app_no_restricted_accounts" msgid="4011285085817350390">"Aplikacija ne podržava račune za ograničene profile"</string>
+    <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+    <skip />
     <string name="app_not_found" msgid="3429141853498927379">"Nije pronađena aplikacija za upravljanje ovom radnjom"</string>
     <string name="revoke" msgid="5404479185228271586">"Opozovi"</string>
 </resources>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 516241f..3060fd1 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -1498,7 +1498,8 @@
     <string name="user_switched" msgid="3768006783166984410">"<xliff:g id="NAME">%1$s</xliff:g> az aktuális felhasználó."</string>
     <string name="owner_name" msgid="2716755460376028154">"Tulajdonos"</string>
     <string name="error_message_title" msgid="4510373083082500195">"Hiba"</string>
-    <string name="app_no_restricted_accounts" msgid="4011285085817350390">"Ez az alkalmazás nem támogatja a korlátozott profilokkal rendelkező fiókokat"</string>
+    <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+    <skip />
     <string name="app_not_found" msgid="3429141853498927379">"Nincs megfelelő alkalmazás a művelet elvégzésére."</string>
     <string name="revoke" msgid="5404479185228271586">"Visszavonás"</string>
 </resources>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 812d016..5504078 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -1498,7 +1498,8 @@
     <string name="user_switched" msgid="3768006783166984410">"Pengguna saat ini <xliff:g id="NAME">%1$s</xliff:g>."</string>
     <string name="owner_name" msgid="2716755460376028154">"Pemilik"</string>
     <string name="error_message_title" msgid="4510373083082500195">"Kesalahan"</string>
-    <string name="app_no_restricted_accounts" msgid="4011285085817350390">"Aplikasi ini tidak mendukung akun untuk profil yang dibatasi"</string>
+    <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+    <skip />
     <string name="app_not_found" msgid="3429141853498927379">"Tidak ada aplikasi yang ditemukan untuk menangani tindakan ini"</string>
     <string name="revoke" msgid="5404479185228271586">"Cabut"</string>
 </resources>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 05bed06..a1e8bfc 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -1498,7 +1498,8 @@
     <string name="user_switched" msgid="3768006783166984410">"Utente corrente <xliff:g id="NAME">%1$s</xliff:g>."</string>
     <string name="owner_name" msgid="2716755460376028154">"Proprietario"</string>
     <string name="error_message_title" msgid="4510373083082500195">"Errore"</string>
-    <string name="app_no_restricted_accounts" msgid="4011285085817350390">"Questa applicazione non supporta account relativi a profili con limitazioni"</string>
+    <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+    <skip />
     <string name="app_not_found" msgid="3429141853498927379">"Nessuna applicazione trovata in grado di gestire questa azione"</string>
     <string name="revoke" msgid="5404479185228271586">"Revoca"</string>
 </resources>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 1e0e204..d48f846 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -1498,7 +1498,8 @@
     <string name="user_switched" msgid="3768006783166984410">"המשתמש הנוכחי <xliff:g id="NAME">%1$s</xliff:g>."</string>
     <string name="owner_name" msgid="2716755460376028154">"בעלים"</string>
     <string name="error_message_title" msgid="4510373083082500195">"שגיאה"</string>
-    <string name="app_no_restricted_accounts" msgid="4011285085817350390">"היישום הזה לא תומך בחשבונות עבור פרופילים מוגבלים"</string>
+    <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+    <skip />
     <string name="app_not_found" msgid="3429141853498927379">"לא נמצא יישום שתומך בפעולה זו"</string>
     <string name="revoke" msgid="5404479185228271586">"בטל"</string>
 </resources>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 3241159..9932924 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -1498,7 +1498,8 @@
     <string name="user_switched" msgid="3768006783166984410">"現在のユーザーは<xliff:g id="NAME">%1$s</xliff:g>です。"</string>
     <string name="owner_name" msgid="2716755460376028154">"所有者"</string>
     <string name="error_message_title" msgid="4510373083082500195">"エラー"</string>
-    <string name="app_no_restricted_accounts" msgid="4011285085817350390">"このアプリでは制限付きプロフィールのアカウントはサポートしていません"</string>
+    <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+    <skip />
     <string name="app_not_found" msgid="3429141853498927379">"この操作を行うアプリが見つかりません"</string>
     <string name="revoke" msgid="5404479185228271586">"取り消し"</string>
 </resources>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index b6e07c8..f66fb33 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -1498,7 +1498,8 @@
     <string name="user_switched" msgid="3768006783166984410">"현재 사용자는 <xliff:g id="NAME">%1$s</xliff:g>님입니다."</string>
     <string name="owner_name" msgid="2716755460376028154">"소유자"</string>
     <string name="error_message_title" msgid="4510373083082500195">"오류"</string>
-    <string name="app_no_restricted_accounts" msgid="4011285085817350390">"이 애플리케이션은 제한된 프로필의 계정을 지원하지 않습니다."</string>
+    <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+    <skip />
     <string name="app_not_found" msgid="3429141853498927379">"이 작업을 처리하는 애플리케이션을 찾을 수 없습니다."</string>
     <string name="revoke" msgid="5404479185228271586">"취소"</string>
 </resources>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 2ad0598..d4019f3 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -1498,7 +1498,8 @@
     <string name="user_switched" msgid="3768006783166984410">"Dabartinis naudotojas: <xliff:g id="NAME">%1$s</xliff:g>."</string>
     <string name="owner_name" msgid="2716755460376028154">"Savininkas"</string>
     <string name="error_message_title" msgid="4510373083082500195">"Klaida"</string>
-    <string name="app_no_restricted_accounts" msgid="4011285085817350390">"Ši programa nepalaiko apribotų profilių paskyrų"</string>
+    <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+    <skip />
     <string name="app_not_found" msgid="3429141853498927379">"Nerasta programa šiam veiksmui apdoroti"</string>
     <string name="revoke" msgid="5404479185228271586">"Anuliuoti"</string>
 </resources>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index de30037..dac8a7b 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -1498,7 +1498,8 @@
     <string name="user_switched" msgid="3768006783166984410">"Pašreizējais lietotājs: <xliff:g id="NAME">%1$s</xliff:g>."</string>
     <string name="owner_name" msgid="2716755460376028154">"Īpašnieks"</string>
     <string name="error_message_title" msgid="4510373083082500195">"Kļūda"</string>
-    <string name="app_no_restricted_accounts" msgid="4011285085817350390">"Šajā lietojumprogrammā netiek atbalstīti ierobežotu profilu konti."</string>
+    <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+    <skip />
     <string name="app_not_found" msgid="3429141853498927379">"Netika atrasta neviena lietojumprogramma, kas var veikt šo darbību."</string>
     <string name="revoke" msgid="5404479185228271586">"Atsaukt"</string>
 </resources>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index b518ea9..bcc9493 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -1498,7 +1498,8 @@
     <string name="user_switched" msgid="3768006783166984410">"Pengguna semasa <xliff:g id="NAME">%1$s</xliff:g>."</string>
     <string name="owner_name" msgid="2716755460376028154">"Pemilik"</string>
     <string name="error_message_title" msgid="4510373083082500195">"Ralat"</string>
-    <string name="app_no_restricted_accounts" msgid="4011285085817350390">"Apl ini tidak menyokong akaun untuk profil yang disekat"</string>
+    <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+    <skip />
     <string name="app_not_found" msgid="3429141853498927379">"Tidak menemui aplikasi untuk mengendalikan tindakan ini"</string>
     <string name="revoke" msgid="5404479185228271586">"Batalkan"</string>
 </resources>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 080a05c..5993cc9 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -1498,7 +1498,8 @@
     <string name="user_switched" msgid="3768006783166984410">"Gjeldende bruker: <xliff:g id="NAME">%1$s</xliff:g>."</string>
     <string name="owner_name" msgid="2716755460376028154">"Eier"</string>
     <string name="error_message_title" msgid="4510373083082500195">"Feil"</string>
-    <string name="app_no_restricted_accounts" msgid="4011285085817350390">"Denne appen støtter ikke kontoer for begrensede profiler"</string>
+    <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+    <skip />
     <string name="app_not_found" msgid="3429141853498927379">"Finner ingen apper som kan utføre denne handlingen"</string>
     <string name="revoke" msgid="5404479185228271586">"Opphev"</string>
 </resources>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 299658e..b8e5deb 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -1498,7 +1498,8 @@
     <string name="user_switched" msgid="3768006783166984410">"Huidige gebruiker <xliff:g id="NAME">%1$s</xliff:g>."</string>
     <string name="owner_name" msgid="2716755460376028154">"Eigenaar"</string>
     <string name="error_message_title" msgid="4510373083082500195">"Fout"</string>
-    <string name="app_no_restricted_accounts" msgid="4011285085817350390">"Deze app biedt geen ondersteuning voor accounts voor beperkte profielen"</string>
+    <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+    <skip />
     <string name="app_not_found" msgid="3429141853498927379">"Er is geen app gevonden om deze actie uit te voeren"</string>
     <string name="revoke" msgid="5404479185228271586">"Intrekken"</string>
 </resources>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index babfe61..642237c 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -52,9 +52,9 @@
     <string name="needPuk2" msgid="4526033371987193070">"Wprowadź kod PUK2, aby odblokować kartę SIM."</string>
     <string name="imei" msgid="2625429890869005782">"IMEI"</string>
     <string name="meid" msgid="4841221237681254195">"MEID"</string>
-    <string name="ClipMmi" msgid="6952821216480289285">"Identyfikator rozmówcy przy połączeniach przychodzących"</string>
-    <string name="ClirMmi" msgid="7784673673446833091">"Identyfikator rozmówcy przy połączeniach wychodzących"</string>
-    <string name="CfMmi" msgid="5123218989141573515">"Przekazywanie połączeń"</string>
+    <string name="ClipMmi" msgid="6952821216480289285">"Nazwa rozmówcy przy połączeniach przychodzących"</string>
+    <string name="ClirMmi" msgid="7784673673446833091">"Nazwa rozmówcy przy połączeniach wychodzących"</string>
+    <string name="CfMmi" msgid="5123218989141573515">"Przekierowanie połączeń"</string>
     <string name="CwMmi" msgid="9129678056795016867">"Połączenia oczekujące"</string>
     <string name="BaMmi" msgid="455193067926770581">"Blokada dzwonienia"</string>
     <string name="PwdMmi" msgid="7043715687905254199">"Zmiana hasła"</string>
@@ -65,10 +65,10 @@
     <string name="RuacMmi" msgid="7827887459138308886">"Odrzucanie niepożądanych, irytujących połączeń"</string>
     <string name="CndMmi" msgid="3116446237081575808">"Dostarczanie numeru telefonującego"</string>
     <string name="DndMmi" msgid="1265478932418334331">"Nie przeszkadzać"</string>
-    <string name="CLIRDefaultOnNextCallOn" msgid="429415409145781923">"Identyfikator rozmówcy ustawiony jest domyślnie na „zastrzeżony”. Następne połączenie: zastrzeżony"</string>
-    <string name="CLIRDefaultOnNextCallOff" msgid="3092918006077864624">"Identyfikator rozmówcy ustawiony jest domyślnie na „zastrzeżony”. Następne połączenie: nie zastrzeżony"</string>
-    <string name="CLIRDefaultOffNextCallOn" msgid="6179425182856418465">"Identyfikator rozmówcy ustawiony jest domyślnie na „nie zastrzeżony”. Następne połączenie: zastrzeżony"</string>
-    <string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"Identyfikator rozmówcy ustawiony jest domyślnie na „nie zastrzeżony”. Następne połączenie: nie zastrzeżony"</string>
+    <string name="CLIRDefaultOnNextCallOn" msgid="429415409145781923">"Nazwa rozmówcy ustawiona jest domyślnie na „zastrzeżony”. Następne połączenie: zastrzeżony"</string>
+    <string name="CLIRDefaultOnNextCallOff" msgid="3092918006077864624">"Nazwa rozmówcy ustawiona jest domyślnie na „zastrzeżony”. Następne połączenie: nie zastrzeżony"</string>
+    <string name="CLIRDefaultOffNextCallOn" msgid="6179425182856418465">"Nazwa rozmówcy ustawiona jest domyślnie na „nie zastrzeżony”. Następne połączenie: zastrzeżony"</string>
+    <string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"Nazwa rozmówcy ustawiona jest domyślnie na „nie zastrzeżony”. Następne połączenie: nie zastrzeżony"</string>
     <string name="serviceNotProvisioned" msgid="8614830180508686666">"Usługa nie jest świadczona."</string>
     <string name="CLIRPermanent" msgid="3377371145926835671">"Nie możesz zmienić ustawienia identyfikatora rozmówcy."</string>
     <string name="RestrictedChangedTitle" msgid="5592189398956187498">"Zmieniono ograniczenie dostępu"</string>
@@ -1498,7 +1498,8 @@
     <string name="user_switched" msgid="3768006783166984410">"Bieżący użytkownik: <xliff:g id="NAME">%1$s</xliff:g>."</string>
     <string name="owner_name" msgid="2716755460376028154">"Właściciel"</string>
     <string name="error_message_title" msgid="4510373083082500195">"Błąd"</string>
-    <string name="app_no_restricted_accounts" msgid="4011285085817350390">"Ta aplikacja nie obsługuje kont w przypadku profili z ograniczeniami"</string>
+    <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+    <skip />
     <string name="app_not_found" msgid="3429141853498927379">"Nie znaleziono aplikacji do obsługi tej akcji"</string>
     <string name="revoke" msgid="5404479185228271586">"Cofnij"</string>
 </resources>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 6d76248..ff912b9 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -1498,7 +1498,8 @@
     <string name="user_switched" msgid="3768006783166984410">"<xliff:g id="NAME">%1$s</xliff:g> do utilizador atual."</string>
     <string name="owner_name" msgid="2716755460376028154">"Proprietário"</string>
     <string name="error_message_title" msgid="4510373083082500195">"Erro"</string>
-    <string name="app_no_restricted_accounts" msgid="4011285085817350390">"Esta aplicação não suporta contas de perfis restritos"</string>
+    <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+    <skip />
     <string name="app_not_found" msgid="3429141853498927379">"Não foram encontradas aplicações para executar esta ação"</string>
     <string name="revoke" msgid="5404479185228271586">"Revogar"</string>
 </resources>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 252fc27..9698884 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -205,7 +205,7 @@
     <string name="permgrouplab_appInfo" msgid="8028789762634147725">"Informações sobre seus aplicativos"</string>
     <string name="permgroupdesc_appInfo" msgid="3950378538049625907">"Capacidade de afetar o comportamento de outros aplicativos no dispositivo."</string>
     <string name="permgrouplab_wallpaper" msgid="3850280158041175998">"Plano de fundo"</string>
-    <string name="permgroupdesc_wallpaper" msgid="5630417854750540154">"Alterar as configurações de papel de parede do dispositivo."</string>
+    <string name="permgroupdesc_wallpaper" msgid="5630417854750540154">"Alterar as configurações de plano de fundo do dispositivo."</string>
     <string name="permgrouplab_systemClock" msgid="406535759236612992">"Relógio"</string>
     <string name="permgroupdesc_systemClock" msgid="3944359833624094992">"Alterar a hora ou fuso horário no dispositivo."</string>
     <string name="permgrouplab_statusBar" msgid="2095862568113945398">"Barra de status"</string>
@@ -533,7 +533,7 @@
     <string name="permdesc_factoryTest" product="tablet" msgid="3952059318359653091">"Executa como um teste do fabricante de nível inferior, permitindo o acesso completo ao hardware do tablet. Disponível apenas quando um tablet está em execução no modo de teste do fabricante."</string>
     <string name="permdesc_factoryTest" product="default" msgid="8136644990319244802">"Executa como um teste do fabricante de nível inferior, permitindo o acesso completo ao hardware do telefone. Disponível apenas quando um telefone está em execução no modo de teste do fabricante."</string>
     <string name="permlab_setWallpaper" msgid="6627192333373465143">"definir plano de fundo"</string>
-    <string name="permdesc_setWallpaper" msgid="7373447920977624745">"Permite que o aplicativo defina o papel de parede do sistema."</string>
+    <string name="permdesc_setWallpaper" msgid="7373447920977624745">"Permite que o aplicativo defina o plano de fundo do sistema."</string>
     <string name="permlab_setWallpaperHints" msgid="3278608165977736538">"ajustar tamanho do plano de fundo"</string>
     <string name="permdesc_setWallpaperHints" msgid="8235784384223730091">"Permite que o aplicativo defina as dicas de tamanho do plano de fundo do sistema."</string>
     <string name="permlab_masterClear" msgid="2315750423139697397">"redefinir o sistema para os padrões de fábrica"</string>
@@ -1498,7 +1498,8 @@
     <string name="user_switched" msgid="3768006783166984410">"Usuário atual <xliff:g id="NAME">%1$s</xliff:g>."</string>
     <string name="owner_name" msgid="2716755460376028154">"Proprietário"</string>
     <string name="error_message_title" msgid="4510373083082500195">"Erro"</string>
-    <string name="app_no_restricted_accounts" msgid="4011285085817350390">"Este aplicativo não suporta contas para perfis restritos"</string>
+    <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+    <skip />
     <string name="app_not_found" msgid="3429141853498927379">"Nenhum aplicativo encontrado para executar a ação"</string>
     <string name="revoke" msgid="5404479185228271586">"Revogar"</string>
 </resources>
diff --git a/core/res/res/values-rm/strings.xml b/core/res/res/values-rm/strings.xml
index 4404d875..b2a0bca 100644
--- a/core/res/res/values-rm/strings.xml
+++ b/core/res/res/values-rm/strings.xml
@@ -2435,7 +2435,7 @@
     <skip />
     <!-- no translation found for error_message_title (4510373083082500195) -->
     <skip />
-    <!-- no translation found for app_no_restricted_accounts (4011285085817350390) -->
+    <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
     <skip />
     <!-- no translation found for app_not_found (3429141853498927379) -->
     <skip />
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 4267fe1..b7866f6 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -1498,7 +1498,8 @@
     <string name="user_switched" msgid="3768006783166984410">"Utilizator curent: <xliff:g id="NAME">%1$s</xliff:g>."</string>
     <string name="owner_name" msgid="2716755460376028154">"Proprietar"</string>
     <string name="error_message_title" msgid="4510373083082500195">"Eroare"</string>
-    <string name="app_no_restricted_accounts" msgid="4011285085817350390">"Această aplicație nu acceptă conturi pentru profilurile cu permisiuni limitate"</string>
+    <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+    <skip />
     <string name="app_not_found" msgid="3429141853498927379">"Nicio aplicație pentru gestionarea acestei acțiuni"</string>
     <string name="revoke" msgid="5404479185228271586">"Revocați"</string>
 </resources>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index b05bef7..3b8b907 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -1498,7 +1498,8 @@
     <string name="user_switched" msgid="3768006783166984410">"Выбран аккаунт пользователя <xliff:g id="NAME">%1$s</xliff:g>."</string>
     <string name="owner_name" msgid="2716755460376028154">"Владелец"</string>
     <string name="error_message_title" msgid="4510373083082500195">"Ошибка"</string>
-    <string name="app_no_restricted_accounts" msgid="4011285085817350390">"Это приложение не поддерживается в аккаунтах для профилей с ограниченным доступом"</string>
+    <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+    <skip />
     <string name="app_not_found" msgid="3429141853498927379">"Невозможно обработать это действие"</string>
     <string name="revoke" msgid="5404479185228271586">"Отменить"</string>
 </resources>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 96b44f7..2d62a47 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -1498,7 +1498,7 @@
     <string name="user_switched" msgid="3768006783166984410">"Aktuálny používateľ je <xliff:g id="NAME">%1$s</xliff:g>."</string>
     <string name="owner_name" msgid="2716755460376028154">"Vlastník"</string>
     <string name="error_message_title" msgid="4510373083082500195">"Chyba"</string>
-    <string name="app_no_restricted_accounts" msgid="4011285085817350390">"Táto aplikácia nepodporuje účty pre profily s obmedzením"</string>
+    <string name="app_no_restricted_accounts" msgid="5739463249673727736">"Táto aplikácia nepodporuje účty pre profily s obmedzením"</string>
     <string name="app_not_found" msgid="3429141853498927379">"Aplikácia potrebná na spracovanie tejto akcie sa nenašla"</string>
     <string name="revoke" msgid="5404479185228271586">"Odvolať"</string>
 </resources>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 5280b06..fd0b91f 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -1498,7 +1498,8 @@
     <string name="user_switched" msgid="3768006783166984410">"Trenutni uporabnik <xliff:g id="NAME">%1$s</xliff:g>."</string>
     <string name="owner_name" msgid="2716755460376028154">"Lastnik"</string>
     <string name="error_message_title" msgid="4510373083082500195">"Napaka"</string>
-    <string name="app_no_restricted_accounts" msgid="4011285085817350390">"Ta aplikacija ne podpira računov za profile z omejitvami"</string>
+    <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+    <skip />
     <string name="app_not_found" msgid="3429141853498927379">"Najdena ni bila nobena aplikacija za izvedbo tega dejanja"</string>
     <string name="revoke" msgid="5404479185228271586">"Prekliči"</string>
 </resources>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 79a3d87..742375f 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -1498,7 +1498,8 @@
     <string name="user_switched" msgid="3768006783166984410">"Актуелни корисник <xliff:g id="NAME">%1$s</xliff:g>."</string>
     <string name="owner_name" msgid="2716755460376028154">"Власник"</string>
     <string name="error_message_title" msgid="4510373083082500195">"Грешка"</string>
-    <string name="app_no_restricted_accounts" msgid="4011285085817350390">"Ова апликација не подржава налоге за ограничене профиле"</string>
+    <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+    <skip />
     <string name="app_not_found" msgid="3429141853498927379">"Није пронађена ниједна апликација која би могла да обави ову радњу"</string>
     <string name="revoke" msgid="5404479185228271586">"Опозови"</string>
 </resources>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 0775d0a..1a316bd 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -1498,7 +1498,8 @@
     <string name="user_switched" msgid="3768006783166984410">"Nuvarande användare: <xliff:g id="NAME">%1$s</xliff:g>."</string>
     <string name="owner_name" msgid="2716755460376028154">"Ägare"</string>
     <string name="error_message_title" msgid="4510373083082500195">"Fel"</string>
-    <string name="app_no_restricted_accounts" msgid="4011285085817350390">"Den här appen stöder inte konton för begränsade profiler"</string>
+    <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+    <skip />
     <string name="app_not_found" msgid="3429141853498927379">"Ingen app som kan hantera åtgärden hittades"</string>
     <string name="revoke" msgid="5404479185228271586">"Återkalla"</string>
 </resources>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 450e6a3..bf03bdc 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -1498,7 +1498,8 @@
     <string name="user_switched" msgid="3768006783166984410">"Mtumiaji wa sasa <xliff:g id="NAME">%1$s</xliff:g>."</string>
     <string name="owner_name" msgid="2716755460376028154">"Mmiliki"</string>
     <string name="error_message_title" msgid="4510373083082500195">"Hitilafu"</string>
-    <string name="app_no_restricted_accounts" msgid="4011285085817350390">"Programu hii haiwezi kutumiwa na akaunti za wasifu zilizowekewa vikwazo"</string>
+    <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+    <skip />
     <string name="app_not_found" msgid="3429141853498927379">"Hakuna programu iliyopatikana ili kushughulikia kitendo hiki"</string>
     <string name="revoke" msgid="5404479185228271586">"Batilisha"</string>
 </resources>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index fd3ab94..f917448 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -1498,7 +1498,7 @@
     <string name="user_switched" msgid="3768006783166984410">"ผู้ใช้ปัจจุบัน <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="owner_name" msgid="2716755460376028154">"เจ้าของ"</string>
     <string name="error_message_title" msgid="4510373083082500195">"ข้อผิดพลาด"</string>
-    <string name="app_no_restricted_accounts" msgid="4011285085817350390">"แอปพลิเคชันนี้ไม่สนับสนุนบัญชีที่มีโปรไฟล์ที่ถูกจำกัด"</string>
+    <string name="app_no_restricted_accounts" msgid="5739463249673727736">"แอปนี้ไม่สนับสนุนบัญชีที่มีโปรไฟล์ที่ถูกจำกัด"</string>
     <string name="app_not_found" msgid="3429141853498927379">"ไม่พบแอปพลิเคชันสำหรับการทำงานนี้"</string>
     <string name="revoke" msgid="5404479185228271586">"เพิกถอน"</string>
 </resources>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index ce46219..53aaa0e 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -1498,7 +1498,8 @@
     <string name="user_switched" msgid="3768006783166984410">"Kasalukuyang user <xliff:g id="NAME">%1$s</xliff:g>."</string>
     <string name="owner_name" msgid="2716755460376028154">"May-ari"</string>
     <string name="error_message_title" msgid="4510373083082500195">"Error"</string>
-    <string name="app_no_restricted_accounts" msgid="4011285085817350390">"Hindi sinusuportahan ng application na ito ang mga account para sa mga pinaghihigpitang profile"</string>
+    <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+    <skip />
     <string name="app_not_found" msgid="3429141853498927379">"Walang nakitang application na mangangasiwa sa pagkilos na ito"</string>
     <string name="revoke" msgid="5404479185228271586">"Bawiin"</string>
 </resources>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index c6e8519..1c25ab7 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -1498,7 +1498,8 @@
     <string name="user_switched" msgid="3768006783166984410">"Geçerli kullanıcı: <xliff:g id="NAME">%1$s</xliff:g>."</string>
     <string name="owner_name" msgid="2716755460376028154">"Sahibi"</string>
     <string name="error_message_title" msgid="4510373083082500195">"Hata"</string>
-    <string name="app_no_restricted_accounts" msgid="4011285085817350390">"Bu uygulama kısıtlanmış profillerin hesaplarını desteklemez"</string>
+    <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+    <skip />
     <string name="app_not_found" msgid="3429141853498927379">"Bu eylemi gerçekleştirecek bir uygulama bulunamadı"</string>
     <string name="revoke" msgid="5404479185228271586">"İptal et"</string>
 </resources>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 216a9b1..9070582 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -1498,7 +1498,8 @@
     <string name="user_switched" msgid="3768006783166984410">"Поточний користувач: <xliff:g id="NAME">%1$s</xliff:g>."</string>
     <string name="owner_name" msgid="2716755460376028154">"Власник"</string>
     <string name="error_message_title" msgid="4510373083082500195">"Помилка"</string>
-    <string name="app_no_restricted_accounts" msgid="4011285085817350390">"Ця програма не підтримує облікові записи для обмежених профілів"</string>
+    <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+    <skip />
     <string name="app_not_found" msgid="3429141853498927379">"Не знайдено програму для обробки цієї дії"</string>
     <string name="revoke" msgid="5404479185228271586">"Анулювати"</string>
 </resources>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 7f076b9..5d4f0a7 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -1498,7 +1498,8 @@
     <string name="user_switched" msgid="3768006783166984410">"Người dùng hiện tại <xliff:g id="NAME">%1$s</xliff:g>."</string>
     <string name="owner_name" msgid="2716755460376028154">"Chủ sở hữu"</string>
     <string name="error_message_title" msgid="4510373083082500195">"Lỗi"</string>
-    <string name="app_no_restricted_accounts" msgid="4011285085817350390">"Ứng dụng này không hỗ trợ tài khoản cho các tiểu sử bị hạn chế"</string>
+    <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+    <skip />
     <string name="app_not_found" msgid="3429141853498927379">"Không tìm thấy ứng dụng nào để xử lý tác vụ này"</string>
     <string name="revoke" msgid="5404479185228271586">"Thu hồi"</string>
 </resources>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 2e93751..9878860 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -451,17 +451,17 @@
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"允许安装位置信息提供程序"</string>
     <string name="permdesc_installLocationProvider" msgid="9066146120470591509">"创建用于测试的模拟位置源或安装新的位置提供程序。此权限可让该应用覆盖由其他位置源(如 GPS)或位置提供程序返回的位置和/或状态信息。"</string>
     <string name="permlab_accessFineLocation" msgid="1191898061965273372">"精确位置(基于 GPS 和网络)"</string>
-    <string name="permdesc_accessFineLocation" msgid="5295047563564981250">"允许该应用通过全球定位系统 (GPS) 或网络位置信息源(例如基站和 Wi-Fi)获取您的精确位置信息。您必须在设备上开启这些位置服务,应用才能获得位置信息。应用会使用此类服务确定您的位置,这可能会消耗更多电量。"</string>
+    <string name="permdesc_accessFineLocation" msgid="5295047563564981250">"允许该应用通过全球定位系统 (GPS) 或网络位置信息源(例如基站和 WLAN)获取您的精确位置信息。您必须在设备上开启这些位置服务,应用才能获得位置信息。应用会使用此类服务确定您的位置,这可能会消耗更多电量。"</string>
     <string name="permlab_accessCoarseLocation" msgid="4887895362354239628">"大致位置(基于网络)"</string>
-    <string name="permdesc_accessCoarseLocation" msgid="2538200184373302295">"允许该应用获取您的大致位置信息。这类位置信息来自于使用网络位置信息源(例如基站和 Wi-Fi)的位置服务。您必须在设备上开启这些位置服务,应用才能获得位置信息。应用会使用此类服务确定您的大概位置。"</string>
+    <string name="permdesc_accessCoarseLocation" msgid="2538200184373302295">"允许该应用获取您的大致位置信息。这类位置信息来自于使用网络位置信息源(例如基站和 WLAN)的位置服务。您必须在设备上开启这些位置服务,应用才能获得位置信息。应用会使用此类服务确定您的大概位置。"</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"访问 SurfaceFlinger"</string>
     <string name="permdesc_accessSurfaceFlinger" msgid="1041619516733293551">"允许应用使用 SurfaceFlinger 低级功能。"</string>
     <string name="permlab_readFrameBuffer" msgid="6690504248178498136">"读取帧缓冲区"</string>
     <string name="permdesc_readFrameBuffer" msgid="4937405521809454680">"允许应用读取帧缓冲区的内容。"</string>
-    <string name="permlab_configureWifiDisplay" msgid="5595661694746742168">"配置 Wi-Fi 显示设备"</string>
-    <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"允许应用配置并连接到 Wi-Fi 显示设备。"</string>
-    <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"控制 Wi-Fi 显示设备"</string>
-    <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"允许应用控制 Wi-Fi 显示设备的基础功能。"</string>
+    <string name="permlab_configureWifiDisplay" msgid="5595661694746742168">"配置 WLAN 显示设备"</string>
+    <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"允许应用配置并连接到 WLAN 显示设备。"</string>
+    <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"控制 WLAN 显示设备"</string>
+    <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"允许应用控制 WLAN 显示设备的基础功能。"</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"更改您的音频设置"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"允许该应用修改全局音频设置,例如音量和用于输出的扬声器。"</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"录音"</string>
@@ -567,13 +567,13 @@
     <string name="permdesc_changeTetherState" msgid="1524441344412319780">"允许应用更改绑定网络连接的状态。"</string>
     <string name="permlab_changeBackgroundDataSetting" msgid="1400666012671648741">"更改后台数据使用设置"</string>
     <string name="permdesc_changeBackgroundDataSetting" msgid="5347729578468744379">"允许应用更改后台数据使用设置。"</string>
-    <string name="permlab_accessWifiState" msgid="5202012949247040011">"查看 Wi-Fi 连接"</string>
-    <string name="permdesc_accessWifiState" msgid="5002798077387803726">"允许该应用查看 Wi-Fi 网络的相关信息,例如是否启用了 Wi-Fi 以及连接的 Wi-Fi 设备的名称。"</string>
-    <string name="permlab_changeWifiState" msgid="6550641188749128035">"连接 Wi-Fi 和断开连接"</string>
-    <string name="permdesc_changeWifiState" msgid="7137950297386127533">"允许该应用与 Wi-Fi 接入点建立和断开连接,以及更改 Wi-Fi 网络的设备配置。"</string>
-    <string name="permlab_changeWifiMulticastState" msgid="1368253871483254784">"允许接收 Wi-Fi 多播"</string>
-    <string name="permdesc_changeWifiMulticastState" product="tablet" msgid="7969774021256336548">"允许该应用使用多播地址接收发送到 Wi-Fi 网络上所有设备(而不仅仅是您的平板电脑)的数据包。该操作的耗电量比非多播模式要大。"</string>
-    <string name="permdesc_changeWifiMulticastState" product="default" msgid="6851949706025349926">"允许该应用使用多播地址接收发送到 Wi-Fi 网络上所有设备(而不仅仅是您的手机)的数据包。该操作的耗电量比非多播模式要大。"</string>
+    <string name="permlab_accessWifiState" msgid="5202012949247040011">"查看 WLAN 连接"</string>
+    <string name="permdesc_accessWifiState" msgid="5002798077387803726">"允许该应用查看 WLAN 网络的相关信息,例如是否启用了 WLAN 以及连接的 WLAN 设备的名称。"</string>
+    <string name="permlab_changeWifiState" msgid="6550641188749128035">"连接 WLAN 和断开连接"</string>
+    <string name="permdesc_changeWifiState" msgid="7137950297386127533">"允许该应用与 WLAN 接入点建立和断开连接,以及更改 WLAN 网络的设备配置。"</string>
+    <string name="permlab_changeWifiMulticastState" msgid="1368253871483254784">"允许接收 WLAN 多播"</string>
+    <string name="permdesc_changeWifiMulticastState" product="tablet" msgid="7969774021256336548">"允许该应用使用多播地址接收发送到 WLAN 网络上所有设备(而不仅仅是您的平板电脑)的数据包。该操作的耗电量比非多播模式要大。"</string>
+    <string name="permdesc_changeWifiMulticastState" product="default" msgid="6851949706025349926">"允许该应用使用多播地址接收发送到 WLAN 网络上所有设备(而不仅仅是您的手机)的数据包。该操作的耗电量比非多播模式要大。"</string>
     <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"访问蓝牙设置"</string>
     <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"允许应用配置本地蓝牙平板电脑,以及发现远程设备并进行配对。"</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"允许应用配置本地蓝牙手机,以及发现远程设备并进行配对。"</string>
@@ -1130,23 +1130,23 @@
     <string name="ringtone_picker_title" msgid="3515143939175119094">"铃声"</string>
     <string name="ringtone_unknown" msgid="5477919988701784788">"未知铃声"</string>
   <plurals name="wifi_available">
-    <item quantity="one" msgid="6654123987418168693">"有可用的 Wi-Fi 网络"</item>
-    <item quantity="other" msgid="4192424489168397386">"有可用的 Wi-Fi 网络"</item>
+    <item quantity="one" msgid="6654123987418168693">"有可用的 WLAN 网络"</item>
+    <item quantity="other" msgid="4192424489168397386">"有可用的 WLAN 网络"</item>
   </plurals>
   <plurals name="wifi_available_detailed">
-    <item quantity="one" msgid="1634101450343277345">"打开可用的 Wi-Fi 网络"</item>
-    <item quantity="other" msgid="7915895323644292768">"打开可用的 Wi-Fi 网络"</item>
+    <item quantity="one" msgid="1634101450343277345">"打开可用的 WLAN 网络"</item>
+    <item quantity="other" msgid="7915895323644292768">"打开可用的 WLAN 网络"</item>
   </plurals>
-    <string name="wifi_available_sign_in" msgid="4029489716605255386">"登录到 Wi-Fi 网络"</string>
+    <string name="wifi_available_sign_in" msgid="4029489716605255386">"登录到 WLAN 网络"</string>
     <string name="network_available_sign_in" msgid="8495155593358054676">"登录网络"</string>
     <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
     <skip />
-    <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"无法连接到 Wi-Fi"</string>
+    <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"无法连接到 WLAN"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" 互联网连接状况不佳。"</string>
-    <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
-    <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"启动 Wi-Fi Direct。此操作将会关闭 Wi-Fi 客户端/热点。"</string>
-    <string name="wifi_p2p_failed_message" msgid="3763669677935623084">"无法启动 Wi-Fi Direct。"</string>
-    <string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"已启用 Wi-Fi Direct"</string>
+    <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"WLAN Direct"</string>
+    <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"启动 WLAN Direct。此操作将会关闭 WLAN 客户端/热点。"</string>
+    <string name="wifi_p2p_failed_message" msgid="3763669677935623084">"无法启动 WLAN Direct。"</string>
+    <string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"已启用 WLAN Direct"</string>
     <string name="wifi_p2p_enabled_notification_message" msgid="1638949953993894335">"通过触摸进行设置"</string>
     <string name="accept" msgid="1645267259272829559">"接受"</string>
     <string name="decline" msgid="2112225451706137894">"拒绝"</string>
@@ -1156,8 +1156,8 @@
     <string name="wifi_p2p_to_message" msgid="248968974522044099">"收件人:"</string>
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"键入所需的 PIN:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
-    <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="8012981257742232475">"平板电脑连接到“<xliff:g id="DEVICE_NAME">%1$s</xliff:g>”时会暂时断开与 Wi-Fi 的连接"</string>
-    <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"手机连接到<xliff:g id="DEVICE_NAME">%1$s</xliff:g>时会暂时断开与 Wi-Fi 的连接。"</string>
+    <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="8012981257742232475">"平板电脑连接到“<xliff:g id="DEVICE_NAME">%1$s</xliff:g>”时会暂时断开与 WLAN 的连接"</string>
+    <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"手机连接到<xliff:g id="DEVICE_NAME">%1$s</xliff:g>时会暂时断开与 WLAN 的连接。"</string>
     <string name="select_character" msgid="3365550120617701745">"插入字符"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"正在发送短信"</string>
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;在发送大量短信。是否允许该应用继续发送短信?"</string>
@@ -1399,12 +1399,12 @@
     <string name="data_usage_3g_limit_title" msgid="7093334419518706686">"2G-3G 数据已停用"</string>
     <string name="data_usage_4g_limit_title" msgid="7636489436819470761">"4G 数据已停用"</string>
     <string name="data_usage_mobile_limit_title" msgid="7869402519391631884">"移动数据已停用"</string>
-    <string name="data_usage_wifi_limit_title" msgid="8992154736441284865">"Wi-Fi 数据网络已停用"</string>
+    <string name="data_usage_wifi_limit_title" msgid="8992154736441284865">"WLAN 数据网络已停用"</string>
     <string name="data_usage_limit_body" msgid="3317964706973601386">"触摸可启用。"</string>
     <string name="data_usage_3g_limit_snoozed_title" msgid="7026739121138005231">"已超出 2G-3G 数据流量限制"</string>
     <string name="data_usage_4g_limit_snoozed_title" msgid="1106562779311209039">"已超出 4G 数据使用上限"</string>
     <string name="data_usage_mobile_limit_snoozed_title" msgid="279240572165412168">"已超出移动数据流量上限"</string>
-    <string name="data_usage_wifi_limit_snoozed_title" msgid="8743856006384825974">"超出了 Wi-Fi 数据流量上限"</string>
+    <string name="data_usage_wifi_limit_snoozed_title" msgid="8743856006384825974">"超出了 WLAN 数据流量上限"</string>
     <string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"超出规定上限 <xliff:g id="SIZE">%s</xliff:g>。"</string>
     <string name="data_usage_restricted_title" msgid="5965157361036321914">"后台数据受限制"</string>
     <string name="data_usage_restricted_body" msgid="6741521330997452990">"触摸可去除限制。"</string>
@@ -1498,7 +1498,8 @@
     <string name="user_switched" msgid="3768006783166984410">"当前用户是<xliff:g id="NAME">%1$s</xliff:g>。"</string>
     <string name="owner_name" msgid="2716755460376028154">"机主"</string>
     <string name="error_message_title" msgid="4510373083082500195">"错误"</string>
-    <string name="app_no_restricted_accounts" msgid="4011285085817350390">"此应用不支持受限个人资料的帐户"</string>
+    <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+    <skip />
     <string name="app_not_found" msgid="3429141853498927379">"找不到可处理此操作的应用"</string>
     <string name="revoke" msgid="5404479185228271586">"撤消"</string>
 </resources>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 5d55678..f175fc1 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -1498,7 +1498,8 @@
     <string name="user_switched" msgid="3768006783166984410">"目前的使用者是 <xliff:g id="NAME">%1$s</xliff:g>。"</string>
     <string name="owner_name" msgid="2716755460376028154">"擁有者"</string>
     <string name="error_message_title" msgid="4510373083082500195">"錯誤"</string>
-    <string name="app_no_restricted_accounts" msgid="4011285085817350390">"這個應用程式不支援設有限制的個人資料所屬帳戶"</string>
+    <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+    <skip />
     <string name="app_not_found" msgid="3429141853498927379">"找不到支援此操作的應用程式"</string>
     <string name="revoke" msgid="5404479185228271586">"撤銷"</string>
 </resources>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index df86b74..eed5e04 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -1498,7 +1498,7 @@
     <string name="user_switched" msgid="3768006783166984410">"Umsebenzisi wamanje <xliff:g id="NAME">%1$s</xliff:g>."</string>
     <string name="owner_name" msgid="2716755460376028154">"Umnikazi"</string>
     <string name="error_message_title" msgid="4510373083082500195">"Iphutha"</string>
-    <string name="app_no_restricted_accounts" msgid="4011285085817350390">"Lolu hlelo lokusebenza alusekeli ama-akhawunti wamaphrofayela akhawulelwe"</string>
+    <string name="app_no_restricted_accounts" msgid="5739463249673727736">"Lolu hlelo lokusebenza alusekeli ama-akhawunti wamaphrofayela akhawulelwe"</string>
     <string name="app_not_found" msgid="3429141853498927379">"Alukho uhlelo lokusebenza olutholakele lokuphatha lesi senzo"</string>
     <string name="revoke" msgid="5404479185228271586">"Chitha"</string>
 </resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 5d71f75..459a634 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -4057,10 +4057,6 @@
         <attr name="drawable" />
     </declare-styleable>
 
-    <declare-styleable name="MipmapDrawableItem">
-        <attr name="drawable" />
-    </declare-styleable>
-
     <!-- Drawable used to rotate another drawable. -->
     <declare-styleable name="RotateDrawable">
         <attr name="visible" />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index f282188..d40eb64 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -4123,7 +4123,7 @@
     <!-- Error message title [CHAR LIMIT=35] -->
     <string name="error_message_title">Error</string>
     <!-- Message informing user that app is not permitted to access accounts. [CHAR LIMIT=none] -->
-    <string name="app_no_restricted_accounts">This application does not support accounts for restricted profiles</string>
+    <string name="app_no_restricted_accounts">This app doesn\'t support accounts for restricted profiles</string>
     <!-- Message informing user that the requested activity could not be found [CHAR LIMIT=none] -->
     <string name="app_not_found">No application found to handle this action</string>
     <string name="revoke">Revoke</string>
diff --git a/docs/html/about/dashboards/index.jd b/docs/html/about/dashboards/index.jd
index 6956634..43eead9 100644
--- a/docs/html/about/dashboards/index.jd
+++ b/docs/html/about/dashboards/index.jd
@@ -57,7 +57,7 @@
 </div>
 
 
-<p style="clear:both"><em>Data collected during a 14-day period ending on May 1, 2013.
+<p style="clear:both"><em>Data collected during a 14-day period ending on June 3, 2013.
 <br/>Any versions with less than 0.1% distribution are not shown.</em>
 </p>
 
@@ -83,7 +83,7 @@
 </div>
 
 
-<p style="clear:both"><em>Data collected during a 14-day period ending on May 1, 2013
+<p style="clear:both"><em>Data collected during a 14-day period ending on June 3, 2013
 <br/>Any screen configurations with less than 0.1% distribution are not shown.</em></p>
 
 
@@ -130,7 +130,7 @@
 
 
 
-<p style="clear:both"><em>Data collected during a 14-day period ending on May 1, 2013</em></p>
+<p style="clear:both"><em>Data collected during a 14-day period ending on June 3, 2013</em></p>
 
 
 
@@ -148,7 +148,7 @@
 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",
+    "chart": "//chart.googleapis.com/chart?chl=Eclair%7CFroyo%7CGingerbread%7CHoneycomb%7CIce%20Cream%20Sandwich%7CJelly%20Bean&chd=t%3A1.6%2C3.2%2C36.5%2C0.1%2C25.6%2C33.0&chf=bg%2Cs%2C00000000&chco=c4df9b%2C6fad0c&cht=p&chs=500x250",
     "data": [
       {
         "api": 4,
@@ -158,12 +158,12 @@
       {
         "api": 7,
         "name": "Eclair",
-        "perc": "1.7"
+        "perc": "1.5"
       },
       {
         "api": 8,
         "name": "Froyo",
-        "perc": "3.7"
+        "perc": "3.2"
       },
       {
         "api": 9,
@@ -173,7 +173,7 @@
       {
         "api": 10,
         "name": "Gingerbread",
-        "perc": "38.4"
+        "perc": "36.4"
       },
       {
         "api": 13,
@@ -183,17 +183,17 @@
       {
         "api": 15,
         "name": "Ice Cream Sandwich",
-        "perc": "27.5"
+        "perc": "25.6"
       },
       {
         "api": 16,
         "name": "Jelly Bean",
-        "perc": "26.1"
+        "perc": "29.0"
       },
       {
         "api": 17,
         "name": "Jelly Bean",
-        "perc": "2.3"
+        "perc": "4.0"
       }
     ]
   }
@@ -205,35 +205,34 @@
 
 var SCREEN_DATA =
 [
-
   {
     "data": {
       "Large": {
         "hdpi": "0.4",
         "ldpi": "0.6",
-        "mdpi": "2.9",
+        "mdpi": "3.0",
         "tvdpi": "1.0",
-        "xhdpi": "0.7"
+        "xhdpi": "0.6"
       },
       "Normal": {
-        "hdpi": "37.3",
+        "hdpi": "36.0",
         "ldpi": "0.1",
-        "mdpi": "16.1",
-        "xhdpi": "24.9",
-        "xxhdpi": "1.3"
+        "mdpi": "16.0",
+        "xhdpi": "24.5",
+        "xxhdpi": "3.3"
       },
       "Small": {
-        "ldpi": "9.8"
+        "hdpi": "0.1",
+        "ldpi": "9.9"
       },
       "Xlarge": {
-        "hdpi": "0.1",
-        "ldpi": "0.2",
-        "mdpi": "4.5",
+        "hdpi": "0.2",
+        "mdpi": "4.2",
         "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"
+    "densitychart": "//chart.googleapis.com/chart?chl=ldpi%7Cmdpi%7Ctvdpi%7Chdpi%7Cxhdpi%7Cxxhdpi&chd=t%3A10.6%2C23.2%2C1.0%2C36.7%2C25.2%2C3.3&chf=bg%2Cs%2C00000000&chco=c4df9b%2C6fad0c&cht=p&chs=400x250",
+    "layoutchart": "//chart.googleapis.com/chart?chl=Xlarge%7CLarge%7CNormal%7CSmall&chd=t%3A4.5%2C5.6%2C79.9%2C10.0&chf=bg%2Cs%2C00000000&chco=c4df9b%2C6fad0c&cht=p&chs=400x250"
   }
 ];
 
diff --git a/docs/html/about/index.jd b/docs/html/about/index.jd
index 0b72701..1573cc3 100644
--- a/docs/html/about/index.jd
+++ b/docs/html/about/index.jd
@@ -1,4 +1,5 @@
 page.title=Android, the world's most popular mobile platform
+excludeFromSuggestions=true
 walkthru=0
 header.hide=0
 
diff --git a/docs/html/about/start.jd b/docs/html/about/start.jd
index fbe70e3..727c975 100644
--- a/docs/html/about/start.jd
+++ b/docs/html/about/start.jd
@@ -1,4 +1,5 @@
 page.title=Get Started
+excludeFromSuggestions=true
 walkthru=0
 
 @jd:body
diff --git a/docs/html/channels/io2013.jd b/docs/html/channels/io2013.jd
new file mode 100644
index 0000000..977eb2f
--- /dev/null
+++ b/docs/html/channels/io2013.jd
@@ -0,0 +1,346 @@
+fullpage=true
+page.title=Google I/O 13
+@jd:body
+    
+<style>
+#ioplayer-frame {
+  z-index:10;
+  width:703px;
+  height:396px;
+  margin:0;
+  position:relative;
+}
+
+#noplayer-message {
+  position:absolute;
+  top:50%;left:0;
+  width:100%;
+  z-index:-1;
+  text-align:center;
+  display:none;
+}
+
+h1 {
+  font-weight:100;
+  font-size:40px;
+  line-height:30px;
+  margin:30px 0 10px 0px;
+  color:#000;
+}
+
+h2 {
+  font-weight:100;
+  font-size:30px;
+  line-height:30px;
+  margin:12px 0 10px 0px;
+  color:#000;
+  float:left;
+  display:block;
+}
+
+.col-4 h2 {
+  margin-top:40px;
+}
+
+ul.videos {
+  list-style:none;
+  margin:0;
+  width:auto;
+}
+ul.videos li {
+  display:block;
+  float:left;
+  position:relative;
+  margin:0 2px 2px 0;
+  background-repeat:no-repeat !important;
+  background-size:320px auto;
+  background-position:10% 50%;
+  z-index:1; /* IE: the description is 2 */
+}
+ul.videos li a {
+  color:#fff !important;
+  display:block;
+  margin:0;
+  padding:8px 12px;
+  width:209px;
+  height:134px;
+  box-shadow:inset 500px 500px 999px rgba(000, 000, 000, 0.2);
+  background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, rgba(0,0,0,0.8)), color-stop(1, transparent));
+  background-image: -webkit-linear-gradient(top, rgba(0,0,0,0.8), transparent);
+  background-image: -moz-linear-gradient(top, rgba(0,0,0,0.8), transparent);
+  background-image: -o-linear-gradient(top, rgba(0,0,0,0.8), transparent);
+  background-image: linear-gradient(to bottom, rgba(0,0,0,0.8), transparent);
+  filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#cc000000', endColorstr='#00ffffff',GradientType=0 ); /* IE6-9 */
+}
+ul.videos.featured li {
+  margin:0 0 2px;
+}
+ul.videos.featured li a {
+  margin:0;
+  height:115px;
+}
+ul.videos li a:hover {
+  box-shadow:inset 500px 500px 999px rgba(255,255,255, 0.6);
+}
+ul.videos li h4 {
+  text-shadow:1px 1px 0 rgba(0,0,0,0.8);
+  font-size:18px;
+  line-height:22px;
+  color:#fff;
+  margin:0;
+  height:100%; /* IE: to fill clickable area */
+}
+
+ul.videos li .description-frame {
+  display:none;
+  z-index:2; /* IE: the li is 1 */
+}
+ul.videos li a:hover .description-frame {
+  display:block;
+  position:absolute;
+  top:80px;
+  left:8px;
+  z-index:99;
+}
+ul.videos .description {
+  background:#fff;
+  width:200px;
+  padding:8px;
+  -webkit-border-radius:1px;
+  -moz-border-radius:1px;
+  border-radius:1px;
+  -moz-box-shadow: 0 2px 3px 2px rgba(000,000,000, 0.4);
+  -webkit-box-shadow: 0 2px 3px 2px rgba(000,000,000, 0.4);
+  box-shadow: 0 2px 3px 2px rgba(000,000,000, 0.4);
+  font-size:11px;
+  line-height:12px;
+  color:#000;
+  overflow:hidden;
+}
+ul.videos .arrow-up {
+  position:absolute;
+  left:15px;
+  top:-11px;
+  width:0;
+  height:0;
+  border-bottom:12px solid #fff;
+  border-left:12px solid transparent;
+  border-right:12px solid transparent;
+}
+ul.videos .arrow-down {
+  position:absolute;
+  left:15px;
+  bottom:-11px;
+  width:0;
+  height:0;
+  border-top:12px solid #fff;
+  border-left:12px solid transparent;
+  border-right:12px solid transparent;
+}
+
+ul.videos span.tag {
+  font-size:.9em;
+  font-weight:normal;
+  display: block;
+  position: absolute;
+  bottom: 0;
+  color: #fff;
+  left: 0;
+  padding: 4px;
+  border-top-right-radius:4px;
+  text-transform:uppercase;
+  text-shadow: none;
+}
+ul.videos span.tag.design {
+  background-color:rgba(51, 181, 229, .7);
+  filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#cc33b5e5', endColorstr='#cc33b5e5',GradientType=0 ); /* IE6-9 */
+}
+ul.videos span.tag.develop {
+  background-color:rgba(255, 136, 0, .7);
+  filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ccff8800', endColorstr='#ccff8800',GradientType=0 ); /* IE6-9 */
+}
+ul.videos span.tag.distribute {
+  background-color:rgba(153, 204, 0, .7);
+  filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#cc99cc00', endColorstr='#cc99cc00',GradientType=0 ); /* IE6-9 */
+}
+
+</style>
+
+
+
+
+
+
+
+<div class="wrap">
+
+  <div class="col-12" style="width:704px;margin:0">
+    <h1>Android @ Google I/O 13</h1>
+    <div id="ioplayer-frame">
+      <div id="noplayer-message">
+        <!-- busted flash player message -->
+        Your video is supposed to appear here.<br/>
+        Make sure you have the <a href="//get.adobe.com/flashplayer/" target="_blank">Flash&reg; Player</a>.
+      </div>
+      <div id="player"><!-- Youtube embeds here... actually replaces this div --></div>
+    </div>
+  </div>
+
+  <div class="col-4" style="margin:0;width:234px;padding:0 0 0 2px">
+    <h2 class="norule">Most Popular</h2>
+    <ul class="videos featured" id="playlist2">
+    </ul>
+  </div>
+</div>
+
+<div class="wrap">
+
+    <div style="position:absolute;width:940px;text-align:right">
+      <a href="//www.youtube.com/AndroidDevelopers" target="_blank">
+      More on YouTube
+        <img src="//www.youtube.com/favicon.ico" style="border:0;width:16px;height:16px;vertical-align:middle;margin:0 2px 3px 2px">
+      </a>
+    </div>
+  <div style="width:944px;overflow:hidden;padding:0 0 20px">
+    <h2 class="norule">All Videos</h2>
+    <ul class="videos" id="playlist1" style="clear:left">
+      <span id="videos-design"></span>
+      <span id="videos-develop"></span>
+      <span id="videos-distribute"></span>
+    </ul>
+  </div>
+
+</div>
+
+<br class="clearfix"/>
+
+      
+      
+      
+      
+      
+      
+      
+      
+      
+
+<script src="//swfobject.googlecode.com/svn/trunk/swfobject/swfobject.js" type="text/javascript"></script>
+<script type="text/javascript">
+
+/* Load a video into the player box.
+ * @param id        The YouTube video ID
+ * @param title     The video title to display in the player box (character escaped)
+ * @param autoplay  Whether to automatically play the video
+ */
+function loadVideo(id, title, autoplay) {
+  var url = '//www.youtube.com/v/' + id + '&rel=1&border=0&fs=1' + (autoplay?'&autoplay=1':'');
+  swfobject.embedSWF(url, 'player', '704', '397', '9.0.0', false, false, {allowfullscreen: 'true'});
+  $('body,html').animate({ scrollTop: 0 }, "slow");
+  setTimeout(function(){$('#noplayer-message').show()}, 2000);
+}
+
+
+function buildPlaylistDesign(data) {
+  buildPlaylist(data, $('ul#playlist1 #videos-design'), "design");
+}
+
+function buildPlaylistDevelop(data) {
+  buildPlaylist(data, $('ul#playlist1 #videos-develop'), "develop");
+}
+
+function buildPlaylistDistribute(data) {
+  buildPlaylist(data, $('ul#playlist1 #videos-distribute'), "distribute");
+}
+
+function buildPlaylist2(data) {
+  buildPlaylist(data, $('ul#playlist2'));
+}
+
+function buildPlaylist(data, ul, tag) {
+
+  var MAX_DESC_LENGTH = 200; // the length at which we will trim the description
+  var feed = data.feed;
+  var entries = feed.entry || [];
+  var playlistId = feed.yt$playlistId.$t;
+
+  // Loop through each entry (each video) and add it to the '#DevelopersLive' list
+  for (var i = 0; i < entries.length; i++) {
+    var entry = entries[i];
+    var title = entry.title.$t;
+    var id = entry.media$group.yt$videoid.$t;
+    // get 180x320 thumbnail
+    var thumbs = entry.media$group.media$thumbnail;
+    var thumbUrl;
+    for (var j = 0; j < thumbs.length; j++) {
+      if (thumbs[j].yt$name == "hqdefault") {
+        thumbUrl = thumbs[j].url;
+      }
+    }
+
+    // chop out the google io title
+    title = title.substr(title.indexOf("-") + 1, title.length);
+
+    var fullDescription = entry.media$group.media$description.$t;
+    var playerUrl = entry.media$group.media$content[0].url;
+    var shortDescription = fullDescription.substr(0, MAX_DESC_LENGTH);
+    // further shorten description if there's a url (remove it)
+    var httpindex = shortDescription.indexOf("http://");
+    if (httpindex != -1) {
+      shortDescription = shortDescription.substring(0,httpindex);
+    }
+    shortDescription += shortDescription.length == MAX_DESC_LENGTH ? "..." : ""; // add ellipsis if we've chopped the description
+
+    var a = $('<a href="#" id="' + id + '" '
+          + 'onclick="loadVideo(\'' + id + '\',\'' + escape(title) + '\',true); return false;" />');
+    var pShortDescription = $('<div class="description-frame"><div class="arrow-up"></div>'
+          + '<div class="description">' + shortDescription + '</div></div>');
+    var h4Title = "<h4>" + title + "</h4>";
+    var li = $('<li style="background-image:url(\'' + thumbUrl +'\')" />');
+
+    li.append(a);
+    a.append(h4Title).append(pShortDescription);
+
+    if (tag !== undefined) {
+      var $tag = $('<span class="tag ' + tag + '">' + tag + '</span>');
+      a.append($tag);
+    }
+
+    ul.append(li);
+
+
+    // put the first video in the player 
+    if ((tag == "design") && (i == 0)) {
+      loadVideo(id, escape(title), false);
+    }
+  }
+}
+
+
+/* Request the playlist feeds from YouTube */
+function showDevelopersLivePlaylist() {
+  var playlistId = "PLWz5rJ2EKKc-qVhMuAprIFYFbCotdgJKq"; /* IO 13 - Design */
+  $.getScript("//gdata.youtube.com/feeds/api/playlists/"
+          + playlistId +
+          "?v=2&alt=json-in-script&max-results=50&callback=buildPlaylistDesign&orderby=position");
+
+  playlistId = "PLWz5rJ2EKKc9rkwO9yBosRvkQBJd5utmR"; /* IO 13 - Develop */
+  $.getScript("//gdata.youtube.com/feeds/api/playlists/"
+          + playlistId +
+          "?v=2&alt=json-in-script&max-results=50&callback=buildPlaylistDevelop&orderby=position");
+
+  playlistId = "PLWz5rJ2EKKc-1WjgQqL0B4OQtbLfhMlB2"; /* IO 13 - Distribute */
+  $.getScript("//gdata.youtube.com/feeds/api/playlists/"
+          + playlistId +
+          "?v=2&alt=json-in-script&max-results=50&callback=buildPlaylistDistribute&orderby=position");
+
+
+  playlistId = "PLWz5rJ2EKKc9WGUwq2gQ-coU3fSyexgOx"; /* IO 13 - The Android Sessions */
+  $.getScript("//gdata.youtube.com/feeds/api/playlists/"
+          + playlistId +
+          "?v=2&alt=json-in-script&max-results=3&callback=buildPlaylist2&orderby=viewCount");
+}
+
+showDevelopersLivePlaylist();
+
+
+</script>
\ No newline at end of file
diff --git a/docs/html/google/gcm/gcm.jd b/docs/html/google/gcm/gcm.jd
index 886677a..5acf60d 100644
--- a/docs/html/google/gcm/gcm.jd
+++ b/docs/html/google/gcm/gcm.jd
@@ -1,4 +1,4 @@
-page.title=Google Cloud Messaging for Android
+page.title=GCM Architectural Overview
 @jd:body
 
 <div id="qv-wrapper">
diff --git a/docs/html/google/play-services/gcm.jd b/docs/html/google/play-services/gcm.jd
index 67b55ea..a9da73f 100644
--- a/docs/html/google/play-services/gcm.jd
+++ b/docs/html/google/play-services/gcm.jd
@@ -1,4 +1,4 @@
-page.title=GCM Extensions for Android
+page.title=GCM Extensions
 page.tags="cloud","push","messaging"
 header.hide=1
 @jd:body
diff --git a/docs/html/guide/appendix/media-formats.jd b/docs/html/guide/appendix/media-formats.jd
index 2342087..069a603 100644
--- a/docs/html/guide/appendix/media-formats.jd
+++ b/docs/html/guide/appendix/media-formats.jd
@@ -1,4 +1,4 @@
-page.title=Android Supported Media Formats
+page.title=Supported Media Formats
 page.tags="video","audio","mpeg","mp4","m4a","mp3","3gp","3gpp","flac","wave","wav"
 @jd:body
 
diff --git a/docs/html/guide/faq/commontasks.jd b/docs/html/guide/faq/commontasks.jd
index 7b90de2..086721f 100644
--- a/docs/html/guide/faq/commontasks.jd
+++ b/docs/html/guide/faq/commontasks.jd
@@ -1,6 +1,5 @@
 page.title=Common Tasks and How to Do Them in Android
-parent.title=FAQs, Tips, and How-to
-parent.link=index.html
+excludeFromSuggestions=true
 @jd:body
 
 <ul>
diff --git a/docs/html/guide/faq/framework.jd b/docs/html/guide/faq/framework.jd
index 4a7a3fc..c851e72 100644
--- a/docs/html/guide/faq/framework.jd
+++ b/docs/html/guide/faq/framework.jd
@@ -1,6 +1,5 @@
 page.title=Android Application Framework FAQ
-parent.title=FAQs, Tips, and How-to
-parent.link=index.html
+excludeFromSuggestions=true
 @jd:body
 
 <ul>
diff --git a/docs/html/guide/faq/index.jd b/docs/html/guide/faq/index.jd
index 9a2614b..0c5fb0e 100644
--- a/docs/html/guide/faq/index.jd
+++ b/docs/html/guide/faq/index.jd
@@ -1,4 +1,5 @@
 page.title=Android FAQs
+excludeFromSuggestions=true
 @jd:body
 
 <dl>
diff --git a/docs/html/guide/faq/licensingandoss.jd b/docs/html/guide/faq/licensingandoss.jd
index c267fe81..d1dd9a7 100644
--- a/docs/html/guide/faq/licensingandoss.jd
+++ b/docs/html/guide/faq/licensingandoss.jd
@@ -1,6 +1,5 @@
 page.title=Android Open Source Licensing FAQ
-parent.title=FAQs, Tips, and How-to
-parent.link=index.html
+excludeFromSuggestions=true
 @jd:body
 
 <ul>
diff --git a/docs/html/guide/faq/security.jd b/docs/html/guide/faq/security.jd
index a6e07c8..96fc7f5 100644
--- a/docs/html/guide/faq/security.jd
+++ b/docs/html/guide/faq/security.jd
@@ -1,6 +1,5 @@
 page.title=Android Security FAQ
-parent.title=FAQs, Tips, and How-to
-parent.link=index.html
+excludeFromSuggestions=true
 @jd:body
 
 <ul>
diff --git a/docs/html/guide/faq/troubleshooting.jd b/docs/html/guide/faq/troubleshooting.jd
index f19f5ec..8bb7eeb 100644
--- a/docs/html/guide/faq/troubleshooting.jd
+++ b/docs/html/guide/faq/troubleshooting.jd
@@ -1,6 +1,5 @@
 page.title=Troubleshooting
-parent.title=FAQs, Tips, and How-to
-parent.link=index.html
+excludeFromSuggestions=true
 @jd:body
 
 
diff --git a/docs/html/guide/guide_toc.cs b/docs/html/guide/guide_toc.cs
index ff35d2e..5f9f530 100644
--- a/docs/html/guide/guide_toc.cs
+++ b/docs/html/guide/guide_toc.cs
@@ -76,9 +76,16 @@
           <span class="en">Permissions</span>
         </a>
       </li>
-      <li><a href="<?cs var:toroot ?>guide/topics/appwidgets/index.html">
+      <li class="nav-section">
+        <div class="nav-section-header"><a href="<?cs var:toroot ?>guide/topics/appwidgets/index.html">
             <span class="en">App Widgets</span>
-          </a></li>
+          </a></div>
+        <ul>
+          <li><a href="<?cs var:toroot ?>guide/topics/appwidgets/host.html">
+              <span class="en">App Widget Host</span>
+            </a></li>
+        </ul>
+      </li>
       <li class="nav-section">
       <div class="nav-section-header"><a href="<?cs var:toroot ?>guide/topics/manifest/manifest-intro.html">
           <span class="en">Android Manifest</span>
diff --git a/docs/html/guide/topics/appwidgets/host.jd b/docs/html/guide/topics/appwidgets/host.jd
new file mode 100644
index 0000000..da7408f
--- /dev/null
+++ b/docs/html/guide/topics/appwidgets/host.jd
@@ -0,0 +1,392 @@
+page.title=App Widget Host
+page.tags="AppWidgetHost","home screen","launcher"
+@jd:body
+
+<div id="qv-wrapper">
+  <div id="qv">
+    
+    <h2>In this document</h2>
+        <ol>
+          <li><a href="#host-binding">Binding App Widgets</a>
+          <ol>
+            <li><a href="#binding-pre">Binding app widgets on Android 4.0 and lower</a></li>
+            <li><a href="#binding-41">Binding app widgets on Android 4.1 and higher</a></li>
+         </ol>
+          </li>
+          <li><a href="#host-state">Host Responsibilities</a>
+          <ol>
+            <li><a href="#30">Android 3.0</a></li>
+            <li><a href="#31">Android 3.1</a></li>
+            <li><a href="#40">Android 4.0</a></li>
+            <li><a href="#41">Android 4.1</li>
+            <li><a href="#42">Android 4.2</a></li>
+         </ol>
+         </li>
+      </ol>
+  </div>
+</div>
+
+
+<p>The Android Home screen available on most Android devices allows the user
+to embed <a href="{@docRoot}guide/topics/appwidgets/index.html">app widgets</a> for quick
+access to content. If you're building a Home replacement or a similar app,
+you can also allow the user to embed app widgets by implementing an
+{@link android.appwidget.AppWidgetHost}.
+This is not something that most apps will ever need to do, but if you are 
+creating your own host, it's important to understand the contractual obligations 
+a host implicitly agrees to.</p>
+
+<p>This document focuses on the responsibilities involved in implementing a custom 
+{@link android.appwidget.AppWidgetHost}. For an example of how to implement an 
+{@link android.appwidget.AppWidgetHost}, see the source code for the
+Android Home screen 
+<a href="https://android.googlesource.com/platform/packages/apps/Launcher2/+/master/src/com/android/launcher2/Launcher.java">
+Launcher</a>. 
+
+
+<p>Here is an overview of key classes and concepts involved in implementing a custom 
+{@link android.appwidget.AppWidgetHost}:</p>
+<ul>
+    <li><strong>App Widget Host</strong>&mdash;  
+    The {@link android.appwidget.AppWidgetHost} provides the interaction 
+with the AppWidget service for apps, like the home screen, that want to embed 
+app widgets in their UI. An {@link android.appwidget.AppWidgetHost} must have 
+an ID that is unique within the host's own package. This ID remains persistent 
+across all uses of the host. The ID is typically a hard-coded value that you assign
+in your application.</li>
+  
+    <li><strong>App Widget ID</strong>&mdash;
+    Each app widget instance is assigned a unique ID at the time of binding 
+(see {@link android.appwidget.AppWidgetManager#bindAppWidgetIdIfAllowed bindAppWidgetIdIfAllowed()}, 
+discussed in more detail in <a href="#binding">Binding app widgets</a>). 
+The unique ID is obtained by the host using {@link android.appwidget.AppWidgetHost#allocateAppWidgetId() allocateAppWidgetId()}. This ID is persistent across the lifetime of the widget, 
+that is, until it is deleted from the host. Any host-specific state (such as the 
+size and location of the widget) should be persisted by the hosting package and 
+associated with the app widget ID.
+</li>
+  
+    <li><strong>App Widget Host View</strong>&mdash;  
+    {@link android.appwidget.AppWidgetHostView} can be thought of as a frame 
+that the widget is wrapped in whenever it needs to be displayed. An app widget 
+is assigned to an {@link android.appwidget.AppWidgetHostView} every time the 
+widget is inflated by the host. </li>
+    <li><strong>Options Bundle</strong>&mdash;
+The {@link android.appwidget.AppWidgetHost} uses the options bundle to communicate 
+information to the {@link android.appwidget.AppWidgetProvider} about how the 
+widget is being displayed (for example, size range, and whether the widget is on 
+a lockscreen or the home screen). This information allows the 
+{@link android.appwidget.AppWidgetProvider} to tailor the widget's contents 
+and appearance based on how and where it is  displayed.
+You use 
+{@link android.appwidget.AppWidgetHostView#updateAppWidgetOptions(android.os.Bundle) updateAppWidgetOptions()}
+and 
+{@link android.appwidget.AppWidgetHostView#updateAppWidgetSize updateAppWidgetSize()}
+
+to modify an app widget's 
+bundle. Both of these methods trigger a callback to the 
+{@link android.appwidget.AppWidgetProvider}.</p></li>
+</ul>
+
+<h2 id="host-binding">Binding App Widgets</h2>
+
+<p>When a user adds an app widget to a host, a process called
+<em>binding</em> occurs. <em>Binding</em> refers to associating
+a particular app widget ID to a specific host and to a specific
+{@link android.appwidget.AppWidgetProvider}. There are different
+ways of achieving this, depending on what version of Android your
+app is running on.</p>
+
+<h3 id="binding-pre">Binding app widgets on Android 4.0 and lower</h3>
+
+<p>On devices running Android version 4.0 and lower, users add app widgets 
+via a system activity that allows users to select a widget. This implicitly 
+does a permission check&mdash;that is, by adding the app widget, the user is 
+implicitly granting permission to your app to add app widgets to the host. 
+Here is an example that illustrates 
+this approach, taken from the original 
+<a href="https://android.googlesource.com/platform/packages/apps/Launcher/+/master/src/com/android/launcher/Launcher.java">Launcher</a>. In this snippet, an event handler invokes 
+{@link android.app.Activity#startActivityForResult(android.content.Intent,int) startActivityForResult()} 
+with the request code {@code REQUEST_PICK_APPWIDGET} in response to a 
+user action:</p>
+
+<pre>
+private static final int REQUEST_CREATE_APPWIDGET = 5;
+private static final int REQUEST_PICK_APPWIDGET = 9;
+...
+public void onClick(DialogInterface dialog, int which) {
+    switch (which) {
+    ...
+        case AddAdapter.ITEM_APPWIDGET: {
+            ...
+            int appWidgetId = 
+                    Launcher.this.mAppWidgetHost.allocateAppWidgetId();
+            Intent pickIntent = 
+                    new Intent(AppWidgetManager.ACTION_APPWIDGET_PICK);
+            pickIntent.putExtra
+                    (AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
+            ...
+            startActivityForResult(pickIntent, REQUEST_PICK_APPWIDGET);
+            break;
+    }
+    ...
+}</pre>
+
+<p>When the system activity finishes, it returns a result with the user's chosen
+app widget to your activity. In the following example, the activity responds
+by calling {@code addAppWidget()} to add the app widget:</p>
+
+<pre>public final class Launcher extends Activity 
+        implements View.OnClickListener, OnLongClickListener {
+    ...
+    &#64;Override
+    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+        mWaitingForResult = false;
+
+        if (resultCode == RESULT_OK && mAddItemCellInfo != null) {
+            switch (requestCode) {
+                ...
+                case REQUEST_PICK_APPWIDGET:
+                    addAppWidget(data);
+                    break;
+                case REQUEST_CREATE_APPWIDGET:
+                    completeAddAppWidget(data, mAddItemCellInfo, !mDesktopLocked);
+                    break;
+                }
+        } 
+        ...
+    }
+}</pre>
+
+<p>The method {@code addAppWidget()} checks to see if the app widget
+needs to be configured before it's added:</p>
+
+<pre>void addAppWidget(Intent data) {
+    int appWidgetId = data.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);
+
+    String customWidget = data.getStringExtra(EXTRA_CUSTOM_WIDGET);
+    AppWidgetProviderInfo appWidget = 
+            mAppWidgetManager.getAppWidgetInfo(appWidgetId);
+
+    if (appWidget.configure != null) {
+        // Launch over to configure widget, if needed.
+        Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_CONFIGURE);
+        intent.setComponent(appWidget.configure);
+        intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
+        startActivityForResult(intent, REQUEST_CREATE_APPWIDGET);
+    } else {
+        // Otherwise, finish adding the widget.
+    }
+}</pre>
+
+<p>For more discussion of configuration,
+see <a href="{@docRoot}guide/topics/appwidgets/index.html#Configuring">Creating an
+App Widget Configuration Activity</a>.</p>
+
+<p>Once the app widget is ready, the next step is to do the
+actual work of adding it to the workspace. The 
+<a href="https://android.googlesource.com/platform/packages/apps/Launcher/+/master/src/com/android/launcher/Launcher.java">original Launcher</a> uses a method called {@code completeAddAppWidget()}
+to do this.</p>
+
+<h3 id="binding-41">Binding app widgets on Android 4.1 and higher</h3>
+
+<p>Android 4.1 adds APIs for a more streamlined binding process.
+These APIs also make it possible for a host to provide a custom UI for
+binding. To use this improved process, your app must declare the
+{@link android.Manifest.permission#BIND_APPWIDGET} permission in its manifest:</p>
+
+<pre>&lt;uses-permission android:name="android.permission.BIND_APPWIDGET" /&gt;
+</pre>
+
+
+<p>But this is just the first step. At runtime the user must
+explicitly grant permission to your app to allow it to add app widgets
+to the host. To test whether your app has permission to add the widget,
+you use the 
+{@link android.appwidget.AppWidgetManager#bindAppWidgetIdIfAllowed bindAppWidgetIdIfAllowed()} 
+method. 
+If {@link android.appwidget.AppWidgetManager#bindAppWidgetIdIfAllowed bindAppWidgetIdIfAllowed()}
+returns {@code false}, your app must display a dialog prompting the
+user to grant permission 
+("allow" or "always allow," to cover all future app widget additions).
+This snippet gives an example of how to display the dialog:</p>
+
+<pre>Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_BIND);
+intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
+intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_PROVIDER, info.componentName);
+// This is the options bundle discussed above
+intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS, options);
+startActivityForResult(intent, REQUEST_BIND_APPWIDGET);
+</pre>
+
+<p>The host also has to check whether the user added 
+an app widget that needs configuration. For more discussion of this topic,
+see 
+<a href="{@docRoot}guide/topics/appwidgets/index.html#Configuring">Creating
+an App Widget Configuration Activity</a>.</p>
+
+<h2 id="host-state">Host Responsibilities</h2>
+
+<div class="sidebox-wrapper">
+<div class="sidebox">
+  <h2>What Version are You Targeting?</h2>
+  <p>The approach you use in implementing your host should depend on what Android version  
+you're targeting. Many of the features described in this section were introduced 
+in 3.0 or later. For example:</p>
+<ul>
+<li>Android 3.0 (API Level 11) introduces auto-advance behavior for widgets.</li>
+<li>Android 3.1 (API Level 12) introduces the ability to resize widgets.</li>
+<li>Android 4.0 (API Level 15) introduces a change in padding policy that
+puts the responsibility on the 
+host to manage padding.</li>
+<li>Android 4.1 (API Level 16) adds an API that allows the widget provider
+to get more detailed information about the environment in which its
+widget instances are being hosted.</li>
+<li>Android 4.2 (API Level 17) introduces the options bundle and the 
+{@link android.appwidget.AppWidgetManager#bindAppWidgetIdIfAllowed(int,android.content.ComponentName,android.os.Bundle) bindAppWidgetIdIfAllowed()} 
+method. It also introduces lockscreen widgets.</li>
+</ul>
+<p>If you are targeting earlier devices, refer to the original 
+<a href="https://android.googlesource.com/platform/packages/apps/Launcher/+/master/src/com/android/launcher/Launcher.java">Launcher</a> as an example.
+</div>
+</div>
+
+<p>Widget developers can specify a number of configuration settings
+for widgets using the <a href="{@docRoot}guide/topics/appwidgets/index.html#MetaData">
+AppWidgetProviderInfo metadata</a>.
+These configuration options, discussed in more detail below, can be
+retrieved by the host from the {@link android.appwidget.AppWidgetProviderInfo}
+object associated with a widget provider.</p>
+
+<p>Regardless of the version of Android you are targeting, all hosts
+have the following responsibilities:</p>
+
+<ul>
+<li>When adding a widget, you must allocate the widget ID as described above.
+You must also make sure that when a widget is removed from the host, you call {@link android.appwidget.AppWidgetHost#deleteAppWidgetId deleteAppWidgetId()}
+to deallocate the widget ID.</li>
+
+<li>When adding a widget, be sure to launch its configuration activity
+if it exists, as described in
+<a href="{@docRoot}guide/topics/appwidgets/index.html#UpdatingFromTheConfiguration">
+Updating the App Widget
+from the Configuration Activity</a>. This is a necessary step for many app widgets before
+they can be properly displayed.</li>
+
+<li>Every app widget specifies a minimum width and height in dps, as defined in the {@link android.appwidget.AppWidgetProviderInfo} metadata
+(using {@link android.appwidget.AppWidgetProviderInfo#minWidth android:minWidth} and 
+{@link android.appwidget.AppWidgetProviderInfo#minHeight android:minHeight}).
+Make sure that the widget is laid out with at least this many dps.
+For example, many hosts align icons and widgets in a grid. In this scenario,
+by default the host should add the app widget using the minimum number of
+cells that satisfy the {@code minWidth} and {@code minHeight} constraints.</li>
+
+</ul>
+
+<p>In addition to the requirements listed above, specific platform
+versions introduce features that place new responsibilities on the
+host. These are described in the following sections.</p>
+
+<h3 id="30">Android 3.0</h3>
+
+<p>Android 3.0 (API Level 11) introduces the ability for a widget to specify {@link android.appwidget.AppWidgetProviderInfo#autoAdvanceViewId autoAdvanceViewId()}.
+This view ID should point to an instance of an
+{@link android.widget.Advanceable}, such as {@link android.widget.StackView}
+or {@link android.widget.AdapterViewFlipper}. This indicates that the host
+should call {@link android.widget.Advanceable#advance advance()} on this
+view at an interval deemed appropriate by the host (taking into account whether
+it makes sense to advance the widget&mdash;for example, the host probably
+wouldn't want to advance a widget if it were on another page, or
+if the screen were turned off).</p>
+
+<h3 id="31">Android 3.1</h3>
+
+<p>Android 3.1 (API Level 12) introduces the ability to resize widgets.
+A widget can specify that it is resizable using the
+{@link android.appwidget.AppWidgetProviderInfo#resizeMode android:resizeMode}
+attribute in the {@link android.appwidget.AppWidgetProviderInfo}
+metadata, and indicate whether it supports horizontal and/or
+vertical resizing. Introduced in Android 4.0 (API Level 14), the widget can also specify a
+{@link android.appwidget.AppWidgetProviderInfo#minResizeWidth android:minResizeWidth}
+and/or {@link android.appwidget.AppWidgetProviderInfo#minResizeHeight android:minResizeHeight}.</p>
+
+<p>It is the host’s responsibility to make it possible for the
+widget to be resized horizontally and/or vertically, as specified
+by the widget. A widget that specifies that it is resizable can be
+resized arbitrarily large, but should not be resized smaller than
+the values specified by {@link
+android.appwidget.AppWidgetProviderInfo#minResizeWidth android:minResizeWidth}
+and {@link
+android.appwidget.AppWidgetProviderInfo#minResizeHeight android:minResizeHeight}.
+For a sample implementation, see  <a href="https://android.googlesource.com/platform/packages/apps/Launcher2/+/master/src/com/android/launcher2/AppWidgetResizeFrame.java">
+{@code AppWidgetResizeFrame}</a> in {@code Launcher2}.</p>
+
+
+<h3 id="40">Android 4.0</h3>
+
+<p>Android 4.0 (API Level 15) introduces a change in padding policy that
+puts the responsibility on the host to manage padding. As of 4.0, app
+widgets no longer include their own padding. Instead, the system adds
+padding for each widget, based the characteristics of the current screen.
+This leads to a more uniform, consistent presentation of widgets in a grid.
+To assist applications that host app widgets, the platform provides
+the method
+{@link android.appwidget.AppWidgetHostView#getDefaultPaddingForWidget getDefaultPaddingForWidget()}.
+Applications can call this method to get the system-defined padding
+and account for it when computing the number of cells to allocate to the widget.</p>
+
+<h3 id="41">Android 4.1</h3>
+
+<p>Android 4.1 (API Level 16) adds an API that allows the widget provider
+to get more detailed information  about the environment in which its
+widget instances are being hosted. Specifically, the host hints to the
+widget provider about the size at which the widget is being displayed.
+It is the host’s responsibility to provide this size information.</p>
+
+<p>The host provides this information via
+{@link android.appwidget.AppWidgetHostView#updateAppWidgetSize updateAppWidgetSize()}.
+The size is specified as a minimum and maximum width/height in dps.
+The reason that a range is specified (as opposed to a fixed size)
+is because the width and height of a widget may change with orientation.
+You don’t want the host to have to update all of its widgets on rotation,
+as this could cause serious system slowdown. These values should be
+updated once upon the widget being placed, any time the widget is resized,
+and any time the launcher inflates the widget for the first time in a
+given boot (as the values aren’t persisted across boot).</p>
+
+
+<h3 id="42">Android 4.2</h3>
+
+<p>Android 4.2 (API Level 17) adds the ability for the options bundle
+to be specified at bind time. This is the ideal way to specify app
+widget options, including size, as it gives the {@link
+android.appwidget.AppWidgetProvider} immediate access to the options
+data on the first update. This can be achieved by using the method {@link android.appwidget.AppWidgetManager#bindAppWidgetIdIfAllowed(int,android.content.ComponentName,android.os.Bundle) bindAppWidgetIdIfAllowed()}. For more discussion of this topic,
+see <a href="#host-binding">Binding app widgets</a>.</p>
+
+<p>Android 4.2 also introduces lockscreen widgets. When hosting widgets
+on the lockscreen, the host must specify this information within the app
+widget options bundle (the {@link
+android.appwidget.AppWidgetProvider} can use this information to style
+the widget appropriately). To designate a widget as a lockscreen widget, use {@link android.appwidget.AppWidgetHostView#updateAppWidgetOptions updateAppWidgetOptions()}
+and include the field
+{@link android.appwidget.AppWidgetManager#OPTION_APPWIDGET_HOST_CATEGORY}
+with the value {@link android.appwidget.AppWidgetProviderInfo#WIDGET_CATEGORY_KEYGUARD}.
+This option defaults to
+{@link android.appwidget.AppWidgetProviderInfo#WIDGET_CATEGORY_HOME_SCREEN},
+so it is not explicitly required to set this for a home screen host.</p>
+
+<p>Make sure that your host adds only app widgets that are appropriate
+for your app&mdash;for example, if your host is a home screen, ensure
+that the
+{@link android.appwidget.AppWidgetProviderInfo#widgetCategory android:widgetCategory}
+attribute in the 
+{@link android.appwidget.AppWidgetProviderInfo} metadata includes
+the flag {@link android.appwidget.AppWidgetProviderInfo#WIDGET_CATEGORY_HOME_SCREEN}.
+Similarly, for the lockscreen, ensure that field includes the flag  {@link android.appwidget.AppWidgetProviderInfo#WIDGET_CATEGORY_KEYGUARD}. For more
+discussion of this topic, see
+<a href="{@docRoot}guide/topics/appwidgets/index.html#lockscreen">
+Enabling App Widgets on the Lockscreen</a>.</p>
+
+
+
+
diff --git a/docs/html/guide/topics/appwidgets/index.jd b/docs/html/guide/topics/appwidgets/index.jd
index 774c66a..d8ad844 100644
--- a/docs/html/guide/topics/appwidgets/index.jd
+++ b/docs/html/guide/topics/appwidgets/index.jd
@@ -22,15 +22,16 @@
         <ol>
           <li><a href="#UpdatingFromTheConfiguration">Updating the App Widget
 from 
-            the configuration Activity</a></li>
+            the Configuration Activity</a></li>
         </ol>
       </li>
       <li><a href="#preview">Setting a Preview Image</a></li>
-      <li><a href="#lockscreen">Enabling App Widgets on the Lockscreen
+      <li><a href="#lockscreen">Enabling App Widgets on the Lockscreen</a>
         <ol>
-          <li><a href="#lockscreen-sizing">Sizing guidelines</li>
+          <li><a href="#lockscreen-sizing">Sizing guidelines</a></li>
         </ol>
       </li>
+
       <li><a href="#collections">Using App Widgets with Collections</a>
         <ol>
           <li><a href="#collection_sample">Sample application</a></li>
@@ -66,7 +67,9 @@
 <img src="{@docRoot}images/appwidgets/appwidget.png" alt="" />
 
 <p>This document describes how to publish an App Widget using an App Widget
-provider.</p>
+provider. For a discussion of creating your own {@link android.appwidget.AppWidgetHost}
+to host app widgets, see <a href="{@docRoot}guide/topics/appwidgets/host.html">
+App Widget Host</a>.</p>
 
 <div class="note design">
 <p><strong>Widget Design</strong></p>
@@ -100,7 +103,7 @@
 and allows him or her
 to modify App Widget settings at create-time.</p>
 
-<p>The following sections describe how to setup each of these components.</p>
+<p>The following sections describe how to set up each of these components.</p>
 
 
 <h2 id="Manifest">Declaring an App Widget in the Manifest</h2>
@@ -165,8 +168,8 @@
 
 <pre>
 &lt;appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
-    android:minWidth="294dp"
-    android:minHeight="72dp"
+    android:minWidth="40dp"
+    android:minHeight="40dp"
     android:updatePeriodMillis="86400000"
     android:previewImage="@drawable/preview"
     android:initialLayout="@layout/example_appwidget"
@@ -270,6 +273,14 @@
 To declare a widget as resizeable horizontally and vertically, supply the value
 "horizontal|vertical". Introduced in Android 3.1.</li> 
 
+<li>The <code>minResizeHeight</code> attribute specifies the minimum height (in dps) to which
+the widget can be resized. This field has no effect if it is greater than {@code minHeight} or if
+vertical resizing isn't enabled (see <code>resizeMode</code>). Introduced in Android 4.0.</li>
+
+<li>The <code> minResizeWidth </code> attribute specifies the minimum width (in dps) to which
+the widget can be resized. This field has no effect if it is greater than {@code minWidth} or if
+horizontal resizing isn't enabled (see <code>resizeMode</code>). Introduced in Android 4.0.</li>
+
 <li>The <code>widgetCategory</code> attribute declares whether your App Widget can be displayed on the home screen, 
 the lock screen (keyguard), or both. Values for this attribute include "home_screen" and "keyguard".  A widget that 
 is displayed on both needs to ensure that it follows the design guidelines for both widget classes. For more
@@ -788,12 +799,12 @@
 
 <h2 id="collections">Using App Widgets with Collections</h2>
 
-<p>Android 3.0 introduces App Widgets with collections. These kinds of App
+<p>Android 3.0 introduces app widgets with collections. These kinds of App
 Widgets use the {@link android.widget.RemoteViewsService} to display collections
 that are backed by remote data, such as from a <a
 href="{@docRoot}guide/topics/providers/content-providers.html">content
 provider</a>. The data provided by the {@link android.widget.RemoteViewsService}
-is presented in the App Widget using one of the following view types, which
+is presented in the app widget using one of the following view types, which
 we’ll refer to as “collection views:”</p>
 
 <dl>
@@ -900,15 +911,15 @@
 </ul>
 <h3 id="implementing_collections">Implementing app widgets with collections</h3>
 
-<p>To implement an App Widget with collections, you follow the same basic steps 
+<p>To implement an app widget with collections, you follow the same basic steps 
 you would use to implement any app widget. The following sections  describe the
-additional steps you need to perform to implement an App Widget with
+additional steps you need to perform to implement an app widget with
 collections.</p>
 
 <h4>Manifest for app widgets with collections</h4>
 
 <p> In addition to the requirements listed in <a href="#Manifest">Declaring an
-App Widget in the Manifest</a>, to make it possible for App Widgets with
+app widget in the Manifest</a>, to make it possible for app widgets with
 collections to bind to your {@link android.widget.RemoteViewsService}, you must
 declare the service in your manifest file with the permission {@link
 android.Manifest.permission#BIND_REMOTEVIEWS}. This prevents other applications
@@ -987,7 +998,7 @@
 android.widget.RemoteViewsService.RemoteViewsFactory RemoteViewsFactory}, and
 the widget can serve up the appropriate data. When you call this method, you
 must pass an intent that  points to your implementation of {@link
-android.widget.RemoteViewsService} and the App Widget ID that specifies the app
+android.widget.RemoteViewsService} and the app widget ID that specifies the app
 widget to update.</p>
 
 
@@ -1009,7 +1020,7 @@
         // Add the app widget ID to the intent extras.
         intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetIds[i]);
         intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));
-        // Instantiate the RemoteViews object for the App Widget layout.
+        // Instantiate the RemoteViews object for the app widget layout.
         RemoteViews rv = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
         // Set up the RemoteViews object to use a RemoteViews adapter. 
         // This adapter connects
@@ -1367,15 +1378,15 @@
 
 <h3 id="fresh">Keeping Collection Data Fresh</h3>
 
-<p>The following figure illustrates the flow that occurs in an App Widget that
+<p>The following figure illustrates the flow that occurs in an app widget that
 uses
-collections when updates occur. It shows how the App Widget code interacts with
+collections when updates occur. It shows how the app widget code interacts with
 the  {@link android.widget.RemoteViewsService.RemoteViewsFactory
 RemoteViewsFactory}, and how you can trigger updates:</p>
 
 <img src="{@docRoot}images/appwidgets/appwidget_collections.png" alt="" />
 
-<p>One feature of App Widgets that use collections is the ability to provide
+<p>One feature of app widgets that use collections is the ability to provide
 users with up-to-date content. For example, consider the Android 3.0 Gmail
 app widget, which provides users with a snapshot of their inbox. To make this
 possible, you need to be able to trigger your {@link
diff --git a/docs/html/images/home/io-videos-2013.png b/docs/html/images/home/io-videos-2013.png
new file mode 100644
index 0000000..8655e8f
--- /dev/null
+++ b/docs/html/images/home/io-videos-2013.png
Binary files differ
diff --git a/docs/html/index.jd b/docs/html/index.jd
index 0799802..3435283 100644
--- a/docs/html/index.jd
+++ b/docs/html/index.jd
@@ -13,21 +13,25 @@
         <div class="frame">
             <ul>
                 <li class="item carousel-home">
-                    <div class="content-left col-10">
-                    <a href="https://developers.google.com/live/android/browse">
-                      <img src="{@docRoot}images/home/io-gdl-2013.png" style="margin:60px 0 0">
-                    </a>
+                    <div class="content-left col-11" style="padding-top:10px;">
+                        <a href="{@docRoot}channels/io2013.html">
+                          <img src="{@docRoot}images/home/io-videos-2013.png" style="margin:60px 0 0;
+                          box-shadow: 3px 10px 18px 1px #999;">
+                        </a>
                     </div>
-                    <div class="content-right col-5">
+                    <div class="content-right col-4">
                     <h1>Watch the Android talks from Google I/O</h1>
                     <p>If you weren't able to attend Google I/O in person or couldn't make it
                     to all the talks, you can catch up on the action
                     with all the recordings, brought to you by
                     <a href="http://developers.google.com/live">Google Developers Live</a>.</p>
-                    <p><a href="https://developers.google.com/live/android/browse" class="button"
+                    <p><a href="{@docRoot}channels/io2013.html" class="button"
                     >See the Android talks</a></p>
                     </div>
                 </li>
+
+
+
                 <li class="item carousel-home">
                     <div class="content-left col-11" style="padding-top:65px;">
                       <script src="//ajax.googleapis.com/ajax/libs/swfobject/2.2/swfobject.js"></script>
diff --git a/docs/html/sdk/installing/migrate.jd b/docs/html/sdk/installing/migrate.jd
index d988a95..20a698b 100644
--- a/docs/html/sdk/installing/migrate.jd
+++ b/docs/html/sdk/installing/migrate.jd
@@ -15,26 +15,27 @@
 <li>In Eclipse, select <strong>File > Export</strong>.</li>
 <li>In the window that appears, open <strong>Android</strong> and select <strong>Generate Gradle
 build files</strong>.</li>
-<li>Select the projects you want to export for Android Studio and click
+<li>Select the project you want to export for Android Studio and click
 <strong>Finish</strong>.</li>
 </ol>
 
-<p>Your selected projects remain in the same location but now contain a {@code build.gradle}
-file and are ready for Android Studio.</p>
+<p>Your selected project remains in the same location but now contains a {@code build.gradle}
+file and is ready for Android Studio.</p>
 
 
 <h2 id="Export">Import into Android Studio</h2>
 <ol>
-  <li>In Android Studio, select <strong>File > Import Project</strong>.</li>
-  <li>Locate a project you exported from Eclipse, select the project's root directory and
-    click <strong>OK</strong>.</li>
-  <li>Select <strong>Create project from existing sources</strong> and click
-    <strong>Next</strong>.</li>
-  <li>Follow the walk-through to complete the import process.</li>
+  <li>In Android Studio, close any projects currently open. You should see the
+  <strong>Welcome to Android Studio</strong> window.</li>
+  <li>Click <strong>Import Project</strong>.</li>
+  <li>Locate the project you exported from Eclipse, expand it, select the
+  <strong>build.gradle</strong> file and click <strong>OK</strong>.</li>
+  <li>In the following dialog, leave <strong>Use gradle wrapper</strong> selected and click
+  <strong>OK</strong>. (You do not need to specify the Gradle home.)</li>
 </ol>
 
 
-<p>Now that your projects are imported to Android Studio, 
+<p>Now that your project is imported to Android Studio, 
 read <a href="{@docRoot}sdk/installing/studio-tips.html">Tips and Tricks</a> for some
 help getting started.</p>
 
diff --git a/docs/html/tools/devices/emulator.jd b/docs/html/tools/devices/emulator.jd
index fda233d..ea1549d 100644
--- a/docs/html/tools/devices/emulator.jd
+++ b/docs/html/tools/devices/emulator.jd
@@ -1,6 +1,4 @@
-page.title=Using the Android Emulator
-parent.title=Managing Virtual Devices
-parent.link=index.html
+page.title=Using the Emulator
 @jd:body
 
 <div id="qv-wrapper">
diff --git a/docs/html/tools/extras/support-library.jd b/docs/html/tools/extras/support-library.jd
index 9cc0361..60168f4 100644
--- a/docs/html/tools/extras/support-library.jd
+++ b/docs/html/tools/extras/support-library.jd
@@ -565,7 +565,7 @@
   <li>Proceed to install the package.</li>
 </ol>
 
-<p>When done, all files (including source code, samples, and the {@code .jar} files) are saved
+<p>When done, all files (including source code, samples, and the JAR files) are saved
 into the <code>&lt;sdk&gt;/extras/android/support/</code> directory. This directory contains
 each of the different support libraries, such as the library for API level 4 and up and the library
 for API level 13 and up, each named with the respective version (such as {@code v4/}).</p>
@@ -574,20 +574,57 @@
 <h2 id="SettingUp">Setting Up a Project to Use a Library</h2>
 
 <p>To add one of the libraries to your Android project:</p>
+<dl>
+    <dt>
+        Add the JAR file to your project.
+    </dt>
+    <dd>
+        Copy the JAR file for the library you want to use into your Android project. To do this:
+        <ul>
+            <li>
+                Create the directory {@code libs/} at the root of your project
+                (next to {@code src/}, {@code res/}, and so forth).
+            </li>
+            <li>
+                Locate the JAR file for the library you want to use and copy it into the
+                {@code libs/} directory.
+                <p>
+                    For example, the library that supports API level 4 and up is located at
+                    {@code &lt;sdk&gt;/extras/android/support/v4/android-support-v4.jar}.
+                </p>
+            </li>
+        </ul>
+        <p>
+            Your build system may expect to find the JAR file in a directory other than
+            {@code libs}. Read the documentation for your build system to learn where to put the
+            JAR file.
+        </p>
+    </dd>
+    <dt>
+        If necessary, add the {@code libs/} directory to your build path.
+    </dt>
+    <dd>
+        Read the documentation for your build system to learn how to add the JAR file to the
+        build path.
+    </dd>
+</dl>
+<p>
+    To confirm that you've added the JAR file to the correct directory and added it to the build
+    path:
+</p>
 <ol>
-  <li>In your Android project, create a directory named {@code libs} at the root of your
-project (next to {@code src/}, {@code res/}, etc.)</li>
-  <li>Locate the JAR file for the library you want to use and copy it into the {@code
-libs/} directory.
-    <p>For example, the library that supports API level 4 and up is located at {@code
-&lt;sdk&gt;/extras/android/support/v4/android-support-v4.jar}.</p>
-  </li>
-  <li>Add the JAR to your project build path.
-    <p>In Eclipse, right-click the JAR file in the Package Explorer, select <strong>Build
-Path</strong> &gt; <strong>Add to Build Path</strong>.</p>
-  </li>
+    <li>
+        Edit one of your source files to add an {@code import} statement that imports a
+        class from the {@code android.support.*} package.
+    </li>
+    <li>
+        Build your app. The code should compile cleanly.
+    </li>
+    <li>
+        As a double-check, run your app. It should run correctly, without any runtime exceptions
+        indicating that the class in {@code android.support.*} can't be found.
+    </li>
 </ol>
-
 <p>Your application is now ready to use the library APIs. All the
 provided APIs are available in the {@code android.support} package (for
 example, {@code android.support.v4}).</p>
diff --git a/docs/html/tools/tools_toc.cs b/docs/html/tools/tools_toc.cs
index a63492e..6389880 100644
--- a/docs/html/tools/tools_toc.cs
+++ b/docs/html/tools/tools_toc.cs
@@ -53,7 +53,7 @@
         <ul>
           <li><a href="<?cs var:toroot ?>tools/devices/managing-avds.html"><span class="en">With AVD Manager</span></a></li>
           <li><a href="<?cs var:toroot ?>tools/devices/managing-avds-cmdline.html"><span class="en">From the Command Line</span></a></li>
-          <li><a href="<?cs var:toroot ?>tools/devices/emulator.html"><span class="en">Using the Android Emulator</span></a></li>
+          <li><a href="<?cs var:toroot ?>tools/devices/emulator.html"><span class="en">Using the Emulator</span></a></li>
         </ul>
       </li>
       <li><a href="<?cs var:toroot ?>tools/device.html"><span class="en">Using Hardware Devices</span></a></li>
diff --git a/docs/html/training/location/receive-location-updates.jd b/docs/html/training/location/receive-location-updates.jd
index eb4ffa3..c33f075 100644
--- a/docs/html/training/location/receive-location-updates.jd
+++ b/docs/html/training/location/receive-location-updates.jd
@@ -567,7 +567,12 @@
     protected void onStop() {
         // If the client is connected
         if (mLocationClient.isConnected()) {
-            stopPeriodicUpdates();
+            /*
+             * Remove location updates for a listener.
+             * The current Activity is the listener, so
+             * the argument is "this".
+             */
+            removeLocationUpdates(this);
         }
         /*
          * After disconnect() is called, the client is
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index 6d236d9..c8fce9e 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -869,10 +869,6 @@
             drawable = new StateListDrawable();
         } else if (name.equals("level-list")) {
             drawable = new LevelListDrawable();
-        /* Probably not doing this.
-        } else if (name.equals("mipmap")) {
-            drawable = new MipmapDrawable();
-        */
         } else if (name.equals("layer-list")) {
             drawable = new LayerDrawable();
         } else if (name.equals("transition")) {
diff --git a/graphics/java/android/graphics/drawable/MipmapDrawable.java b/graphics/java/android/graphics/drawable/MipmapDrawable.java
deleted file mode 100644
index cd39719..0000000
--- a/graphics/java/android/graphics/drawable/MipmapDrawable.java
+++ /dev/null
@@ -1,312 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.graphics.drawable;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-import android.content.res.Resources;
-import android.content.res.TypedArray;
-import android.graphics.Rect;
-import android.util.AttributeSet;
-
-import java.io.IOException;
-
-/**
- * @hide -- we are probably moving to do MipMaps in another way (more integrated
- * with the resource system).
- *
- * A resource that manages a number of alternate Drawables, and which actually draws the one which
- * size matches the most closely the drawing bounds. Providing several pre-scaled version of the
- * drawable helps minimizing the aliasing artifacts that can be introduced by the scaling.
- *
- * <p>
- * Use {@link #addDrawable(Drawable)} to define the different Drawables that will represent the
- * mipmap levels of this MipmapDrawable. The mipmap Drawable that will actually be used when this
- * MipmapDrawable is drawn is the one which has the smallest intrinsic height greater or equal than
- * the bounds' height. This selection ensures that the best available mipmap level is scaled down to
- * draw this MipmapDrawable.
- * </p>
- *
- * If the bounds' height is larger than the largest mipmap, the largest mipmap will be scaled up.
- * Note that Drawables without intrinsic height (i.e. with a negative value, such as Color) will
- * only be used if no other mipmap Drawable are provided. The Drawables' intrinsic heights should
- * not be changed after the Drawable has been added to this MipmapDrawable.
- *
- * <p>
- * The different mipmaps' parameters (opacity, padding, color filter, gravity...) should typically
- * be similar to ensure a continuous visual appearance when the MipmapDrawable is scaled. The aspect
- * ratio of the different mipmaps should especially be equal.
- * </p>
- *
- * A typical example use of a MipmapDrawable would be for an image which is intended to be scaled at
- * various sizes, and for which one wants to provide pre-scaled versions to precisely control its
- * appearance.
- *
- * <p>
- * The intrinsic size of a MipmapDrawable are inferred from those of the largest mipmap (in terms of
- * {@link Drawable#getIntrinsicHeight()}). On the opposite, its minimum
- * size is defined by the smallest provided mipmap.
- * </p>
-
- * It can be defined in an XML file with the <code>&lt;mipmap></code> element.
- * Each mipmap Drawable is defined in a nested <code>&lt;item></code>. For example:
- * <pre>
- * &lt;mipmap xmlns:android="http://schemas.android.com/apk/res/android">
- *  &lt;item android:drawable="@drawable/my_image_8" />
- *  &lt;item android:drawable="@drawable/my_image_32" />
- *  &lt;item android:drawable="@drawable/my_image_128" />
- * &lt;/mipmap>
- *</pre>
- * <p>
- * With this XML saved into the res/drawable/ folder of the project, it can be referenced as
- * the drawable for an {@link android.widget.ImageView}. Assuming that the heights of the provided
- * drawables are respectively 8, 32 and 128 pixels, the first one will be scaled down when the
- * bounds' height is lower or equal than 8 pixels. The second drawable will then be used up to a
- * height of 32 pixels and the largest drawable will be used for greater heights.
- * </p>
- * @attr ref android.R.styleable#MipmapDrawableItem_drawable
- */
-public class MipmapDrawable extends DrawableContainer {
-    private final MipmapContainerState mMipmapContainerState;
-    private boolean mMutated;
-
-    public MipmapDrawable() {
-        this(null, null);
-    }
-
-    /**
-     * Adds a Drawable to the list of available mipmap Drawables. The Drawable actually used when
-     * this MipmapDrawable is drawn is determined from its bounds.
-     *
-     * This method has no effect if drawable is null.
-     *
-     * @param drawable The Drawable that will be added to list of available mipmap Drawables.
-     */
-
-    public void addDrawable(Drawable drawable) {
-        if (drawable != null) {
-            mMipmapContainerState.addDrawable(drawable);
-            onDrawableAdded();
-        }
-    }
-
-    private void onDrawableAdded() {
-        // selectDrawable assumes that the container content does not change.
-        // When a Drawable is added, the same index can correspond to a new Drawable, and since
-        // selectDrawable has a fast exit case when oldIndex==newIndex, the new drawable could end
-        // up not being used in place of the previous one if they happen to share the same index.
-        // This make sure the new computed index can actually replace the previous one.
-        selectDrawable(-1);
-        onBoundsChange(getBounds());
-    }
-
-    // overrides from Drawable
-
-    @Override
-    protected void onBoundsChange(Rect bounds) {
-        final int index = mMipmapContainerState.indexForBounds(bounds);
-
-        // Will call invalidateSelf() if needed
-        selectDrawable(index);
-
-        super.onBoundsChange(bounds);
-    }
-
-    @Override
-    public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs)
-    throws XmlPullParserException, IOException {
-
-        super.inflate(r, parser, attrs);
-
-        int type;
-
-        final int innerDepth = parser.getDepth() + 1;
-        int depth;
-        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
-                && ((depth = parser.getDepth()) >= innerDepth
-                        || type != XmlPullParser.END_TAG)) {
-            if (type != XmlPullParser.START_TAG) {
-                continue;
-            }
-
-            if (depth > innerDepth || !parser.getName().equals("item")) {
-                continue;
-            }
-
-            TypedArray a = r.obtainAttributes(attrs,
-                    com.android.internal.R.styleable.MipmapDrawableItem);
-
-            int drawableRes = a.getResourceId(
-                    com.android.internal.R.styleable.MipmapDrawableItem_drawable, 0);
-
-            a.recycle();
-
-            Drawable dr;
-            if (drawableRes != 0) {
-                dr = r.getDrawable(drawableRes);
-            } else {
-                while ((type = parser.next()) == XmlPullParser.TEXT) {
-                }
-                if (type != XmlPullParser.START_TAG) {
-                    throw new XmlPullParserException(
-                            parser.getPositionDescription()
-                            + ": <item> tag requires a 'drawable' attribute or "
-                            + "child tag defining a drawable");
-                }
-                dr = Drawable.createFromXmlInner(r, parser, attrs);
-            }
-
-            mMipmapContainerState.addDrawable(dr);
-        }
-
-        onDrawableAdded();
-    }
-
-    @Override
-    public Drawable mutate() {
-        if (!mMutated && super.mutate() == this) {
-            mMipmapContainerState.mMipmapHeights = mMipmapContainerState.mMipmapHeights.clone();
-            mMutated = true;
-        }
-        return this;
-    }
-
-    private final static class MipmapContainerState extends DrawableContainerState {
-        private int[] mMipmapHeights;
-
-        MipmapContainerState(MipmapContainerState orig, MipmapDrawable owner, Resources res) {
-            super(orig, owner, res);
-
-            if (orig != null) {
-                mMipmapHeights = orig.mMipmapHeights;
-            } else {
-                mMipmapHeights = new int[getChildren().length];
-            }
-
-            // Change the default value
-            setConstantSize(true);
-        }
-
-        /**
-         * Returns the index of the child mipmap drawable that will best fit the provided bounds.
-         * This index is determined by comparing bounds' height and children intrinsic heights.
-         * The returned mipmap index is the smallest mipmap which height is greater or equal than
-         * the bounds' height. If the bounds' height is larger than the largest mipmap, the largest
-         * mipmap index is returned.
-         *
-         * @param bounds The bounds of the MipMapDrawable.
-         * @return The index of the child Drawable that will best fit these bounds, or -1 if there
-         * are no children mipmaps.
-         */
-        public int indexForBounds(Rect bounds) {
-            final int boundsHeight = bounds.height();
-            final int N = getChildCount();
-            for (int i = 0; i < N; i++) {
-                if (boundsHeight <= mMipmapHeights[i]) {
-                    return i;
-                }
-            }
-
-            // No mipmap larger than bounds found. Use largest one which will be scaled up.
-            if (N > 0) {
-                return N - 1;
-            }
-            // No Drawable mipmap at all
-            return -1;
-        }
-
-        /**
-         * Adds a Drawable to the list of available mipmap Drawables. This list can be retrieved
-         * using {@link DrawableContainer.DrawableContainerState#getChildren()} and this method
-         * ensures that it is always sorted by increasing {@link Drawable#getIntrinsicHeight()}.
-         *
-         * @param drawable The Drawable that will be added to children list
-         */
-        public void addDrawable(Drawable drawable) {
-            // Insert drawable in last position, correctly resetting cached values and
-            // especially mComputedConstantSize
-            int pos = addChild(drawable);
-
-            // Bubble sort the last drawable to restore the sort by intrinsic height
-            final int drawableHeight = drawable.getIntrinsicHeight();
-
-            while (pos > 0) {
-                final Drawable previousDrawable = mDrawables[pos-1];
-                final int previousIntrinsicHeight = previousDrawable.getIntrinsicHeight();
-
-                if (drawableHeight < previousIntrinsicHeight) {
-                    mDrawables[pos] = previousDrawable;
-                    mMipmapHeights[pos] = previousIntrinsicHeight;
-
-                    mDrawables[pos-1] = drawable;
-                    mMipmapHeights[pos-1] = drawableHeight;
-                    pos--;
-                } else {
-                    break;
-                }
-            }
-        }
-
-        /**
-         * Intrinsic sizes are those of the largest available mipmap.
-         * Minimum sizes are those of the smallest available mipmap.
-         */
-        @Override
-        protected void computeConstantSize() {
-            final int N = getChildCount();
-            if (N > 0) {
-                final Drawable smallestDrawable = mDrawables[0];
-                mConstantMinimumWidth = smallestDrawable.getMinimumWidth();
-                mConstantMinimumHeight = smallestDrawable.getMinimumHeight();
-
-                final Drawable largestDrawable = mDrawables[N-1];
-                mConstantWidth = largestDrawable.getIntrinsicWidth();
-                mConstantHeight = largestDrawable.getIntrinsicHeight();
-            } else {
-                mConstantWidth = mConstantHeight = -1;
-                mConstantMinimumWidth = mConstantMinimumHeight = 0;
-            }
-            mComputedConstantSize = true;
-        }
-
-        @Override
-        public Drawable newDrawable() {
-            return new MipmapDrawable(this, null);
-        }
-
-        @Override
-        public Drawable newDrawable(Resources res) {
-            return new MipmapDrawable(this, res);
-        }
-
-        @Override
-        public void growArray(int oldSize, int newSize) {
-            super.growArray(oldSize, newSize);
-            int[] newInts = new int[newSize];
-            System.arraycopy(mMipmapHeights, 0, newInts, 0, oldSize);
-            mMipmapHeights = newInts;
-        }
-    }
-
-    private MipmapDrawable(MipmapContainerState state, Resources res) {
-        MipmapContainerState as = new MipmapContainerState(state, this, res);
-        mMipmapContainerState = as;
-        setConstantState(as);
-        onDrawableAdded();
-    }
-}
diff --git a/graphics/java/android/renderscript/Allocation.java b/graphics/java/android/renderscript/Allocation.java
index 3d4d40a..e1b8c6c 100644
--- a/graphics/java/android/renderscript/Allocation.java
+++ b/graphics/java/android/renderscript/Allocation.java
@@ -1736,6 +1736,9 @@
                                                       int usage) {
 
         rs.validate();
+        if ((usage & (USAGE_SHARED | USAGE_IO_INPUT | USAGE_IO_OUTPUT)) != 0) {
+            throw new RSIllegalArgumentException("Unsupported usage specified.");
+        }
         Bitmap b = BitmapFactory.decodeResource(res, id);
         Allocation alloc = createFromBitmap(rs, b, mips, usage);
         b.recycle();
@@ -1763,7 +1766,7 @@
         if (rs.getApplicationContext().getApplicationInfo().targetSdkVersion >= 18) {
             return createFromBitmapResource(rs, res, id,
                                             MipmapControl.MIPMAP_NONE,
-                                            USAGE_SHARED | USAGE_SCRIPT | USAGE_GRAPHICS_TEXTURE);
+                                            USAGE_SCRIPT | USAGE_GRAPHICS_TEXTURE);
         }
         return createFromBitmapResource(rs, res, id,
                                         MipmapControl.MIPMAP_NONE,
diff --git a/graphics/tests/graphicstests/src/android/graphics/drawable/MipmapDrawableTest.java b/graphics/tests/graphicstests/src/android/graphics/drawable/MipmapDrawableTest.java
deleted file mode 100644
index 5fcc3bc..0000000
--- a/graphics/tests/graphicstests/src/android/graphics/drawable/MipmapDrawableTest.java
+++ /dev/null
@@ -1,280 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.graphics.drawable;
-
-import android.graphics.Canvas;
-import android.graphics.ColorFilter;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.MipmapDrawable;
-import android.graphics.drawable.DrawableContainer.DrawableContainerState;
-import android.test.InstrumentationTestCase;
-
-public class MipmapDrawableTest extends InstrumentationTestCase {
-    private MockMipmapDrawable mMipmapDrawable;
-
-    private DrawableContainerState mDrawableContainerState;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        mMipmapDrawable = new MockMipmapDrawable();
-        mDrawableContainerState = (DrawableContainerState) mMipmapDrawable.getConstantState();
-    }
-
-    public void testMipmapDrawable() {
-        new MipmapDrawable();
-        // Check the values set in the constructor
-        assertNotNull(new MipmapDrawable().getConstantState());
-        assertTrue(new MockMipmapDrawable().hasCalledOnBoundsChanged());
-    }
-
-    public void testAddDrawable() {
-        assertEquals(0, mDrawableContainerState.getChildCount());
-
-        // nothing happens if drawable is null
-        mMipmapDrawable.reset();
-        mMipmapDrawable.addDrawable(null);
-        assertEquals(0, mDrawableContainerState.getChildCount());
-        assertFalse(mMipmapDrawable.hasCalledOnBoundsChanged());
-
-        mMipmapDrawable.reset();
-        mMipmapDrawable.addDrawable(new MockDrawable());
-        assertEquals(1, mDrawableContainerState.getChildCount());
-        assertTrue(mMipmapDrawable.hasCalledOnBoundsChanged());
-
-        mMipmapDrawable.reset();
-        mMipmapDrawable.addDrawable(new MockDrawable());
-        assertEquals(2, mDrawableContainerState.getChildCount());
-        assertTrue(mMipmapDrawable.hasCalledOnBoundsChanged());
-    }
-
-    public void testSortedByHeight() {
-        Drawable small = new MockDrawable(8);
-        Drawable medium = new MockDrawable(32);
-        Drawable large = new MockDrawable(128);
-
-        mMipmapDrawable.addDrawable(medium);
-        assertSame(medium, mDrawableContainerState.getChildren()[0]);
-
-        mMipmapDrawable.addDrawable(small);
-        assertSame(small, mDrawableContainerState.getChildren()[0]);
-        assertSame(medium, mDrawableContainerState.getChildren()[1]);
-
-        mMipmapDrawable.addDrawable(large);
-        assertSame(small, mDrawableContainerState.getChildren()[0]);
-        assertSame(medium, mDrawableContainerState.getChildren()[1]);
-        assertSame(large, mDrawableContainerState.getChildren()[2]);
-
-        mMipmapDrawable.addDrawable(small);
-        assertSame(small, mDrawableContainerState.getChildren()[0]);
-        assertSame(small, mDrawableContainerState.getChildren()[1]);
-        assertSame(medium, mDrawableContainerState.getChildren()[2]);
-        assertSame(large, mDrawableContainerState.getChildren()[3]);
-
-        mMipmapDrawable.addDrawable(medium);
-        assertSame(small, mDrawableContainerState.getChildren()[0]);
-        assertSame(small, mDrawableContainerState.getChildren()[1]);
-        assertSame(medium, mDrawableContainerState.getChildren()[2]);
-        assertSame(medium, mDrawableContainerState.getChildren()[3]);
-        assertSame(large, mDrawableContainerState.getChildren()[4]);
-
-        mMipmapDrawable.addDrawable(large);
-        assertSame(small, mDrawableContainerState.getChildren()[0]);
-        assertSame(small, mDrawableContainerState.getChildren()[1]);
-        assertSame(medium, mDrawableContainerState.getChildren()[2]);
-        assertSame(medium, mDrawableContainerState.getChildren()[3]);
-        assertSame(large, mDrawableContainerState.getChildren()[4]);
-        assertSame(large, mDrawableContainerState.getChildren()[5]);
-    }
-
-    public void testSetBoundsOneItem() {
-        // the method is not called if same bounds are set
-        mMipmapDrawable.reset();
-        mMipmapDrawable.setBounds(mMipmapDrawable.getBounds());
-        assertFalse(mMipmapDrawable.hasCalledOnBoundsChanged());
-
-        // the method is called if different bounds are set, even without drawables
-        mMipmapDrawable.reset();
-        mMipmapDrawable.setBounds(new Rect(0, 0, 0, mMipmapDrawable.getBounds().height() + 1));
-        assertTrue(mMipmapDrawable.hasCalledOnBoundsChanged());
-
-        // adding an item should check bounds to see if new drawable is more appropriate
-        mMipmapDrawable.reset();
-        Drawable item = new MockDrawable(42);
-        mMipmapDrawable.addDrawable(item);
-        assertTrue(mMipmapDrawable.hasCalledOnBoundsChanged());
-
-        // the method is called if different bounds are set
-        mMipmapDrawable.setBounds(new Rect(0, 0, 0, mMipmapDrawable.getBounds().height() + 1));
-        assertTrue(mMipmapDrawable.hasCalledOnBoundsChanged());
-
-        // check that correct drawable is selected for any size.
-        mMipmapDrawable.setBounds(new Rect(0, 0, 0, item.getIntrinsicHeight() - 1));
-        assertSame(item, mMipmapDrawable.getCurrent());
-
-        mMipmapDrawable.setBounds(new Rect(0, 0, 0, item.getIntrinsicHeight()));
-        assertSame(item, mMipmapDrawable.getCurrent());
-
-        mMipmapDrawable.setBounds(new Rect(0, 0, 0, item.getIntrinsicHeight() + 1));
-        assertSame(item, mMipmapDrawable.getCurrent());
-    }
-
-    public void testSetBounds() {
-        Drawable small = new MockDrawable(8);
-        Drawable medium = new MockDrawable(32);
-        Drawable large = new MockDrawable(128);
-
-        mMipmapDrawable.addDrawable(large);
-        mMipmapDrawable.addDrawable(small);
-        mMipmapDrawable.addDrawable(medium);
-
-        // check that correct drawable is selected.
-        mMipmapDrawable.setBounds(new Rect(0, 0, 0, small.getIntrinsicHeight() - 1));
-        assertSame(small, mMipmapDrawable.getCurrent());
-
-        mMipmapDrawable.setBounds(new Rect(0, 0, 0, small.getIntrinsicHeight()));
-        assertSame(small, mMipmapDrawable.getCurrent());
-
-        mMipmapDrawable.setBounds(new Rect(0, 0, 0, small.getIntrinsicHeight() + 1));
-        assertSame(medium, mMipmapDrawable.getCurrent());
-
-        mMipmapDrawable.setBounds(new Rect(0, 0, 0, medium.getIntrinsicHeight() - 1));
-        assertSame(medium, mMipmapDrawable.getCurrent());
-
-        mMipmapDrawable.setBounds(new Rect(0, 0, 0, medium.getIntrinsicHeight()));
-        assertSame(medium, mMipmapDrawable.getCurrent());
-
-        mMipmapDrawable.setBounds(new Rect(0, 0, 0, medium.getIntrinsicHeight() + 1));
-        assertSame(large, mMipmapDrawable.getCurrent());
-
-        mMipmapDrawable.setBounds(new Rect(0, 0, 0, large.getIntrinsicHeight() - 1));
-        assertSame(large, mMipmapDrawable.getCurrent());
-
-        mMipmapDrawable.setBounds(new Rect(0, 0, 0, large.getIntrinsicHeight()));
-        assertSame(large, mMipmapDrawable.getCurrent());
-
-        mMipmapDrawable.setBounds(new Rect(0, 0, 0, large.getIntrinsicHeight() + 1));
-        assertSame(large, mMipmapDrawable.getCurrent());
-    }
-
-    public void testSizes() {
-        // Check default value with no mipmap defined
-        assertEquals(-1, mMipmapDrawable.getIntrinsicHeight());
-        assertEquals(-1, mMipmapDrawable.getIntrinsicWidth());
-        assertEquals(0, mMipmapDrawable.getMinimumHeight());
-        assertEquals(0, mMipmapDrawable.getMinimumWidth());
-
-        Drawable small = new MockDrawable(8, 4);
-        Drawable medium = new MockDrawable(32, 16);
-        Drawable large = new MockDrawable(128, 64);
-
-        mMipmapDrawable.addDrawable(medium);
-        assertEquals(medium.getIntrinsicHeight(), mMipmapDrawable.getIntrinsicHeight());
-        assertEquals(medium.getMinimumHeight(), mMipmapDrawable.getMinimumHeight());
-
-        mMipmapDrawable.addDrawable(large);
-        assertEquals(large.getIntrinsicHeight(), mMipmapDrawable.getIntrinsicHeight());
-        assertEquals(medium.getMinimumHeight(), mMipmapDrawable.getMinimumHeight());
-
-        mMipmapDrawable.addDrawable(small);
-        assertEquals(large.getIntrinsicHeight(), mMipmapDrawable.getIntrinsicHeight());
-        assertEquals(small.getMinimumHeight(), mMipmapDrawable.getMinimumHeight());
-    }
-
-    public void testReplacementWhenAdded() {
-        Drawable small = new MockDrawable(8);
-        Drawable medium = new MockDrawable(32);
-        Drawable large = new MockDrawable(128);
-
-        // Small bounds, so that the smallest mipmap should always be selected
-        mMipmapDrawable.setBounds(new Rect(0, 0, 0, 0));
-
-        // Providing smaller versions, that should immediately be used as current
-        mMipmapDrawable.addDrawable(large);
-        assertSame(large, mMipmapDrawable.getCurrent());
-
-        mMipmapDrawable.addDrawable(medium);
-        assertSame(medium, mMipmapDrawable.getCurrent());
-
-        mMipmapDrawable.addDrawable(small);
-        assertSame(small, mMipmapDrawable.getCurrent());
-    }
-
-    private class MockMipmapDrawable extends MipmapDrawable {
-        private boolean mHasCalledOnBoundsChanged;
-
-        public boolean hasCalledOnBoundsChanged() {
-            return mHasCalledOnBoundsChanged;
-        }
-
-        public void reset() {
-            mHasCalledOnBoundsChanged = false;
-        }
-
-        @Override
-        protected void onBoundsChange(Rect bounds) {
-            super.onBoundsChange(bounds);
-            mHasCalledOnBoundsChanged = true;
-        }
-    }
-
-    private class MockDrawable extends Drawable {
-        int mIntrinsicHeight;
-        int mMinimumHeight;
-
-        public MockDrawable() {
-            this(0);
-        }
-
-        public MockDrawable(int intrinsicHeight) {
-            this(intrinsicHeight, intrinsicHeight);
-        }
-
-        public MockDrawable(int intrinsicHeight, int minimumHeight) {
-            mIntrinsicHeight = intrinsicHeight;
-            mMinimumHeight = minimumHeight;
-        }
-
-        @Override
-        public void draw(Canvas canvas) {
-        }
-
-        @Override
-        public int getOpacity() {
-            return 0;
-        }
-
-        @Override
-        public void setAlpha(int alpha) {
-        }
-
-        @Override
-        public void setColorFilter(ColorFilter cf) {
-        }
-
-        @Override
-        public int getIntrinsicHeight() {
-            return mIntrinsicHeight;
-        }
-
-        @Override
-        public int getMinimumHeight() {
-            return mMinimumHeight;
-        }
-    }
-}
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index 33ba229..9e13ca4 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -71,7 +71,9 @@
 import android.text.TextUtils;
 import android.util.Log;
 import android.view.KeyEvent;
+import android.view.Surface;
 import android.view.VolumePanel;
+import android.view.WindowManager;
 
 import com.android.internal.telephony.ITelephony;
 import com.android.internal.util.XmlUtils;
@@ -431,6 +433,7 @@
     private volatile IRingtonePlayer mRingtonePlayer;
 
     private int mDeviceOrientation = Configuration.ORIENTATION_UNDEFINED;
+    private int mDeviceRotation = Surface.ROTATION_0;
 
     // Request to override default use of A2DP for media.
     private boolean mBluetoothA2dpEnabled;
@@ -452,7 +455,9 @@
             AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET |
             AudioSystem.DEVICE_OUT_ALL_USB;
 
+    // TODO merge orientation and rotation
     private final boolean mMonitorOrientation;
+    private final boolean mMonitorRotation;
 
     private boolean mDockAudioMediaEnabled = true;
 
@@ -545,14 +550,21 @@
         intentFilter.addAction(Intent.ACTION_USER_SWITCHED);
 
         intentFilter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
-        // Register a configuration change listener only if requested by system properties
-        // to monitor orientation changes (off by default)
+        // TODO merge orientation and rotation
         mMonitorOrientation = SystemProperties.getBoolean("ro.audio.monitorOrientation", false);
         if (mMonitorOrientation) {
             Log.v(TAG, "monitoring device orientation");
             // initialize orientation in AudioSystem
             setOrientationForAudioSystem();
         }
+        mMonitorRotation = SystemProperties.getBoolean("ro.audio.monitorRotation", false);
+        if (mMonitorRotation) {
+            mDeviceRotation = ((WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE))
+                    .getDefaultDisplay().getRotation();
+            Log.v(TAG, "monitoring device rotation, initial=" + mDeviceRotation);
+            // initialize rotation in AudioSystem
+            setRotationForAudioSystem();
+        }
 
         context.registerReceiver(mReceiver, intentFilter);
 
@@ -3497,6 +3509,9 @@
                     if (mMonitorOrientation) {
                         setOrientationForAudioSystem();
                     }
+                    if (mMonitorRotation) {
+                        setRotationForAudioSystem();
+                    }
 
                     synchronized (mBluetoothA2dpEnabledLock) {
                         AudioSystem.setForceUse(AudioSystem.FOR_MEDIA,
@@ -6375,15 +6390,17 @@
     // Device orientation
     //==========================================================================================
     /**
-     * Handles device configuration changes that may map to a change in the orientation.
-     * This feature is optional, and is defined by the definition and value of the
-     * "ro.audio.monitorOrientation" system property.
+     * Handles device configuration changes that may map to a change in the orientation
+     * or orientation.
+     * Monitoring orientation and rotation is optional, and is defined by the definition and value
+     * of the "ro.audio.monitorOrientation" and "ro.audio.monitorRotation" system properties.
      */
     private void handleConfigurationChanged(Context context) {
         try {
             // reading new orientation "safely" (i.e. under try catch) in case anything
             // goes wrong when obtaining resources and configuration
             Configuration config = context.getResources().getConfiguration();
+            // TODO merge rotation and orientation
             if (mMonitorOrientation) {
                 int newOrientation = config.orientation;
                 if (newOrientation != mDeviceOrientation) {
@@ -6391,6 +6408,14 @@
                     setOrientationForAudioSystem();
                 }
             }
+            if (mMonitorRotation) {
+                int newRotation = ((WindowManager) context.getSystemService(
+                        Context.WINDOW_SERVICE)).getDefaultDisplay().getRotation();
+                if (newRotation != mDeviceRotation) {
+                    mDeviceRotation = newRotation;
+                    setRotationForAudioSystem();
+                }
+            }
             sendMsg(mAudioHandler,
                     MSG_CONFIGURE_SAFE_MEDIA_VOLUME,
                     SENDMSG_REPLACE,
@@ -6439,7 +6464,7 @@
             }
             mVolumePanel.setLayoutDirection(config.getLayoutDirection());
         } catch (Exception e) {
-            Log.e(TAG, "Error retrieving device orientation: " + e);
+            Log.e(TAG, "Error handling configuration change: ", e);
         }
     }
 
@@ -6466,6 +6491,25 @@
         }
     }
 
+    private void setRotationForAudioSystem() {
+        switch (mDeviceRotation) {
+            case Surface.ROTATION_0:
+                AudioSystem.setParameters("rotation=0");
+                break;
+            case Surface.ROTATION_90:
+                AudioSystem.setParameters("rotation=90");
+                break;
+            case Surface.ROTATION_180:
+                AudioSystem.setParameters("rotation=180");
+                break;
+            case Surface.ROTATION_270:
+                AudioSystem.setParameters("rotation=270");
+                break;
+            default:
+                Log.e(TAG, "Unknown device rotation");
+        }
+    }
+
 
     // Handles request to override default use of A2DP for media.
     public void setBluetoothA2dpOnInt(boolean on) {
diff --git a/media/java/android/media/MediaMuxer.java b/media/java/android/media/MediaMuxer.java
index c0fbd2e..774964e 100644
--- a/media/java/android/media/MediaMuxer.java
+++ b/media/java/android/media/MediaMuxer.java
@@ -35,20 +35,29 @@
  * It is generally used like this:
  *
  * <pre>
- * MediaMuxer muxer = new MediaMuxer(...);
+ * MediaMuxer muxer = new MediaMuxer("temp.mp4", OutputFormat.MUXER_OUTPUT_MPEG_4);
+ * // More often, the MediaFormat will be retrieved from MediaCodec.getOutputFormat()
+ * // or MediaExtractor.getTrackFormat().
  * MediaFormat audioFormat = new MediaFormat(...);
  * MediaFormat videoFormat = new MediaFormat(...);
  * int audioTrackIndex = muxer.addTrack(audioFormat);
  * int videoTrackIndex = muxer.addTrack(videoFormat);
- * ByteBuffer inputBuffer = ByteBuffer.allocate(...);
+ * ByteBuffer inputBuffer = ByteBuffer.allocate(bufferSize);
+ * boolean finished = false;
+ * BufferInfo bufferInfo = new BufferInfo();
+ *
  * muxer.start();
- * while(inputBuffer has new data) {
- *   if (new data is audio sample) {
- *     muxer.writeSampleData(audioTrackIndex, inputBuffer, ...);
- *   } else if (new data is video sample) {
- *     muxer.writeSampleData(videoTrackIndex, inputBuffer, ...);
+ * while(!finished) {
+ *   // getInputBuffer() will fill the inputBuffer with one frame of encoded
+ *   // sample from either MediaCodec or MediaExtractor, set isAudioSample to
+ *   // true when the sample is audio data, set up all the fields of bufferInfo,
+ *   // and return true if there are no more samples.
+ *   finished = getInputBuffer(inputBuffer, isAudioSample, bufferInfo);
+ *   if (!finished) {
+ *     int currentTrackIndex = isAudioSample ? audioTrackIndex : videoTrackIndex;
+ *     muxer.writeSampleData(currentTrackIndex, inputBuffer, bufferInfo);
  *   }
- * }
+ * };
  * muxer.stop();
  * muxer.release();
  * </pre>
@@ -74,16 +83,6 @@
         public static final int MUXER_OUTPUT_MPEG_4 = 0;
     };
 
-    /**
-     * The sample is a sync sample, which does not require other video samples
-     * to decode. This flag is used in {@link #writeSampleData} to indicate
-     * which sample is a sync sample.
-     */
-    /* Keep this flag in sync with its equivalent in
-     * include/media/stagefright/MediaMuxer.h.
-     */
-    public static final int SAMPLE_FLAG_SYNC = 1;
-
     // All the native functions are listed here.
     private static native int nativeSetup(FileDescriptor fd, int format);
     private static native void nativeRelease(int nativeObject);
@@ -260,10 +259,13 @@
      * Writes an encoded sample into the muxer.
      * <p>The application needs to make sure that the samples are written into
      * the right tracks. Also, it needs to make sure the samples for each track
-     * are written in chronological order.</p>
+     * are written in chronological order (e.g. in the order they are provided
+     * by the encoder.)</p>
      * @param byteBuf The encoded sample.
      * @param trackIndex The track index for this sample.
      * @param bufferInfo The buffer information related to this sample.
+     * MediaMuxer uses the flags provided in {@link MediaCodec.BufferInfo},
+     * to signal sync frames.
      */
     public void writeSampleData(int trackIndex, ByteBuffer byteBuf,
             BufferInfo bufferInfo) {
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index f745163..b729640 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -16,9 +16,14 @@
 
 package android.media;
 
+import android.content.BroadcastReceiver;
 import android.content.ContentResolver;
 import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
 import android.content.res.AssetFileDescriptor;
+import android.net.Proxy;
+import android.net.ProxyProperties;
 import android.net.Uri;
 import android.os.Handler;
 import android.os.Looper;
@@ -864,6 +869,7 @@
      */
     public void setDataSource(Context context, Uri uri, Map<String, String> headers)
         throws IOException, IllegalArgumentException, SecurityException, IllegalStateException {
+        disableProxyListener();
 
         String scheme = uri.getScheme();
         if(scheme == null || scheme.equals("file")) {
@@ -896,8 +902,13 @@
         }
 
         Log.d(TAG, "Couldn't open file on client side, trying server side");
+
         setDataSource(uri.toString(), headers);
-        return;
+
+        if (scheme.equalsIgnoreCase("http")
+                || scheme.equalsIgnoreCase("https")) {
+            setupProxyListener(context);
+        }
     }
 
     /**
@@ -948,6 +959,8 @@
 
     private void setDataSource(String path, String[] keys, String[] values)
             throws IOException, IllegalArgumentException, SecurityException, IllegalStateException {
+        disableProxyListener();
+
         final Uri uri = Uri.parse(path);
         if ("file".equals(uri.getScheme())) {
             path = uri.getPath();
@@ -991,7 +1004,13 @@
      * @param length the length in bytes of the data to be played
      * @throws IllegalStateException if it is called in an invalid state
      */
-    public native void setDataSource(FileDescriptor fd, long offset, long length)
+    public void setDataSource(FileDescriptor fd, long offset, long length)
+            throws IOException, IllegalArgumentException, IllegalStateException {
+        disableProxyListener();
+        _setDataSource(fd, offset, length);
+    }
+
+    private native void _setDataSource(FileDescriptor fd, long offset, long length)
             throws IOException, IllegalArgumentException, IllegalStateException;
 
     /**
@@ -1332,6 +1351,8 @@
         _reset();
         // make sure none of the listeners get called anymore
         mEventHandler.removeCallbacksAndMessages(null);
+
+        disableProxyListener();
     }
 
     private native void _reset();
@@ -2449,4 +2470,57 @@
         return (mode == VIDEO_SCALING_MODE_SCALE_TO_FIT ||
                 mode == VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING);
     }
+
+    private Context mProxyContext = null;
+    private ProxyReceiver mProxyReceiver = null;
+
+    private void setupProxyListener(Context context) {
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(Proxy.PROXY_CHANGE_ACTION);
+        mProxyReceiver = new ProxyReceiver();
+        mProxyContext = context;
+
+        Intent currentProxy =
+            context.getApplicationContext().registerReceiver(mProxyReceiver, filter);
+
+        if (currentProxy != null) {
+            handleProxyBroadcast(currentProxy);
+        }
+    }
+
+    private void disableProxyListener() {
+        if (mProxyReceiver == null) {
+            return;
+        }
+
+        Context appContext = mProxyContext.getApplicationContext();
+        if (appContext != null) {
+            appContext.unregisterReceiver(mProxyReceiver);
+        }
+
+        mProxyReceiver = null;
+        mProxyContext = null;
+    }
+
+    private void handleProxyBroadcast(Intent intent) {
+        ProxyProperties props =
+            (ProxyProperties)intent.getExtra(Proxy.EXTRA_PROXY_INFO);
+
+        if (props == null || props.getHost() == null) {
+            updateProxyConfig(null);
+        } else {
+            updateProxyConfig(props);
+        }
+    }
+
+    private class ProxyReceiver extends BroadcastReceiver {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (intent.getAction().equals(Proxy.PROXY_CHANGE_ACTION)) {
+                handleProxyBroadcast(intent);
+            }
+        }
+    }
+
+    private native void updateProxyConfig(ProxyProperties props);
 }
diff --git a/media/java/android/media/MediaRouter.java b/media/java/android/media/MediaRouter.java
index e6693b9..d653d94 100644
--- a/media/java/android/media/MediaRouter.java
+++ b/media/java/android/media/MediaRouter.java
@@ -231,7 +231,7 @@
             final int count = mCallbacks.size();
             for (int i = 0; i < count; i++) {
                 CallbackInfo cbi = mCallbacks.get(i);
-                if ((cbi.flags & CALLBACK_FLAG_ACTIVE_SCAN) != 0
+                if ((cbi.flags & CALLBACK_FLAG_PERFORM_ACTIVE_SCAN) != 0
                         && (cbi.type & type) != 0) {
                     return true;
                 }
@@ -330,7 +330,7 @@
      * discover and select a new route.
      * </p>
      */
-    public static final int CALLBACK_FLAG_ACTIVE_SCAN = 1 << 0;
+    public static final int CALLBACK_FLAG_PERFORM_ACTIVE_SCAN = 1 << 0;
 
     /**
      * Flag for {@link #addCallback}: Do not filter route events.
@@ -439,7 +439,7 @@
      * @param types Types of routes this callback is interested in
      * @param cb Callback to add
      * @param flags Flags to control the behavior of the callback.
-     * May be zero or a combination of {@link #CALLBACK_FLAG_ACTIVE_SCAN} and
+     * May be zero or a combination of {@link #CALLBACK_FLAG_PERFORM_ACTIVE_SCAN} and
      * {@link #CALLBACK_FLAG_UNFILTERED_EVENTS}.
      */
     public void addCallback(int types, Callback cb, int flags) {
@@ -453,7 +453,7 @@
             info = new CallbackInfo(cb, types, flags, this);
             sStatic.mCallbacks.add(info);
         }
-        if ((info.flags & CALLBACK_FLAG_ACTIVE_SCAN) != 0) {
+        if ((info.flags & CALLBACK_FLAG_PERFORM_ACTIVE_SCAN) != 0) {
             sStatic.updateActiveScan();
         }
     }
@@ -467,7 +467,7 @@
         int index = findCallbackInfo(cb);
         if (index >= 0) {
             CallbackInfo info = sStatic.mCallbacks.remove(index);
-            if ((info.flags & CALLBACK_FLAG_ACTIVE_SCAN) != 0) {
+            if ((info.flags & CALLBACK_FLAG_PERFORM_ACTIVE_SCAN) != 0) {
                 sStatic.updateActiveScan();
             }
         } else {
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index c5098ce..7c607ea 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -55,6 +55,10 @@
     jfieldID    surface_texture;
 
     jmethodID   post_event;
+
+    jmethodID   proxyConfigGetHost;
+    jmethodID   proxyConfigGetPort;
+    jmethodID   proxyConfigGetExclusionList;
 };
 static fields_t fields;
 
@@ -622,6 +626,20 @@
     if (fields.surface_texture == NULL) {
         return;
     }
+
+    clazz = env->FindClass("android/net/ProxyProperties");
+    if (clazz == NULL) {
+        return;
+    }
+
+    fields.proxyConfigGetHost =
+        env->GetMethodID(clazz, "getHost", "()Ljava/lang/String;");
+
+    fields.proxyConfigGetPort =
+        env->GetMethodID(clazz, "getPort", "()I");
+
+    fields.proxyConfigGetExclusionList =
+        env->GetMethodID(clazz, "getExclusionList", "()Ljava/lang/String;");
 }
 
 static void
@@ -823,6 +841,49 @@
     ;
 }
 
+static void
+android_media_MediaPlayer_updateProxyConfig(
+        JNIEnv *env, jobject thiz, jobject proxyProps)
+{
+    ALOGV("updateProxyConfig");
+    sp<MediaPlayer> thisplayer = getMediaPlayer(env, thiz);
+    if (thisplayer == NULL) {
+        return;
+    }
+
+    if (proxyProps == NULL) {
+        thisplayer->updateProxyConfig(
+                NULL /* host */, 0 /* port */, NULL /* exclusionList */);
+    } else {
+        jstring hostObj = (jstring)env->CallObjectMethod(
+                proxyProps, fields.proxyConfigGetHost);
+
+        const char *host = env->GetStringUTFChars(hostObj, NULL);
+
+        int port = env->CallIntMethod(proxyProps, fields.proxyConfigGetPort);
+
+        jstring exclusionListObj = (jstring)env->CallObjectMethod(
+                proxyProps, fields.proxyConfigGetExclusionList);
+
+        const char *exclusionList =
+            env->GetStringUTFChars(exclusionListObj, NULL);
+
+        if (host != NULL && exclusionListObj != NULL) {
+            thisplayer->updateProxyConfig(host, port, exclusionList);
+        }
+
+        if (exclusionList != NULL) {
+            env->ReleaseStringUTFChars(exclusionListObj, exclusionList);
+            exclusionList = NULL;
+        }
+
+        if (host != NULL) {
+            env->ReleaseStringUTFChars(hostObj, host);
+            host = NULL;
+        }
+    }
+}
+
 // ----------------------------------------------------------------------------
 
 static JNINativeMethod gMethods[] = {
@@ -832,7 +893,7 @@
         (void *)android_media_MediaPlayer_setDataSourceAndHeaders
     },
 
-    {"setDataSource",       "(Ljava/io/FileDescriptor;JJ)V",    (void *)android_media_MediaPlayer_setDataSourceFD},
+    {"_setDataSource",       "(Ljava/io/FileDescriptor;JJ)V",    (void *)android_media_MediaPlayer_setDataSourceFD},
     {"_setVideoSurface",    "(Landroid/view/Surface;)V",        (void *)android_media_MediaPlayer_setVideoSurface},
     {"prepare",             "()V",                              (void *)android_media_MediaPlayer_prepare},
     {"prepareAsync",        "()V",                              (void *)android_media_MediaPlayer_prepareAsync},
@@ -867,6 +928,7 @@
     {"getParameter",        "(ILandroid/os/Parcel;)V",          (void *)android_media_MediaPlayer_getParameter},
     {"native_setRetransmitEndpoint", "(Ljava/lang/String;I)I",  (void *)android_media_MediaPlayer_setRetransmitEndpoint},
     {"setNextMediaPlayer",  "(Landroid/media/MediaPlayer;)V",   (void *)android_media_MediaPlayer_setNextMediaPlayer},
+    {"updateProxyConfig", "(Landroid/net/ProxyProperties;)V", (void *)android_media_MediaPlayer_updateProxyConfig},
 };
 
 static const char* const kClassPathName = "android/media/MediaPlayer";
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/CameraStressTestRunner.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/CameraStressTestRunner.java
index fa59fa4..23b9705 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/CameraStressTestRunner.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/CameraStressTestRunner.java
@@ -19,6 +19,8 @@
 import android.test.InstrumentationTestRunner;
 import android.test.InstrumentationTestSuite;
 import com.android.mediaframeworktest.stress.CameraStressTest;
+import com.android.mediaframeworktest.functional.camera.CameraFunctionalTest;
+import com.android.mediaframeworktest.functional.camera.CameraPairwiseTest;
 
 import junit.framework.TestSuite;
 
@@ -28,6 +30,8 @@
     public TestSuite getAllTests() {
         TestSuite suite = new InstrumentationTestSuite(this);
         suite.addTestSuite(CameraStressTest.class);
+        suite.addTestSuite(CameraFunctionalTest.class);
+        suite.addTestSuite(CameraPairwiseTest.class);
         return suite;
     }
 
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/CameraTestHelper.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/CameraTestHelper.java
new file mode 100644
index 0000000..8bf741c
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/CameraTestHelper.java
@@ -0,0 +1,165 @@
+/*
+ * 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.mediaframeworktest;
+
+import android.hardware.Camera;
+import android.hardware.Camera.Parameters;
+import android.hardware.Camera.PictureCallback;
+import android.hardware.Camera.ShutterCallback;
+import android.os.Environment;
+import android.util.Log;
+import android.view.SurfaceHolder;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FilenameFilter;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import junit.framework.Assert;
+
+public class CameraTestHelper {
+
+    public Camera mCamera;
+    private String TAG = "CameraTestHelper";
+    private static final int CAMERA_ID = 0;
+    private static final long WAIT_GENERIC = 3 * 1000; // 3 seconds
+    private static final long WAIT_ZOOM_ANIMATION = 5 * 1000; // 5 seconds
+    protected static final String CAMERA_STRESS_IMAGES_DIRECTORY = "cameraStressImages";
+    private static final String CAMERA_STRESS_IMAGES_PREFIX = "camera-stress-test";
+    private final CameraErrorCallback mCameraErrorCallback = new CameraErrorCallback();
+
+    private final class CameraErrorCallback implements android.hardware.Camera.ErrorCallback {
+        public void onError(int error, android.hardware.Camera camera) {
+            Assert.fail(String.format("Camera error, code: %d", error));
+        }
+    }
+
+    private ShutterCallback shutterCallback = new ShutterCallback() {
+        @Override
+        public void onShutter() {
+            Log.v(TAG, "Shutter");
+        }
+    };
+
+    private PictureCallback rawCallback = new PictureCallback() {
+        @Override
+        public void onPictureTaken(byte[] data, Camera camera) {
+            Log.v(TAG, "Raw picture taken");
+        }
+    };
+
+    private PictureCallback jpegCallback = new PictureCallback() {
+        @Override
+        public void onPictureTaken(byte[] data, Camera camera) {
+            FileOutputStream fos = null;
+
+            try {
+                Log.v(TAG, "JPEG picture taken");
+                fos = new FileOutputStream(String.format("%s/%s/%s-%d.jpg",
+                        Environment.getExternalStorageDirectory(), CAMERA_STRESS_IMAGES_DIRECTORY,
+                        CAMERA_STRESS_IMAGES_PREFIX, System.currentTimeMillis()));
+                fos.write(data);
+            } catch (FileNotFoundException e) {
+                Log.e(TAG, "File not found: " + e.toString());
+            } catch (IOException e) {
+                Log.e(TAG, "Error accessing file: " + e.toString());
+            } finally {
+                try {
+                    if (fos != null) {
+                        fos.close();
+                    }
+                } catch (IOException e) {
+                    Log.e(TAG, "Error closing file: " + e.toString());
+                }
+            }
+        }
+    };
+
+    /**
+     * Helper method for prepping test
+     */
+    public void setupCameraTest() {
+        // Create the test images directory if it doesn't exist
+        File stressImagesDirectory = new File(String.format("%s/%s",
+                Environment.getExternalStorageDirectory(), CAMERA_STRESS_IMAGES_DIRECTORY));
+        if (!stressImagesDirectory.exists()) {
+            stressImagesDirectory.mkdir();
+        }
+
+        mCamera = Camera.open(CAMERA_ID);
+    }
+
+    /**
+     * Helper method for getting the available parameters of the default camera
+     */
+    public Parameters getCameraParameters() {
+        mCamera = Camera.open(CAMERA_ID);
+        Parameters params = mCamera.getParameters();
+        mCamera.release();
+        return params;
+    }
+
+    /**
+     * Helper method for taking a photo
+     */
+    public void capturePhoto() throws Exception {
+        mCamera.takePicture(shutterCallback, rawCallback, jpegCallback);
+        Thread.sleep(WAIT_GENERIC);
+        mCamera.stopPreview();
+        mCamera.release();
+    }
+
+    /**
+     * Helper method for cleaning up pics taken during tests
+     */
+    public void cleanupTestImages() {
+        try {
+            File stressImagesDirectory = new File(String.format("%s/%s",
+                    Environment.getExternalStorageDirectory(), CAMERA_STRESS_IMAGES_DIRECTORY));
+            File[] stressImages = stressImagesDirectory.listFiles();
+            for (File f : stressImages) {
+                f.delete();
+            }
+        } catch (SecurityException e) {
+            Log.e(TAG, "Security manager access violation: " + e.toString());
+        }
+    }
+
+    /**
+     * Helper method for setting the camera parameters
+     */
+    public void setParameters(Parameters params) {
+        try {
+            mCamera.setParameters(params);
+        } catch (Exception e) {
+            Log.e(TAG, "Error setting camera parameters");
+        }
+    }
+
+    /**
+     * Helper method for starting up the camera preview
+     */
+    public void startCameraPreview(SurfaceHolder surfaceHolder) throws Exception {
+        mCamera.setErrorCallback(mCameraErrorCallback);
+        mCamera.setPreviewDisplay(surfaceHolder);
+        mCamera.startPreview();
+        Thread.sleep(WAIT_GENERIC);
+    }
+}
+
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTest.java
index ed9bb97..10df2e6 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTest.java
@@ -48,9 +48,9 @@
 import java.io.FileDescriptor;
 import java.net.InetAddress;
 
- 
+
 public class MediaFrameworkTest extends Activity implements SurfaceHolder.Callback {
-    
+
     //public static Surface video_sf;
     public static SurfaceView mSurfaceView;
     private MediaController mMediaController;
@@ -58,10 +58,10 @@
     private MediaPlayer mpmidi;
     private MediaPlayer mpmp3;
     private String testfilepath = "/sdcard/awb.awb";
-    
+
     public static AssetFileDescriptor midiafd;
     public static AssetFileDescriptor mp3afd;
-    
+
     public static Bitmap mDestBitmap;
     public static ImageView mOverlayView;
     private SurfaceHolder mSurfaceHolder = null;
@@ -82,10 +82,10 @@
         mSurfaceHolder = mSurfaceView.getHolder();
         mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
         mSurfaceHolder.addCallback(this);
-        
+
         //Get the midi fd
         midiafd = this.getResources().openRawResourceFd(R.raw.testmidi);
-        
+
         //Get the mp3 fd
         mp3afd = this.getResources().openRawResourceFd(R.raw.testmp3);
         mOverlayView.setLayoutParams(lp);
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/camera/CameraFunctionalTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/camera/CameraFunctionalTest.java
new file mode 100644
index 0000000..e6f0aaf
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/camera/CameraFunctionalTest.java
@@ -0,0 +1,255 @@
+/*
+ * 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.mediaframeworktest.functional.camera;
+
+import com.android.mediaframeworktest.MediaFrameworkTest;
+import com.android.mediaframeworktest.CameraTestHelper;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.Writer;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import android.hardware.Camera;
+import android.hardware.Camera.Parameters;
+import android.os.Environment;
+import android.os.Handler;
+import android.os.Looper;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.util.FloatMath;
+import android.util.Log;
+import android.view.SurfaceHolder;
+import com.android.mediaframeworktest.CameraStressTestRunner;
+
+import junit.framework.Assert;
+
+/**
+ * Junit / Instrumentation test case for the following camera APIs:
+ * - flash
+ * - exposure compensation
+ * - white balance
+ * - focus mode
+ *
+ * adb shell am instrument
+ *  -e class com.android.mediaframeworktest.functional.camera.CameraFunctionalTest
+ *  -w com.android.mediaframework/.CameraStressTestRunner
+ */
+public class CameraFunctionalTest extends ActivityInstrumentationTestCase2<MediaFrameworkTest> {
+    private static final long WAIT_TIMEOUT = 10 * 1000; // 10 seconds
+    private CameraTestHelper mCameraTestHelper;
+    private Handler mHandler;
+    private Thread mLooperThread;
+    private Writer mOutput;
+
+    private String TAG = "CameraFunctionalTest";
+
+    public CameraFunctionalTest() {
+        super("com.android.mediaframeworktest", MediaFrameworkTest.class);
+    }
+
+    protected void setUp() throws Exception {
+        final Semaphore sem = new Semaphore(0);
+        mLooperThread = new Thread() {
+            @Override
+            public void run() {
+                Log.v(TAG, "starting looper");
+                Looper.prepare();
+                mHandler = new Handler();
+                sem.release();
+                Looper.loop();
+                Log.v(TAG, "quit looper");
+            }
+        };
+        mLooperThread.start();
+        if (!sem.tryAcquire(WAIT_TIMEOUT, TimeUnit.MILLISECONDS)) {
+            fail("Failed to start the looper.");
+        }
+        getActivity();
+        super.setUp();
+
+        mCameraTestHelper = new CameraTestHelper();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        if (mHandler != null) {
+            mHandler.getLooper().quit();
+            mHandler = null;
+        }
+        if (mLooperThread != null) {
+            mLooperThread.join(WAIT_TIMEOUT);
+            if (mLooperThread.isAlive()) {
+                fail("Failed to stop the looper.");
+            }
+            mLooperThread = null;
+        }
+        super.tearDown();
+    }
+
+    private void runOnLooper(final Runnable command) throws InterruptedException {
+        final Semaphore sem = new Semaphore(0);
+        mHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    command.run();
+                } finally {
+                    sem.release();
+                }
+            }
+        });
+        if (!sem.tryAcquire(WAIT_TIMEOUT, TimeUnit.MILLISECONDS)) {
+            fail("Failed to run the command on the looper.");
+        }
+    }
+
+    /**
+     * Functional test iterating on the range of supported exposure compensation levels
+     */
+    @LargeTest
+    public void testFunctionalCameraExposureCompensation() throws Exception {
+        try {
+            SurfaceHolder surfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
+            Parameters params = mCameraTestHelper.getCameraParameters();
+
+            int min = params.getMinExposureCompensation();
+            int max = params.getMaxExposureCompensation();
+            assertFalse("Adjusting exposure not supported", (max == 0 && min == 0));
+            float step = params.getExposureCompensationStep();
+            int stepsPerEV = (int) Math.round(Math.pow((double) step, -1));
+
+            // only get integer values for exposure compensation
+            for (int i = min; i <= max; i += stepsPerEV) {
+                runOnLooper(new Runnable() {
+                    @Override
+                    public void run() {
+                        mCameraTestHelper.setupCameraTest();
+                    }
+                });
+                Log.v(TAG, "Setting exposure compensation index to " + i);
+                params.setExposureCompensation(i);
+                mCameraTestHelper.setParameters(params);
+                mCameraTestHelper.startCameraPreview(surfaceHolder);
+                mCameraTestHelper.capturePhoto();
+            }
+            mCameraTestHelper.cleanupTestImages();
+        } catch (Exception e) {
+            Log.e(TAG, e.toString());
+            fail("Camera exposure compensation test Exception");
+        }
+    }
+
+    /**
+     * Functional test iterating on the various flash modes (on, off, auto, torch)
+     */
+    @LargeTest
+    public void testFunctionalCameraFlashModes() throws Exception {
+        try {
+            SurfaceHolder surfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
+            Parameters params = mCameraTestHelper.getCameraParameters();
+            List<String> supportedFlashModes = params.getSupportedFlashModes();
+            assertNotNull("No flash modes supported", supportedFlashModes);
+
+            for (int i = 0; i < supportedFlashModes.size(); i++) {
+                runOnLooper(new Runnable() {
+                    @Override
+                    public void run() {
+                        mCameraTestHelper.setupCameraTest();
+                    }
+                });
+                Log.v(TAG, "Setting flash mode to " + supportedFlashModes.get(i));
+                params.setFlashMode(supportedFlashModes.get(i));
+                mCameraTestHelper.setParameters(params);
+                mCameraTestHelper.startCameraPreview(surfaceHolder);
+                mCameraTestHelper.capturePhoto();
+            }
+            mCameraTestHelper.cleanupTestImages();
+        } catch (Exception e) {
+            Log.e(TAG, e.toString());
+            fail("Camera flash mode test Exception");
+        }
+    }
+
+    /**
+     * Functional test iterating on the various focus modes (auto, infinitiy, macro, etc.)
+     */
+    @LargeTest
+    public void testFunctionalCameraFocusModes() throws Exception {
+        try {
+            SurfaceHolder surfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
+            Parameters params = mCameraTestHelper.getCameraParameters();
+            List<String> supportedFocusModes = params.getSupportedFocusModes();
+            assertNotNull("No focus modes supported", supportedFocusModes);
+
+            for (int i = 0; i < supportedFocusModes.size(); i++) {
+                runOnLooper(new Runnable() {
+                    @Override
+                    public void run() {
+                        mCameraTestHelper.setupCameraTest();
+                    }
+                });
+                Log.v(TAG, "Setting focus mode to: " + supportedFocusModes.get(i));
+                params.setFocusMode(supportedFocusModes.get(i));
+                mCameraTestHelper.setParameters(params);
+                mCameraTestHelper.startCameraPreview(surfaceHolder);
+                mCameraTestHelper.capturePhoto();
+            }
+            mCameraTestHelper.cleanupTestImages();
+        } catch (Exception e) {
+            Log.e(TAG, e.toString());
+            fail("Camera focus modes test Exception");
+        }
+    }
+
+    /**
+     * Functional test iterating on the various white balances (auto, daylight, cloudy, etc.)
+     */
+    @LargeTest
+    public void testFunctionalCameraWhiteBalance() throws Exception {
+        try {
+            SurfaceHolder surfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
+            Parameters params = mCameraTestHelper.getCameraParameters();
+            List<String> supportedWhiteBalance = params.getSupportedWhiteBalance();
+            assertNotNull("No white balance modes supported", supportedWhiteBalance);
+
+            for (int i = 0; i < supportedWhiteBalance.size(); i++) {
+                runOnLooper(new Runnable() {
+                    @Override
+                    public void run() {
+                        mCameraTestHelper.setupCameraTest();
+                    }
+                });
+                Log.v(TAG, "Setting white balance to: " + supportedWhiteBalance.get(i));
+                params.setWhiteBalance(supportedWhiteBalance.get(i));
+                mCameraTestHelper.setParameters(params);
+                mCameraTestHelper.startCameraPreview(surfaceHolder);
+                mCameraTestHelper.capturePhoto();
+            }
+            mCameraTestHelper.cleanupTestImages();
+        } catch (Exception e) {
+            Log.e(TAG, e.toString());
+            fail("Camera focus modes test Exception");
+        }
+    }
+}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/camera/CameraPairwiseTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/camera/CameraPairwiseTest.java
new file mode 100644
index 0000000..61b708a
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/camera/CameraPairwiseTest.java
@@ -0,0 +1,501 @@
+/*
+ * 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.mediaframeworktest.functional.camera;
+
+import android.hardware.Camera;
+import android.hardware.Camera.PictureCallback;
+import android.hardware.Camera.ShutterCallback;
+import android.os.Environment;
+import android.os.Handler;
+import android.os.Looper;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.util.FloatMath;
+import android.util.Log;
+import android.view.SurfaceHolder;
+
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+import java.util.List;
+
+import com.android.mediaframeworktest.MediaFrameworkTest;
+import com.android.mediaframeworktest.CameraStressTestRunner;
+import com.android.mediaframeworktest.CameraTestHelper;
+import junit.framework.Assert;
+
+/**
+ * Junit / Instrumentation test case for camera API pairwise testing
+ * Settings tested against: flash mode, exposure compensation, white balance,
+ *  scene mode, picture size, and geotagging
+ *
+ * adb shell am instrument
+ *  - e class com.android.mediaframeworktest.stress.CameraPairwiseTest
+ *  - w com.android.mediaframeworktest/.CameraStressTestRunner
+ */
+public class CameraPairwiseTest extends ActivityInstrumentationTestCase2<MediaFrameworkTest> {
+    private CameraTestHelper mCameraTestHelper;
+    private Handler mHandler;
+    private Thread mLooperThread;
+    private String TAG = "CameraPairwiseTest";
+
+    private static final long WAIT_TIMEOUT = 10 * 1000; // 10 seconds
+
+    // coordinates of the Getty Museuem in Los Angeles
+    private static final double MOCK_LATITUDE = 34.076621;
+    private static final double MOCK_LONGITUDE = -118.473215;
+
+    // camera setting enums
+    public enum Flash { ON, OFF, AUTO };
+    public enum Exposure { MIN, MAX, NONE };
+    public enum WhiteBalance { DAYLIGHT, FLUORESCENT, CLOUDY, INCANDESCENT, AUTO };
+    public enum SceneMode { SUNSET, ACTION, PARTY, NIGHT, AUTO };
+    public enum PictureSize { SMALL, MEDIUM, LARGE };
+    public enum Geotagging { ON, OFF };
+
+    public CameraPairwiseTest() {
+        super("com.android.mediaframeworktest", MediaFrameworkTest.class);
+    }
+
+    protected void setUp() throws Exception {
+        final Semaphore sem = new Semaphore(0);
+        mLooperThread = new Thread() {
+            @Override
+            public void run() {
+                Log.v(TAG, "starting looper");
+                Looper.prepare();
+                mHandler = new Handler();
+                sem.release();
+                Looper.loop();
+                Log.v(TAG, "quit looper");
+            }
+        };
+        mLooperThread.start();
+        if (!sem.tryAcquire(WAIT_TIMEOUT, TimeUnit.MILLISECONDS)) {
+            fail("Failed to start the looper.");
+        }
+        getActivity();
+        super.setUp();
+
+        mCameraTestHelper = new CameraTestHelper();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        if (mHandler != null) {
+            mHandler.getLooper().quit();
+            mHandler = null;
+        }
+        if (mLooperThread != null) {
+            mLooperThread.join(WAIT_TIMEOUT);
+            if (mLooperThread.isAlive()) {
+                fail("Failed to stop the looper.");
+            }
+            mLooperThread = null;
+        }
+        super.tearDown();
+    }
+
+    private void runOnLooper(final Runnable command) throws InterruptedException {
+        final Semaphore sem = new Semaphore(0);
+        mHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    command.run();
+                } finally {
+                    sem.release();
+                }
+            }
+        });
+        if (!sem.tryAcquire(WAIT_TIMEOUT, TimeUnit.MILLISECONDS)) {
+            fail("Failed to run the command on the looper.");
+        }
+    }
+
+    /**
+     * Flash: Auto / Exposure: None / WB: Daylight
+     * Scene: Sunset / Pic: Medium / Geo: off
+     */
+    @LargeTest
+    public void testCameraPairwiseScenario01() throws Exception {
+        genericPairwiseTestCase(Flash.AUTO, Exposure.NONE, WhiteBalance.DAYLIGHT, SceneMode.SUNSET,
+                PictureSize.MEDIUM, Geotagging.OFF);
+    }
+
+    /**
+     * Flash: On / Exposure: Min / WB: Fluorescent
+     * Scene: Auto / Pic: Large / Geo: on
+     */
+    @LargeTest
+    public void testCameraPairwiseScenario02() throws Exception {
+        genericPairwiseTestCase(Flash.ON, Exposure.MIN, WhiteBalance.FLUORESCENT, SceneMode.AUTO,
+                PictureSize.LARGE, Geotagging.ON);
+    }
+
+    /**
+     * Flash: Off / Exposure: Max / WB: Auto
+     * Scene: Night / Pic: Small / Geo: on
+     */
+    @LargeTest
+    public void testCameraPairwiseScenario03() throws Exception {
+        genericPairwiseTestCase(Flash.OFF, Exposure.MAX, WhiteBalance.AUTO, SceneMode.NIGHT,
+                PictureSize.SMALL, Geotagging.ON);
+    }
+
+    /**
+     * Flash: Off / Exposure: Max / WB: Cloudy
+     * Scene: Auto / Pic: Med / Geo: off
+     */
+    @LargeTest
+    public void testCameraPairwiseScenario04() throws Exception {
+        genericPairwiseTestCase(Flash.OFF, Exposure.MAX, WhiteBalance.CLOUDY, SceneMode.AUTO,
+                PictureSize.MEDIUM, Geotagging.OFF);
+    }
+
+    /**
+     * Flash: Auto / Exposure: Max / WB: Incandescent
+     * Scene: Auto / Pic: Large / Geo: off
+     */
+    @LargeTest
+    public void testCameraPairwiseScenario05() throws Exception {
+        genericPairwiseTestCase(Flash.AUTO, Exposure.MAX, WhiteBalance.INCANDESCENT,
+                SceneMode.AUTO, PictureSize.LARGE, Geotagging.OFF);
+    }
+
+    /**
+     * Flash: On / Exposure: None / WB: Cloudy
+     * Scene: Auto / Pic: Small / Geo: on
+     */
+    @LargeTest
+    public void testCameraPairwiseScenario06() throws Exception {
+        genericPairwiseTestCase(Flash.ON, Exposure.NONE, WhiteBalance.CLOUDY, SceneMode.AUTO,
+                PictureSize.SMALL, Geotagging.ON);
+    }
+
+    /**
+     * Flash: Auto / Exposure: Min / WB: Auto
+     * Scene: Action / Pic: Small / Geo: on
+     */
+    @LargeTest
+    public void testCameraPairwiseScenario07() throws Exception {
+        genericPairwiseTestCase(Flash.AUTO, Exposure.MIN, WhiteBalance.AUTO, SceneMode.ACTION,
+                PictureSize.SMALL, Geotagging.ON);
+    }
+
+    /**
+     * Flash: On / Exposure: Min / WB: Auto
+     * Scene: Action / Pic: Medium / Geo: off
+     */
+    @LargeTest
+    public void testCameraPairwiseScenario08() throws Exception {
+        genericPairwiseTestCase(Flash.ON, Exposure.MIN, WhiteBalance.AUTO, SceneMode.ACTION,
+                PictureSize.MEDIUM, Geotagging.OFF);
+    }
+
+    /**
+     * Flash: Off / Exposure: Min / WB: Auto
+     * Scene: Night / Pic: Large / Geo: off
+     */
+    @LargeTest
+    public void testCameraPairwiseScenario09() throws Exception {
+        genericPairwiseTestCase(Flash.OFF, Exposure.MIN, WhiteBalance.AUTO, SceneMode.NIGHT,
+                PictureSize.LARGE, Geotagging.OFF);
+    }
+
+    /**
+     * Flash: Off / Exposure: Min / WB: Daylight
+     * Scene: Sunset / Pic: Small / Geo: off
+     */
+    @LargeTest
+    public void testCameraPairwiseScenario10() throws Exception {
+        genericPairwiseTestCase(Flash.OFF, Exposure.MIN, WhiteBalance.DAYLIGHT, SceneMode.SUNSET,
+                PictureSize.SMALL, Geotagging.OFF);
+    }
+
+    /**
+     * Flash: On / Exposure: Max / WB: Daylight
+     * Scene: Sunset / Pic: Large / Geo: on
+     */
+    @LargeTest
+    public void testCameraPairwiseScenario11() throws Exception {
+        genericPairwiseTestCase(Flash.ON, Exposure.MAX, WhiteBalance.DAYLIGHT, SceneMode.SUNSET,
+                PictureSize.LARGE, Geotagging.ON);
+    }
+
+    /**
+     * Flash: Auto / Exposure: Min / WB: Cloudy
+     * Scene: Auto / Pic: Large / Geo: off
+     */
+    @LargeTest
+    public void testCameraPairwiseScenario12() throws Exception {
+        genericPairwiseTestCase(Flash.AUTO, Exposure.MIN, WhiteBalance.CLOUDY, SceneMode.AUTO,
+                PictureSize.LARGE, Geotagging.OFF);
+    }
+
+    /**
+     * Flash: Off / Exposure: None / WB: Auto
+     * Scene: Party / Pic: Medium / Geo: on
+     */
+    @LargeTest
+    public void testCameraPairwiseScenario13() throws Exception {
+        genericPairwiseTestCase(Flash.OFF, Exposure.NONE, WhiteBalance.AUTO, SceneMode.PARTY,
+                PictureSize.MEDIUM, Geotagging.ON);
+    }
+
+    /**
+     * Flash: Auto / Exposure: None / WB: Auto
+     * Scene: Night / Pic: Small / Geo: off
+     */
+    @LargeTest
+    public void testCameraPairwiseScenario14() throws Exception {
+        genericPairwiseTestCase(Flash.AUTO, Exposure.NONE, WhiteBalance.AUTO, SceneMode.NIGHT,
+                PictureSize.SMALL, Geotagging.OFF);
+    }
+
+    /**
+     * Flash: On / Exposure: None / WB: Incandescent
+     * Scene: Auto / Pic: Medium / Geo: on
+     */
+    @LargeTest
+    public void testCameraPairwiseScenario15() throws Exception {
+        genericPairwiseTestCase(Flash.ON, Exposure.NONE, WhiteBalance.INCANDESCENT, SceneMode.AUTO,
+                PictureSize.MEDIUM, Geotagging.ON);
+    }
+
+    /**
+     * Flash: Auto / Exposure: Min / WB: Auto
+     * Scene: Party / Pic: Small / Geo: off
+     */
+    @LargeTest
+    public void testCameraPairwiseScenario16() throws Exception {
+        genericPairwiseTestCase(Flash.AUTO, Exposure.MIN, WhiteBalance.AUTO, SceneMode.PARTY,
+                PictureSize.SMALL, Geotagging.OFF);
+    }
+
+    /**
+     * Flash: Off / Exposure: Min / WB: Incandescent
+     * Scene: Auto / Pic: Small / Geo: off
+     */
+    @LargeTest
+    public void testCameraPairwiseScenario17() throws Exception {
+        genericPairwiseTestCase(Flash.OFF, Exposure.MIN, WhiteBalance.INCANDESCENT, SceneMode.AUTO,
+                PictureSize.SMALL, Geotagging.OFF);
+    }
+
+    /**
+     * Flash: On / Exposure: None / WB: Auto
+     * Scene: Party / Pic: Large / Geo: off
+     */
+    @LargeTest
+    public void testCameraPairwiseScenario18() throws Exception {
+        genericPairwiseTestCase(Flash.ON, Exposure.NONE, WhiteBalance.AUTO, SceneMode.PARTY,
+                PictureSize.LARGE, Geotagging.OFF);
+    }
+
+    /**
+     * Flash Off / Exposure: None / WB: Auto
+     * Scene: Action / Pic: Large / Geo: off
+     */
+    @LargeTest
+    public void testCameraPairwiseScenario19() throws Exception {
+        genericPairwiseTestCase(Flash.OFF, Exposure.NONE, WhiteBalance.AUTO, SceneMode.ACTION,
+                PictureSize.LARGE, Geotagging.OFF);
+    }
+
+    /**
+     * Flash: Off / Exposure: Max / WB: Fluorescent
+     * Scene: Auto / Pic: Medium / Geo: Off
+     */
+    @LargeTest
+    public void testCameraPairwiseScenario20() throws Exception {
+        genericPairwiseTestCase(Flash.OFF, Exposure.MAX, WhiteBalance.FLUORESCENT, SceneMode.AUTO,
+                PictureSize.MEDIUM, Geotagging.OFF);
+    }
+
+    /**
+     * Flash: Off / Exposure: Min / WB: Auto
+     * Scene: Auto / Pic: Medium / Geo: off
+     */
+    public void testCameraPairwiseScenario21() throws Exception {
+        genericPairwiseTestCase(Flash.OFF, Exposure.MIN, WhiteBalance.AUTO, SceneMode.AUTO,
+                PictureSize.MEDIUM, Geotagging.OFF);
+    }
+
+    /**
+     * Flash: On / Exposure: Max / WB: Auto
+     * Scene: Action / Pic: Small / Geo: off
+     */
+    public void testCameraPairwiseScenario22() throws Exception {
+        genericPairwiseTestCase(Flash.ON, Exposure.MAX, WhiteBalance.AUTO, SceneMode.ACTION,
+                PictureSize.SMALL, Geotagging.OFF);
+    }
+
+    /**
+     * Flash: On / Exposure: Max / WB: Auto
+     * Scene: Night / Pic: Medium / Geo: on
+     */
+    public void testCameraPairwiseScenario23() throws Exception {
+        genericPairwiseTestCase(Flash.ON, Exposure.MAX, WhiteBalance.AUTO, SceneMode.NIGHT,
+                PictureSize.MEDIUM, Geotagging.ON);
+    }
+
+    /**
+     * Flash: Auto / Exposure: None / WB: Fluorescent
+     * Scene: Auto / Pic: Small / Geo: on
+     */
+    public void testCameraPairwiseScenario24() throws Exception {
+        genericPairwiseTestCase(Flash.AUTO, Exposure.NONE, WhiteBalance.FLUORESCENT,
+                SceneMode.AUTO, PictureSize.SMALL, Geotagging.ON);
+    }
+
+    /**
+     * Flash: Auto / Exposure: Max / WB: Daylight
+     * Scene: Auto / Pic: Medium / Geo: off
+     */
+    public void testCameraPairwiseScenario25() throws Exception {
+        genericPairwiseTestCase(Flash.AUTO, Exposure.MAX, WhiteBalance.DAYLIGHT, SceneMode.AUTO,
+                PictureSize.MEDIUM, Geotagging.OFF);
+    }
+
+    /**
+     * Flash: Auto / Exposure: Max / WB: Auto
+     * Scene: Party / Pic: Medium / Geo: on
+     */
+    public void testCameraPairwiseScenario26() throws Exception {
+        genericPairwiseTestCase(Flash.AUTO, Exposure.MAX, WhiteBalance.AUTO, SceneMode.PARTY,
+                PictureSize.MEDIUM, Geotagging.ON);
+    }
+
+    /**
+     * Generic pairwise test method
+     */
+    private void genericPairwiseTestCase(Flash flash, Exposure exposure, WhiteBalance whitebalance,
+            SceneMode scenemode, PictureSize picturesize, Geotagging geotagging) throws Exception {
+        try {
+            SurfaceHolder surfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
+            Camera.Parameters params = mCameraTestHelper.getCameraParameters();
+
+            runOnLooper(new Runnable() {
+                @Override
+                public void run() {
+                    mCameraTestHelper.setupCameraTest();
+                }
+            });
+
+            // Configure flash setting
+            switch (flash) {
+                case ON:
+                    params.setFlashMode(Camera.Parameters.FLASH_MODE_ON);
+                    break;
+                case OFF:
+                    params.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
+                    break;
+                case AUTO:
+                    params.setFlashMode(Camera.Parameters.FLASH_MODE_AUTO);
+                    break;
+            }
+
+            // Configure exposure setting
+            switch (exposure) {
+                case MIN:
+                    params.setExposureCompensation(params.getMinExposureCompensation());
+                    break;
+                case MAX:
+                    params.setExposureCompensation(params.getMaxExposureCompensation());
+                    break;
+                case NONE:
+                    params.setExposureCompensation(0);
+                    break;
+            }
+
+            // Configure white balance setting
+            switch (whitebalance) {
+                case DAYLIGHT:
+                    params.setWhiteBalance(Camera.Parameters.WHITE_BALANCE_DAYLIGHT);
+                    break;
+                case FLUORESCENT:
+                    params.setWhiteBalance(Camera.Parameters.WHITE_BALANCE_FLUORESCENT);
+                    break;
+                case INCANDESCENT:
+                    params.setWhiteBalance(Camera.Parameters.WHITE_BALANCE_INCANDESCENT);
+                    break;
+                case CLOUDY:
+                    params.setWhiteBalance(Camera.Parameters.WHITE_BALANCE_CLOUDY_DAYLIGHT);
+                    break;
+                case AUTO:
+                    params.setWhiteBalance(Camera.Parameters.WHITE_BALANCE_AUTO);
+                    break;
+            }
+
+            // Configure scene mode setting
+            switch (scenemode) {
+                case SUNSET:
+                    params.setSceneMode(Camera.Parameters.SCENE_MODE_SUNSET);
+                    break;
+                case ACTION:
+                    params.setSceneMode(Camera.Parameters.SCENE_MODE_ACTION);
+                    break;
+                case PARTY:
+                    params.setSceneMode(Camera.Parameters.SCENE_MODE_PARTY);
+                    break;
+                case NIGHT:
+                    params.setSceneMode(Camera.Parameters.SCENE_MODE_NIGHT);
+                    break;
+                case AUTO:
+                    params.setSceneMode(Camera.Parameters.SCENE_MODE_AUTO);
+                    break;
+            }
+
+            // Configure picture size setting
+            List<Camera.Size> supportedPictureSizes = params.getSupportedPictureSizes();
+            int mid = (int) Math.floor(supportedPictureSizes.size() / 2);
+            int low = supportedPictureSizes.size() - 1;
+            switch (picturesize) {
+                case SMALL:
+                    params.setPictureSize(supportedPictureSizes.get(low).width,
+                            supportedPictureSizes.get(low).height);
+                    break;
+                case MEDIUM:
+                    params.setPictureSize(supportedPictureSizes.get(mid).width,
+                            supportedPictureSizes.get(mid).height);
+                    break;
+                case LARGE:
+                    params.setPictureSize(supportedPictureSizes.get(0).width,
+                            supportedPictureSizes.get(mid).height);
+                    break;
+            }
+
+            // Configure geotagging setting
+            switch (geotagging) {
+                case ON:
+                    params.setGpsLatitude(MOCK_LATITUDE);
+                    params.setGpsLongitude(MOCK_LONGITUDE);
+                    break;
+                case OFF:
+                    break;
+            }
+
+            mCameraTestHelper.setParameters(params);
+            mCameraTestHelper.startCameraPreview(surfaceHolder);
+            mCameraTestHelper.capturePhoto();
+            mCameraTestHelper.cleanupTestImages();
+        } catch (Exception e) {
+            Log.e(TAG, e.toString());
+            fail("Test case failed");
+        }
+    }
+}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/CameraStressTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/CameraStressTest.java
index ed1d8fc..a112c73 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/CameraStressTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/CameraStressTest.java
@@ -17,13 +17,11 @@
 package com.android.mediaframeworktest.stress;
 
 import com.android.mediaframeworktest.MediaFrameworkTest;
+import com.android.mediaframeworktest.CameraTestHelper;
 
 import java.io.BufferedWriter;
 import java.io.File;
-import java.io.FilenameFilter;
 import java.io.FileWriter;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.Writer;
 import java.util.concurrent.Semaphore;
@@ -31,8 +29,7 @@
 import java.util.List;
 
 import android.hardware.Camera;
-import android.hardware.Camera.PictureCallback;
-import android.hardware.Camera.ShutterCallback;
+import android.hardware.Camera.Parameters;
 import android.os.Environment;
 import android.os.Handler;
 import android.os.Looper;
@@ -45,32 +42,28 @@
 import junit.framework.Assert;
 
 /**
- * Junit / Instrumentation test case for the camera zoom and scene mode APIs
+ * Junit / Instrumentation test case for the following camera APIs:
+ *  - camera zoom
+ *  - scene mode
  *
  * adb shell am instrument
  *  -e class com.android.mediaframeworktest.stress.CameraStressTest
  *  -w com.android.mediaframeworktest/.CameraStressTestRunner
  */
 public class CameraStressTest extends ActivityInstrumentationTestCase2<MediaFrameworkTest> {
-    private String TAG = "CameraStressTest";
-    private Camera mCamera;
 
-    private static final int CAMERA_ID = 0;
-    private static final int NUMBER_OF_ZOOM_LOOPS = 100;
     private static final int NUMBER_OF_SCENE_MODE_LOOPS = 10;
-    private static final long WAIT_GENERIC = 3 * 1000; // 3 seconds
+    private static final int NUMBER_OF_ZOOM_LOOPS = 100;
     private static final long WAIT_TIMEOUT = 10 * 1000; // 10 seconds
-    private static final long WAIT_ZOOM_ANIMATION = 5 * 1000; // 5 seconds
-    private static final String CAMERA_STRESS_IMAGES_DIRECTORY = "cameraStressImages";
-    private static final String CAMERA_STRESS_IMAGES_PREFIX = "camera-stress-test";
     private static final String CAMERA_STRESS_OUTPUT = "cameraStressOutput.txt";
-    private final CameraErrorCallback mCameraErrorCallback = new CameraErrorCallback();
 
-    private Thread mLooperThread;
+    private CameraTestHelper mCameraTestHelper;
     private Handler mHandler;
-
+    private Thread mLooperThread;
     private Writer mOutput;
 
+    private String TAG = "CameraStressTest";
+
     public CameraStressTest() {
         super("com.android.mediaframeworktest", MediaFrameworkTest.class);
     }
@@ -95,19 +88,11 @@
         getActivity();
         super.setUp();
 
-        File sdcard = Environment.getExternalStorageDirectory();
-
-        // Create the test images directory if it doesn't exist
-        File stressImagesDirectory = new File(String.format("%s/%s", sdcard,
-                CAMERA_STRESS_IMAGES_DIRECTORY));
-        if (!stressImagesDirectory.exists()) {
-            stressImagesDirectory.mkdir();
-        }
-
-        // Start writing output file
-        File stressOutFile = new File(String.format("%s/%s",sdcard, CAMERA_STRESS_OUTPUT));
+        mCameraTestHelper = new CameraTestHelper();
+        File stressOutFile = new File(String.format("%s/%s",
+                Environment.getExternalStorageDirectory(), CAMERA_STRESS_OUTPUT));
         mOutput = new BufferedWriter(new FileWriter(stressOutFile, true));
-        mOutput.write(this.getName() + ":\n");
+        mOutput.write(this.getName() + "\n");
     }
 
     @Override
@@ -123,10 +108,8 @@
             }
             mLooperThread = null;
         }
-
         mOutput.write("\n\n");
         mOutput.close();
-
         super.tearDown();
     }
 
@@ -147,182 +130,14 @@
         }
     }
 
-    private final class CameraErrorCallback implements android.hardware.Camera.ErrorCallback {
-        public void onError(int error, android.hardware.Camera camera) {
-            fail(String.format("Camera error, code: %d", error));
-        }
-    }
-
-    private ShutterCallback shutterCallback = new ShutterCallback() {
-        @Override
-        public void onShutter() {
-            Log.v(TAG, "Shutter");
-        }
-    };
-
-    private PictureCallback rawCallback = new PictureCallback() {
-        @Override
-        public void onPictureTaken(byte[] data, Camera camera) {
-            Log.v(TAG, "Raw picture taken");
-        }
-    };
-
-    private PictureCallback jpegCallback = new PictureCallback() {
-        @Override
-        public void onPictureTaken(byte[] data, Camera camera) {
-            FileOutputStream fos = null;
-
-            try {
-                Log.v(TAG, "JPEG picture taken");
-                fos = new FileOutputStream(String.format("%s/%s/%s-%d.jpg",
-                        Environment.getExternalStorageDirectory(), CAMERA_STRESS_IMAGES_DIRECTORY,
-                        CAMERA_STRESS_IMAGES_PREFIX, System.currentTimeMillis()));
-                fos.write(data);
-            } catch (FileNotFoundException e) {
-                Log.e(TAG, "File not found: " + e.toString());
-            } catch (IOException e) {
-                Log.e(TAG, "Error accessing file: " + e.toString());
-            } finally {
-                try {
-                    if (fos != null) {
-                        fos.close();
-                    }
-                } catch (IOException e) {
-                    Log.e(TAG, "Error closing file: " + e.toString());
-                }
-            }
-        }
-    };
-
-    // Helper method for cleaning up pics taken during testStressCameraZoom
-    private void cleanupStressTestImages() {
-        try {
-            File stressImagesDirectory = new File(String.format("%s/%s",
-                    Environment.getExternalStorageDirectory(), CAMERA_STRESS_IMAGES_DIRECTORY));
-            File[] zoomImages = null;
-
-            FilenameFilter filter = new FilenameFilter() {
-                public boolean accept(File dir, String name) {
-                    return name.startsWith(CAMERA_STRESS_IMAGES_PREFIX);
-                }
-            };
-
-            zoomImages = stressImagesDirectory.listFiles(filter);
-
-            for (File f : zoomImages) {
-                f.delete();
-            }
-        } catch (SecurityException e) {
-            Log.e(TAG, "Security manager access violation: " + e.toString());
-        }
-    }
-
-    // Helper method for starting up the camera preview
-    private void startCameraPreview(SurfaceHolder surfaceHolder) {
-        try {
-            mCamera.setErrorCallback(mCameraErrorCallback);
-            mCamera.setPreviewDisplay(surfaceHolder);
-            mCamera.startPreview();
-            Thread.sleep(WAIT_GENERIC);
-        } catch (IOException e) {
-            Log.e(TAG, "Error setting preview display: " + e.toString());
-        } catch (InterruptedException e) {
-            Log.e(TAG, "Error waiting for preview to come up: " + e.toString());
-        } catch (Exception e) {
-            Log.e(TAG, "Error starting up camera preview: " + e.toString());
-        }
-    }
-
-    // Helper method for taking a photo
-    private void capturePhoto() {
-        try {
-            mCamera.takePicture(shutterCallback, rawCallback, jpegCallback);
-            Thread.sleep(WAIT_GENERIC);
-            mCamera.stopPreview();
-            mCamera.release();
-        } catch (InterruptedException e) {
-            Log.e(TAG, "Error waiting for photo to be taken: " + e.toString());
-        } catch (Exception e) {
-            Log.e(TAG, "Error capturing photo: " + e.toString());
-        }
-    }
-
-    // Test case for stressing the camera zoom in/out feature
-    @LargeTest
-    public void testStressCameraZoom() throws Exception {
-        SurfaceHolder mSurfaceHolder;
-        mSurfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
-        mOutput.write("Total number of loops: " + NUMBER_OF_ZOOM_LOOPS + "\n");
-
-        try {
-            Log.v(TAG, "Start preview");
-            mOutput.write("No of loop: ");
-
-            mCamera = Camera.open(CAMERA_ID);
-            Camera.Parameters params = mCamera.getParameters();
-            mCamera.release();
-
-            if (!params.isSmoothZoomSupported() && !params.isZoomSupported()) {
-                Log.v(TAG, "Device camera does not support zoom");
-                fail("Camera zoom stress test failed");
-            } else {
-                Log.v(TAG, "Device camera does support zoom");
-
-                int nextZoomLevel = 0;
-
-                for (int i = 0; i < NUMBER_OF_ZOOM_LOOPS; i++) {
-                    runOnLooper(new Runnable() {
-                        @Override
-                        public void run() {
-                            mCamera = Camera.open(CAMERA_ID);
-                        }
-                    });
-
-                    startCameraPreview(mSurfaceHolder);
-                    params = mCamera.getParameters();
-                    int currentZoomLevel = params.getZoom();
-
-                    if (nextZoomLevel >= params.getMaxZoom()) {
-                        nextZoomLevel = 0;
-                    }
-                    ++nextZoomLevel;
-
-                    if (params.isSmoothZoomSupported()) {
-                        mCamera.startSmoothZoom(nextZoomLevel);
-                    } else {
-                        params.setZoom(nextZoomLevel);
-                        mCamera.setParameters(params);
-                    }
-                    Log.v(TAG, "Zooming from " + currentZoomLevel + " to " + nextZoomLevel);
-
-                    // sleep allows for zoom animation to finish
-                    Thread.sleep(WAIT_ZOOM_ANIMATION);
-                    capturePhoto();
-
-                    if (i == 0) {
-                        mOutput.write(Integer.toString(i));
-                    } else {
-                        mOutput.write(", " + i);
-                    }
-                }
-            }
-            cleanupStressTestImages();
-        } catch (Exception e) {
-            Log.e(TAG, e.toString());
-            fail("Camera zoom stress test Exception");
-        }
-    }
-
-    // Test case for stressing the camera scene mode feature
+    /**
+     * Stress test iterating on the various scene modes (action, night, party, etc.)
+     */
     @LargeTest
     public void testStressCameraSceneModes() throws Exception {
-        SurfaceHolder mSurfaceHolder;
-        mSurfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
-
         try {
-            mCamera = Camera.open(CAMERA_ID);
-            Camera.Parameters params = mCamera.getParameters();
-            mCamera.release();
+            SurfaceHolder surfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
+            Parameters params = mCameraTestHelper.getCameraParameters();
             List<String> supportedSceneModes = params.getSupportedSceneModes();
             assertNotNull("No scene modes supported", supportedSceneModes);
 
@@ -336,27 +151,85 @@
                     runOnLooper(new Runnable() {
                         @Override
                         public void run() {
-                            mCamera = Camera.open(CAMERA_ID);
+                            mCameraTestHelper.setupCameraTest();
                         }
                     });
-
-                    startCameraPreview(mSurfaceHolder);
-                    Log.v(TAG, "Setting mode to " + supportedSceneModes.get(i));
+                    Log.v(TAG, "Setting scene mode to " + supportedSceneModes.get(i));
                     params.setSceneMode(supportedSceneModes.get(i));
-                    mCamera.setParameters(params);
-                    capturePhoto();
+                    mCameraTestHelper.setParameters(params);
+                    mCameraTestHelper.startCameraPreview(surfaceHolder);
+                    mCameraTestHelper.capturePhoto();
 
-                    if ((i == 0) && (j == 0)) {
+                    if (i == 0 && j == 0) {
                         mOutput.write(Integer.toString(j + i * NUMBER_OF_SCENE_MODE_LOOPS));
                     } else {
                         mOutput.write(", " + (j + i * NUMBER_OF_SCENE_MODE_LOOPS));
                     }
                 }
             }
-            cleanupStressTestImages();
+            mCameraTestHelper.cleanupTestImages();
         } catch (Exception e) {
             Log.e(TAG, e.toString());
             fail("Camera scene mode test Exception");
         }
     }
+
+    /**
+     * Stress test iterating on the range of supported camera zoom levels
+     */
+    @LargeTest
+    public void testStressCameraZoom() throws Exception {
+        try {
+            SurfaceHolder surfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
+            Parameters params = mCameraTestHelper.getCameraParameters();
+
+            if (!params.isSmoothZoomSupported() && !params.isZoomSupported()) {
+                Log.v(TAG, "Device camera does not support zoom");
+                fail("Camera zoom stress test failed due to unsupported feature");
+            } else {
+                Log.v(TAG, "Device camera does support zoom");
+                Log.v(TAG, "Start preview");
+                mOutput.write("Total number of loops: " + NUMBER_OF_ZOOM_LOOPS + "\n");
+                mOutput.write("No of loops: ");
+
+                int nextZoomLevel = 0;
+
+                for (int i = 0; i < NUMBER_OF_ZOOM_LOOPS; i++) {
+                    runOnLooper(new Runnable() {
+                        @Override
+                        public void run() {
+                            mCameraTestHelper.setupCameraTest();
+                        }
+                    });
+
+                    mCameraTestHelper.startCameraPreview(surfaceHolder);
+                    params = mCameraTestHelper.mCamera.getParameters();
+                    int currentZoomLevel = params.getZoom();
+
+                    if (nextZoomLevel >= params.getMaxZoom()) {
+                        nextZoomLevel = 0;
+                    }
+                    ++nextZoomLevel;
+
+                    if (params.isSmoothZoomSupported()) {
+                        mCameraTestHelper.mCamera.startSmoothZoom(nextZoomLevel);
+                    } else {
+                        params.setZoom(nextZoomLevel);
+                        mCameraTestHelper.setParameters(params);
+                    }
+                    mCameraTestHelper.capturePhoto();
+
+                    if (i == 0) {
+                        mOutput.write(Integer.toString(i));
+                    } else {
+                        mOutput.write(", " + i);
+                    }
+                }
+            }
+            mCameraTestHelper.cleanupTestImages();
+        } catch (Exception e) {
+            Log.e(TAG, e.toString());
+            fail("Camera zoom stress test Exception");
+        }
+    }
 }
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
index 41da158..0970248 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
@@ -117,7 +117,6 @@
 
     private KeyguardMultiUserSelectorView mKeyguardMultiUserSelectorView;
 
-    protected int mPlaybackState;
     protected int mClientGeneration;
 
     /*package*/ interface UserSwitcherCallback {
@@ -204,10 +203,9 @@
                 .getCachedDisplayClientState();
         mTransportState = (dcs.clearing ? TRANSPORT_GONE :
             (isMusicPlaying(dcs.playbackState) ? TRANSPORT_VISIBLE : TRANSPORT_INVISIBLE));
-        mPlaybackState = dcs.playbackState;
 
         if (DEBUG) Log.v(TAG, "Initial transport state: "
-                + mTransportState + ", pbstate=" + mPlaybackState);
+                + mTransportState + ", pbstate=" + dcs.playbackState);
     }
 
     private void cleanupAppWidgetIds() {
@@ -273,18 +271,27 @@
                 Log.v(TAG, (clearing ? "hide" : "show") + " transport, gen:" + clientGeneration);
             }
             mClientGeneration = clientGeneration;
-            mTransportState = (clearing ? TRANSPORT_GONE : TRANSPORT_INVISIBLE);
-            KeyguardHostView.this.post(mSwitchPageRunnable);
+            final int newState = (clearing ? TRANSPORT_GONE
+                    : (mTransportState == TRANSPORT_VISIBLE ?
+                    TRANSPORT_VISIBLE : TRANSPORT_INVISIBLE));
+            if (newState != mTransportState) {
+                mTransportState = newState;
+                if (DEBUGXPORT) Log.v(TAG, "update widget: transport state changed");
+                KeyguardHostView.this.post(mSwitchPageRunnable);
+            }
         }
         @Override
         public void onMusicPlaybackStateChanged(int playbackState, long eventTime) {
-            mPlaybackState = playbackState;
             if (DEBUGXPORT) Log.v(TAG, "music state changed: " + playbackState);
             if (mTransportState != TRANSPORT_GONE) {
-                mTransportState = (isMusicPlaying(mPlaybackState) ?
+                final int newState = (isMusicPlaying(playbackState) ?
                         TRANSPORT_VISIBLE : TRANSPORT_INVISIBLE);
+                if (newState != mTransportState) {
+                    mTransportState = newState;
+                    if (DEBUGXPORT) Log.v(TAG, "update widget: play state changed");
+                    KeyguardHostView.this.post(mSwitchPageRunnable);
+                }
             }
-            KeyguardHostView.this.post(mSwitchPageRunnable);
         }
     };
 
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 89a8dd7..0ca5f98 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -203,4 +203,7 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"OUTO"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Kennisgewings verskyn hier"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Verkry enige tyd toegang tot hulle deur af te sleep."\n"Sleep weer af vir stelselkontroles."</string>
+    <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Sleep op vanaf onderkant van skerm om stelselbalk te wys"</string>
+    <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Sleep onderkant van skerm om balk te wys"</string>
+    <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Sleep van regterkant van skerm af om stelselbalk te wys"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index e6dad88..4308ec3 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -203,4 +203,7 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"ራስ-ሰር"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"ማሳወቂያዎች እዚህ ላይ ይታያሉ"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"ወደ ታች በማንሸራተት በማንኛውም ጊዜ ይድረሱባቸው።"\n"Swipe የስርዓት መቆጣጠሪያዎችን ለማምጣት እንደገና ወደ ታች ያንሸራትቱ።"</string>
+    <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"የስርዓት አሞሌውን ለማሳየት ከማያ ገጹ ታችኛው ክፍል ጀምረው ወደላይ ያንሸራትቱ"</string>
+    <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"አሞሌውን ለማሳየት የማያ ገጹ ታችኛው ክፍል ያንሸራትቱ"</string>
+    <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"አሞሌውን ለማሳየት ከማያ ገጹ ቀኝ ክፍል ጀምረው ያንሸራትቱ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 110ebc0..1f0c757 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -203,4 +203,7 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"تلقائي"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"تظهر الإشعارات هنا"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"يمكنك الدخول إليها في أي وقت بالتمرير السريع إلى أسفل."\n"يمكنك التمرير السريع إلى أسفل مرة أخرى للوصول إلى عناصر تحكم النظام."</string>
+    <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"مرر سريعًا من أسفل الشاشة لإظهار شريط النظام"</string>
+    <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"مرر سريعًا أسفل الشاشة لإظهار الشريط"</string>
+    <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"مرر سريعًا من يمين الشاشة لإظهار شريط النظام"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index c66e912..b45ddb6 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -205,4 +205,7 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"АЎТА"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Апавяшчэнні з\'яўляюцца тут"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Атрымлівайце доступ да іх у любы час, праводзячы пальцам уніз."\n"Правядзіце пальцам уніз яшчэ раз, каб атрымаць доступ да сродкаў кіравання сістэмай."</string>
+    <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Правядзіце па экрану знізу ўверх, каб адлюстраваць сістэмны радок"</string>
+    <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Правядзіце па ніжняй частцы экрану, каб адлюстраваць радок"</string>
+    <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Правядзіце ад правага краю экрану, каб адлюстраваць сістэмны радок"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index e3f7dc1..c161fbd 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -203,4 +203,7 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"АВТ."</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Известията се показват тук"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Осъществявайте достъп до тях по всяко време, като прекарате пръст надолу."\n"Направете го отново за системните контроли."</string>
+    <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Прекарайте пръст нагоре от долната част на екрана, за да се покаже системната лента"</string>
+    <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Прекарайте пръст от долната част на екрана, за да се покаже лентата"</string>
+    <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Прекарайте пръст отдясно на екрана, за да се покаже системната лента"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 580bfe7..5cf131d 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -205,4 +205,7 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMÀTICA"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Les notificacions apareixen aquí"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Accedeix-hi en qualsevol moment: només has de fer lliscar el dit cap avall."\n"Torna a fer lliscar el dit cap avall per fer que es mostrin els controls del sistema."</string>
+    <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Fes lliscar el dit des de la part inferior de la pantalla perquè es mostri la barra del sistema"</string>
+    <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Fes lliscar el dit des de la part inferior de la pantalla perquè es mostri la barra"</string>
+    <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Fes lliscar el dit des de la dreta de la pantalla perquè es mostri la barra del sistema"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index a623612..0f03db1 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -205,4 +205,7 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMATICKY"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Zde se zobrazují oznámení"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Můžete je kdykoli zobrazit tím, že přejedete prstem dolů."\n"Přejedete-li prstem dolů ještě jednou, zobrazí se ovládací prvky systému."</string>
+    <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Systémový panel zobrazíte přejetím ze spodní části obrazovky nahoru"</string>
+    <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Panel zobrazíte přejetím zdola nahoru"</string>
+    <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Systémový panel zobrazíte přejetím z pravé strany obrazovky"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 7f7a51c..b6a92a6 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -203,4 +203,7 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Underretninger vises her"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Få adgang til dem når som helst ved at stryge ned."\n"Stryg ned igen for at komme til systemindstillingerne."</string>
+    <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Stryg op fra bunden af ​​skærmen for at vise systembjælken."</string>
+    <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Stryg bunden af ​​skærmen for at vise bjælken"</string>
+    <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Stryg fra skærmens højre side for at vise systembjælken"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 2b226b6..3a3c451 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -205,4 +205,7 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Benachrichtigungen erscheinen hier"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Greifen Sie jederzeit auf sie zu, indem Sie nach unten wischen."\n"Wischen Sie für Systemeinstellungen erneut nach unten."</string>
+    <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Zum Einblenden der Systemleiste auf dem Display von unten nach oben wischen"</string>
+    <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Zum Einblenden der Leiste nach oben wischen"</string>
+    <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Zum Einblenden der Systemleiste auf dem Display von rechts nach links wischen"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index dae50a3..befd927 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -205,4 +205,7 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"ΑΥΤΟΜΑΤΗ"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Οι ειδοποιήσεις εμφανίζονται εδώ"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Μεταβείτε σε αυτές ανά πάσα στιγμή σύροντας προς τα κάτω."\n"Σύρετε ξανά προς τα κάτω για τα στοιχεία ελέγχου συστήματος."</string>
+    <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Σύρετε προς τα επάνω από το κάτω μέρος της οθόνης για να εμφανίσετε τη γραμμή συστήματος"</string>
+    <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Σύρετε από το κάτω μέρος της οθόνης για να εμφανίσετε τη γραμμή"</string>
+    <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Σύρετε από τη δεξιά πλευρά της οθόνης για να εμφανίσετε τη γραμμή συστήματος"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 7e74e40..1427c87 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -203,4 +203,7 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Notifications appear here"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Access them any time by swiping down."\n"Swipe down again for system controls."</string>
+    <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Swipe up from bottom of screen to reveal system bar"</string>
+    <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Swipe bottom of screen to reveal bar"</string>
+    <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Swipe from right of screen to reveal system bar"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 1fe4d46..21c6e750 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -205,4 +205,7 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMÁTICO"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Las notificaciones aparecen aquí."</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Desliza el dedo hacia abajo para acceder al contenido."\n"Vuelve a deslizar el dedo hacia abajo para acceder a los controles del sistema."</string>
+    <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Desliza el dedo hacia arriba desde la parte inferior de la pantalla para mostrar la barra del sistema."</string>
+    <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Desliza el dedo desde la parte inferior de la pantalla para mostrar la barra."</string>
+    <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Desliza el dedo desde la parte derecha de la pantalla para mostrar la barra del sistema."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 19de9b6..b2cb952 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -203,4 +203,7 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Las notificaciones aparecen aquí"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Desliza el dedo hacia abajo para acceder al contenido."\n"Vuelve a deslizar el dedo hacia abajo para acceder a los controles del sistema."</string>
+    <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Desliza la pantalla hacia arriba desde la parte inferior para mostrar la barra del sistema"</string>
+    <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Desliza la parte inferior de la pantalla para mostrar la barra"</string>
+    <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Desliza la pantalla desde la derecha para mostrar la barra del sistema"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index 5339006..e2324b5 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -203,4 +203,7 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMAATNE"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Märguanded ilmuvad siia"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Juurdepääs igal ajal sõrmega alla pühkides."\n"Süsteemi juhtnuppude jaoks pühkige uuesti alla."</string>
+    <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Süsteemiriba kuvamiseks pühkige ekraani allosast üles"</string>
+    <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Riba kuvamiseks pühkige ekraani allosas"</string>
+    <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Süsteemiriba kuvamiseks pühkige ekraani paremast servast"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index e766df8..a3eb06b 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -203,4 +203,7 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"خودکار"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"اعلان‌ها در اینجا نمایش داده می‌شوند"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"با کشیدن انگشت به طرف پایین به آنها دسترسی پیدا کنید."\n"برای کنترل‌های سیستم دوباره انگشت خود را به سمت پایین بکشید."</string>
+    <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"برای آشکارسازی نوار سیستم انگشت خود را از پایین صفحه به بالا بکشید"</string>
+    <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"برای آشکارسازی نوار انگشت خود را روی پایین صفحه بکشید"</string>
+    <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"برای آشکارسازی نوار سیستم انگشت خود را از سمت راست صفحه بکشید"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 8e80016..c975970 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -203,4 +203,7 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Ilmoitukset näkyvät tässä"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Näet ilmoitukset liu\'uttamalla sormea alas ruudulla."\n"Voit palauttaa järjestelmän ohjaimet näkyviin liu\'uttamalla sormea alas uudelleen."</string>
+    <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Tuo järjestelmäpalkki näkyviin liu\'uttamalla ruudun alalaidasta ylöspäin"</string>
+    <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Tuo palkki näkyviin liu\'uttamalla ruudun alaosasta"</string>
+    <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Tuo järjestelmäpalkki näkyviin liu\'uttamalla ruudun oikeasta laidasta vasemmalle"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 294c0ee..3b7f798 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -205,4 +205,7 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMATIQUE"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Les notifications s’affichent ici"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Accédez-y à tout moment en faisant glisser le doigt vers le bas."\n"Répétez l\'opération pour accéder aux commandes du système."</string>
+    <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Faites glisser votre doigt de bas en haut sur l\'écran pour afficher la barre système."</string>
+    <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Faites glisser votre doigt au bas de l\'écran pour afficher la barre."</string>
+    <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Faites glisser votre doigt de droite à gauche sur l\'écran pour afficher la barre système."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index cdcda79..05fffc36 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -203,4 +203,7 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"स्वत:"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"सूचनाएं यहां दिखाई देती हैं"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"नीचे स्वाइप करके उन तक कभी भी पहुंचें."\n"सिस्टम नियंत्रणों के लिए पुन: नीचे स्वाइप करें."</string>
+    <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"सिस्टम बार दिखाने के लिए स्क्रीन के नीचे से ऊपर की ओर स्वाइप करें"</string>
+    <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"बार दिखाने के लिए स्क्रीन के नीचे स्वाइप करें"</string>
+    <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"सिस्टम बार दिखाने के लिए स्क्रीन की दाईं ओर से स्वाइप करें"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 93e03d1..0f7f92f 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -203,4 +203,7 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMATSKI"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Obavijesti se prikazuju ovdje"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Pristupite im u bilo kojem trenutku tako da prstom trznete prema dolje. "\n"Ponovo prstom trznite prema dolje za kontrole sustava."</string>
+    <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Prijeđite prstom od dna zaslona prema gore da bi se prikazala traka sustava"</string>
+    <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Prijeđite prstom po dnu zaslona da bi se prikazala traka"</string>
+    <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Prijeđite prstom od desne strane zaslona da bi se prikazala traka sustava"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 27bf2f5..82b3ddd 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -203,4 +203,7 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"automatikus"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Az értesítések itt jelennek meg."</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Bármikor elérheti őket, ha lefelé húzza az ujját."\n"Húzza le az ujját még egyszer a rendszerbeállítások eléréséhez."</string>
+    <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Csúsztassa ujját a képernyő aljától felfelé a rendszersáv megjelenítéséhez"</string>
+    <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Csúsztassa ujját a képernyő alján a sáv megjelenítéséhez"</string>
+    <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Csúsztassa ujját a képernyő jobb oldalától a rendszersáv megjelenítéséhez"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 581c56c..d9597da 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -203,4 +203,7 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"OTOMATIS"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Pemberitahuan muncul di sini"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Akses kapan saja dengan menggesek ke bawah."\n"Gesek ke bawah sekali lagi untuk kontrol sistem."</string>
+    <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Gesek ke atas dari bagian bawah layar untuk membuka bilah sistem"</string>
+    <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Gesek bagian bawah layar untuk membuka bilah"</string>
+    <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Gesek dari bagian kanan layar untuk membuka bilah sistem"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 3d7cb76..6ef9a8e 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -205,4 +205,7 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Le notifiche vengono visualizzate qui"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Puoi accedervi in qualsiasi momento scorrendo verso il basso."\n"Fai scorrere di nuovo verso il basso per visualizzare i controlli del sistema."</string>
+    <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Fai scorrere il dito verso l\'alto dalla parte inferiore dello schermo per visualizzare la barra di sistema"</string>
+    <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Fai scorrere parte inferiore dello schermo per visualizzare la barra"</string>
+    <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Fai scorrere il dito dalla parte destra dello schermo per visualizzare la barra di sistema"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 8dd00d1..8a3f1550 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -203,4 +203,7 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"אוטומטי"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"הודעות מופיעות כאן"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"גש אליהם בכל עת על ידי החלקה למטה."\n"החלק למטה שוב למעבר למרכז הבקרה של המערכת."</string>
+    <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"החלק מעלה מתחתית המסך כדי להציג את סרגל המערכת"</string>
+    <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"החלק מתחתית המסך כדי להציג את הסרגל"</string>
+    <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"החלק מצד ימין של המסך כדי להציג את סרגל המערכת"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index b64d73e..95f24fd 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -205,4 +205,7 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"自動"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"ここに通知が表示されます"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"下にスワイプすると、いつでも通知を表示できます。"\n"システムを管理するにはもう一度下にスワイプしてください。"</string>
+    <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"システムバーを表示するには、画面下部から上方向にスワイプします"</string>
+    <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"バーを表示するには、画面下部からスワイプします"</string>
+    <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"システムバーを表示するには、画面右からスワイプします"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 3f7c520..dc82a01 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -203,4 +203,7 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"자동"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"알림이 여기에 표시됨"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"아래로 스와이프하여 언제든 액세스하세요."\n"한 번 더 아래로 스와이프하면 시스템 관리로 이동합니다."</string>
+    <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"화면 하단에서 위로 스와이프하여 시스템 표시줄 표시"</string>
+    <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"화면 하단에서 스와이프하여 표시줄 표시"</string>
+    <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"화면 오른쪽에서 스와이프하여 시스템 표시줄 표시"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 02d0c5b..b2c5d2c 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -203,4 +203,7 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMATINIS"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Pranešimai rodomi čia"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Perbraukę žemyn bet kuriuo metu pasieksite pranešimus."\n"Jei norite naudoti sistemos valdiklius, perbraukite žemyn dar kartą."</string>
+    <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Jei norite, kad būtų rodoma sistemos juosta, perbraukite aukštyn iš ekrano apačios"</string>
+    <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Jei norite, kad būtų rodoma juosta, perbraukite ekrano apačioje"</string>
+    <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Jei norite, kad būtų rodoma sistemos juosta, perbraukite iš ekrano dešinės"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 372389f..41d1158 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -203,4 +203,7 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMĀTISKI"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Šeit tiek rādīti paziņojumi"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Piekļūstiet tiem jebkurā laikā, velkot uz leju."\n"Vēlreiz velciet, lai tiktu parādītas sistēmas vadīklas."</string>
+    <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Velciet augšup no ekrāna apakšdaļas, lai tiktu parādīta sistēmas josla."</string>
+    <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Velciet no ekrāna apakšdaļas, lai tiktu parādīta josla."</string>
+    <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Velciet no ekrāna labās malas, lai tiktu parādīta sistēmas josla."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index 8505377..cabd7b5 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -203,4 +203,7 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Pemberitahuan dipaparkan di sini"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Akses panel pada bila-bila masa dengan meleret ke bawah."\n"Leret ke bawah sekali lagi untuk mendapatkan kawalan sistem."</string>
+    <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Leret ke atas dari bahagian bawah skrin untuk mendedahkan bar sistem"</string>
+    <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Leret ke bahagian bawah skrin untuk mendedahkan bar"</string>
+    <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Leret dari kanan skrin untuk mendedahkan bar sistem"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 7a7c5a5..31953c3 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -203,4 +203,7 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Varslene vises her"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Bruk dem når som helst ved å sveipe nedover."\n"Sveip nedover igjen for å gå til systemkontrollene."</string>
+    <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Sveip opp fra bunnen av skjermen for å få frem systemfeltet"</string>
+    <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Sveip på bunnen av skjermen for å få frem feltet"</string>
+    <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Sveip fra høyre på skjermen for å få frem systemfeltet"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 3a3c820..6661bfa 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -203,4 +203,7 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMATISCH"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Meldingen worden hier weergegeven"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"U kunt de meldingen op elk gewenst moment openen door met uw vinger omlaag te vegen."\n"Veeg nogmaals met uw vinger omlaag om de systeembesturingselementen weer te geven."</string>
+    <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Veeg omhoog vanaf de onderkant van het scherm om de systeembalk weer te geven"</string>
+    <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Veeg onderkant van scherm om balk weer te geven"</string>
+    <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Veeg vanaf de rechterkant van het scherm om de systeembalk weer te geven"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index fff1aa0..c97372d 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -203,4 +203,7 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMATYCZNA"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Tutaj pokazują się powiadomienia"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Możesz je otworzyć w dowolnej chwili, przesuwając w dół."\n"Przesuń jeszcze raz w dół, by otworzyć ustawienia systemowe."</string>
+    <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Przesuń palcem od dołu ekranu, by odkryć pasek systemu"</string>
+    <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Przesuń palcem dół ekranu, by odkryć pasek"</string>
+    <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Przesuń palcem od prawej strony ekranu, by odkryć pasek systemu"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 5976e0e..eba6c18 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -203,4 +203,7 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMÁTICO"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"As notificações são apresentadas aqui"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Pode aceder em qualquer altura, deslizando rapidamente para baixo com o dedo."\n"Deslize novamente para baixo para aceder aos controlos do sistema."</string>
+    <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Deslize p/ cima a partir da parte inferior do ecrã p/ revelar a barra do sistema"</string>
+    <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Deslize da parte inferior do ecrã p/ revelar a barra"</string>
+    <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Deslize da direita do ecrã p/ revelar a barra do sistema"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 0cfd805..93b0e2d 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -205,4 +205,7 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"As notificações aparecem aqui"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Acesse a qualquer momento deslizando para baixo."\n"Deslize para baixo novamente para acessar os controles do sistema."</string>
+    <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Deslize de cima para baixo na tela para ver a barra do sistema"</string>
+    <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Deslize para baixo para ver a barra"</string>
+    <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Deslize da direita para a esquerda na tela para ver a barra do sistema"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-rm/strings.xml b/packages/SystemUI/res/values-rm/strings.xml
index 606160b..948b959 100644
--- a/packages/SystemUI/res/values-rm/strings.xml
+++ b/packages/SystemUI/res/values-rm/strings.xml
@@ -376,4 +376,10 @@
     <skip />
     <!-- no translation found for status_bar_help_text (7874607155052076323) -->
     <skip />
+    <!-- no translation found for hideybar_confirmation_message_bottom (4678097945183429216) -->
+    <skip />
+    <!-- no translation found for hideybar_confirmation_message_bottom_short (4014207345313478943) -->
+    <skip />
+    <!-- no translation found for hideybar_confirmation_message_right (5359586491708388067) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 44b4b4e..7faa2e4 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -203,4 +203,7 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMAT"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Notificările se afişează aici"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Accesaţi-le oricând glisând în jos."\n"Glisaţi în jos din nou pentru comenzile sistemului."</string>
+    <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Glisați în sus din partea inferioară a ecranului pentru a afișa bara de sistem"</string>
+    <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Glisați dinspre partea inferioară a ecranului pentru a afișa bara"</string>
+    <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Glisați din partea dreaptă a ecranului pentru a afișa bara de sistem"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 9fabb39..2ca195a 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -207,4 +207,7 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"АВТОНАСТРОЙКА"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Это панель уведомлений"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Ее можно открыть, пролистнув экран вниз."\n"Чтобы открыть настройки, проведите пальцем вниз ещё раз."</string>
+    <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Чтобы увидеть строку состояния, проведите пальцем от нижней части экрана вверх"</string>
+    <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Чтобы увидеть строку состояния, проведите по экрану снизу вверх"</string>
+    <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Чтобы увидеть строку состояния, проведите пальцем по экрану справа налево"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index c5143dd..e5e1d58 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -205,4 +205,7 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMATICKY"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Tu sa zobrazujú upozornenia"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Môžete ich kedykoľvek zobraziť tak, že posuniete prstom nadol."\n"Ak posuniete prstom nadol ešte raz, zobrazia sa ovládacie prvky systému."</string>
+    <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Systémový panel zobrazíte posunutím z dolnej časti obrazovky smerom nahor"</string>
+    <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Panel zobrazíte posunutím zdola nahor"</string>
+    <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Systémový panel zobrazíte posunutím z pravej strany obrazovky"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 48f0893..5a0f46a 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -203,4 +203,7 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"SAMODEJNO"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Obvestila so prikazana tukaj"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Do njih lahko kadar koli dostopate tako, da povlečete navzdol."\n"Za prikaz sistemskih kontrolnikov znova povlecite navzdol."</string>
+    <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Povlecite navzgor z dna zaslona, da prikažete sistemsko vrstico"</string>
+    <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Prikažite vrstico tako, da povlečete na dnu zaslona"</string>
+    <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Sistemsko vrstico prikažete tako, da povlečete z desne strani zaslona"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 42ab38a..6a209d05 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -203,4 +203,7 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"АУТОМАТСКА"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Обавештења се појављују овде"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Приступите им у било ком тренутку листањем надоле."\n"Поново листајте надоле да би се приказале системске контроле."</string>
+    <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Превуците нагоре од доњег дела екрана да би се приказала системска трака"</string>
+    <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Превуците од доњег дела екрана да би се приказала трака"</string>
+    <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Превуците од десне стране екрана да би се приказала системска трака"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 4ddcb84..b1c1cf6 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -203,4 +203,7 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Meddelanden visas här"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Du kommer åt dem när som helst genom att dra nedåt."\n"Dra nedåt igen om du vill visa systemkontroller."</string>
+    <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Dra uppåt från skärmens nederkant om du vill visa systemfältet"</string>
+    <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Dra uppåt på skärmen om du vill visa fältet"</string>
+    <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Dra från högersidan av skärmen om du vill visa systemfältet"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index d5c8282..2c8100d 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -201,4 +201,7 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"KIOTOMATIKI"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Arifa zitaonekana hapa"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Wafikie wakati wowote kwa kupapasa chini."\n"Papasa chini tena kupata vidhibiti vya mfumo."</string>
+    <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Papasa kwenda juu kutoka chini ya skrini ili kuonyesha upau wa mfumo"</string>
+    <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Papasa chini ya skrini ili kuonyesha upau"</string>
+    <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Papasa kutoka kulia kwa skrini ili kuonyesha upau wa mfumo"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 20d165f..f36e07f 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -203,4 +203,7 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"อัตโนมัติ"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"การแจ้งเตือนจะแสดงขึ้นที่นี่"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"เข้าถึงได้ทุกเมื่อด้วยการกวาดนิ้วลง"\n"กวาดนิ้วลงอีกครั้งสำหรับการควบคุมระบบ"</string>
+    <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"กวาดขึ้นจากด้านล่างของหน้าจอเพื่อแสดงแถบระบบ"</string>
+    <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"กวาดด้านล่างของหน้าจอเพื่อแสดงแถบ"</string>
+    <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"กวาดจากด้านขวาของหน้าจอเพื่อแสดงแถบระบบ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 48dca2d..68b7896 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -203,4 +203,7 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Dito lumalabas ang mga notification"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"I-access ang mga ito anumang oras sa pamamagitan ng pag-swipe pababa."\n"Muling mag-swipe pababa para sa mga kontrol ng system."</string>
+    <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Mag-swipe pataas mula sa ibaba ng screen upang ipakita ang system bar"</string>
+    <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Mag-swipe sa ibaba ng screen upang ipakita ang bar"</string>
+    <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Mag-swipe mula sa kanan ng screen upang ipakita ang system bar"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 5d64286..0017a9e 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -203,4 +203,7 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"OTOMATİK"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Bildirimler burada görünür"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Aşağıya hızlıca kaydırarak bunlara istediğiniz zaman erişebilirsiniz."\n"Sistem denetimleri için tekrar hızlıca aşağı kaydırın."</string>
+    <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Sistem çubuğunu görüntülemek için ekranın altında yukarı doğru hızlıca kaydırın"</string>
+    <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Çubuğu görüntülemek için ekranın altından hızlıca kaydırın"</string>
+    <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Sistem çubuğunu görüntülemek için ekranın sağından hızlıca kaydırın"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index f862365..a9b0fe7 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -203,4 +203,7 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"АВТО"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Сповіщення з’являються тут"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Отримуйте до них доступ будь-коли, провівши пальцем униз."\n"Знову проведіть униз, щоб відкрити елементи керування системи."</string>
+    <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Проведіть пальцем угору від низу екрана, щоб з’явився системний рядок"</string>
+    <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Проведіть від низу екрана, щоб з’явився рядок"</string>
+    <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Проведіть пальцем справа наліво на екрані, щоб з’явився системний рядок"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index d5a64b0..38f6036 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -203,4 +203,7 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"TỰ ĐỘNG"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Thông báo xuất hiện tại đây"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Truy cập vào chúng bất kỳ lúc nào bằng cách vuốt xuống."\n"Vuốt lại xuống để hiển thị các điều khiển hệ thống."</string>
+    <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Vuốt lên từ cuối màn hình để hiển thị thanh hệ thống"</string>
+    <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Vuốt cuối màn hình để hiển thị thanh"</string>
+    <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Vuốt từ bên phải màn hình để hiển thị thanh hệ thống"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 3d2f2e1..18814c7 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -40,7 +40,7 @@
     <string name="invalid_charger" msgid="4549105996740522523">"不支持 USB 充电功能。"\n"只能使用随附的充电器充电。"</string>
     <string name="battery_low_why" msgid="7279169609518386372">"电量使用情况"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"设置"</string>
-    <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
+    <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"WLAN"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"飞行模式"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"自动旋转屏幕"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"静音"</string>
@@ -100,12 +100,12 @@
     <string name="accessibility_data_two_bars" msgid="6166018492360432091">"数据信号强度为两格。"</string>
     <string name="accessibility_data_three_bars" msgid="9167670452395038520">"数据信号强度为三格。"</string>
     <string name="accessibility_data_signal_full" msgid="2708384608124519369">"数据信号满格。"</string>
-    <string name="accessibility_wifi_off" msgid="3177380296697933627">"已关闭 Wi-Fi。"</string>
-    <string name="accessibility_no_wifi" msgid="1425476551827924474">"Wi-Fi 连接已断开。"</string>
-    <string name="accessibility_wifi_one_bar" msgid="7735893178010724377">"Wi-Fi 信号强度为一格。"</string>
-    <string name="accessibility_wifi_two_bars" msgid="4994274250497262434">"Wi-Fi 信号强度为两格。"</string>
-    <string name="accessibility_wifi_three_bars" msgid="3495755044276588384">"Wi-Fi 信号强度为三格。"</string>
-    <string name="accessibility_wifi_signal_full" msgid="6853561303586480376">"Wi-Fi 信号满格。"</string>
+    <string name="accessibility_wifi_off" msgid="3177380296697933627">"已关闭 WLAN。"</string>
+    <string name="accessibility_no_wifi" msgid="1425476551827924474">"WLAN 连接已断开。"</string>
+    <string name="accessibility_wifi_one_bar" msgid="7735893178010724377">"WLAN 信号强度为一格。"</string>
+    <string name="accessibility_wifi_two_bars" msgid="4994274250497262434">"WLAN 信号强度为两格。"</string>
+    <string name="accessibility_wifi_three_bars" msgid="3495755044276588384">"WLAN 信号强度为三格。"</string>
+    <string name="accessibility_wifi_signal_full" msgid="6853561303586480376">"WLAN 信号满格。"</string>
     <string name="accessibility_no_wimax" msgid="4329180129727630368">"无 WiMAX 信号。"</string>
     <string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"WiMAX 信号强度为一格。"</string>
     <string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"WiMAX 信号强度为两格。"</string>
@@ -130,7 +130,7 @@
     <string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
     <string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"漫游中"</string>
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"EDGE"</string>
-    <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
+    <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"WLAN"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"无 SIM 卡。"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"蓝牙共享网络。"</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"飞行模式。"</string>
@@ -164,7 +164,7 @@
     <string name="data_usage_disabled_dialog" msgid="3853117269051806280">"您已达到指定的数据流量上限。"\n\n"如果您重新启用数据,运营商可能会收取相应的费用。"</string>
     <string name="data_usage_disabled_dialog_enable" msgid="7729772039208664606">"重新启用数据连接"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"未连接互联网"</string>
-    <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi 已连接"</string>
+    <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"WLAN 已连接"</string>
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"正在搜索 GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"已通过 GPS 确定位置"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"清除所有通知。"</string>
@@ -195,14 +195,17 @@
     <string name="quick_settings_settings_label" msgid="5326556592578065401">"设置"</string>
     <string name="quick_settings_time_label" msgid="4635969182239736408">"时间"</string>
     <string name="quick_settings_user_label" msgid="5238995632130897840">"我"</string>
-    <string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
+    <string name="quick_settings_wifi_label" msgid="9135344704899546041">"WLAN"</string>
     <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"未连接"</string>
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"无网络"</string>
-    <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi 已关闭"</string>
-    <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Wi-Fi 显示"</string>
+    <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"WLAN 已关闭"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"WLAN 显示"</string>
     <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"无线显示"</string>
     <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"亮度"</string>
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"自动"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"通知会显示在这里"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"向下滑动可随时查看通知。"\n"再次向下滑动可使用系统控制功能。"</string>
+    <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"从屏幕底部向上滑动即可显示系统栏"</string>
+    <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"从底部向上滑可显示系统栏"</string>
+    <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"从屏幕右侧向左滑动即可显示系统栏"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index d7ecc3f..af3e469 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -205,4 +205,7 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"自動"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"系統會在這裡顯示通知"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"向下滑動即可隨時存取通知。"\n"再次向下滑動即可使用系統控制項。"</string>
+    <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"從螢幕底部向上滑動即可顯示系統列"</string>
+    <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"從螢幕底部滑動即可顯示系統列"</string>
+    <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"從螢幕右側滑動即可顯示系統列"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index fc3c625..af790a3 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -203,4 +203,7 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"OKUZENZAKALELAYO"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Izaziso zivela lapha"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Kufinyelele noma kunini ngokuswayiphela phansi."\n"Swayiphela phansi futhi ngezilawuli zesistimu."</string>
+    <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Swayipha kusukela ngaphansi kwesikrini ukuze uveze ibha yesistimu"</string>
+    <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Swayipha ngaphansi kwesikrini ukuze uveze ibha"</string>
+    <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Swayipha kusukela ngakwesokudla ukuze uveze ibha yesistimu"</string>
 </resources>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/RotationToggle.java b/packages/SystemUI/src/com/android/systemui/statusbar/RotationToggle.java
deleted file mode 100644
index 735ee25..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/RotationToggle.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * 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.systemui.statusbar;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.widget.CompoundButton;
-
-import com.android.systemui.statusbar.policy.AutoRotateController;
-
-public class RotationToggle extends CompoundButton
-        implements AutoRotateController.RotationLockCallbacks {
-    private AutoRotateController mRotater;
-
-    public RotationToggle(Context context) {
-        super(context);
-    }
-
-    public RotationToggle(Context context, AttributeSet attrs) {
-        super(context, attrs);
-    }
-
-    public RotationToggle(Context context, AttributeSet attrs, int defStyle) {
-        super(context, attrs, defStyle);
-    }
-
-    @Override
-    protected void onAttachedToWindow() {
-        super.onAttachedToWindow();
-        mRotater = new AutoRotateController(getContext(), this, this);
-    }
-
-    @Override
-    protected void onDetachedFromWindow() {
-        super.onDetachedFromWindow();
-        if (mRotater != null) {
-            mRotater.release();
-            mRotater = null;
-        }
-    }
-
-    @Override
-    public void setRotationLockControlVisibility(boolean show) {
-        setVisibility(show ? VISIBLE : GONE);
-    }
-}
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 6b30b2c..978b36b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -88,6 +88,7 @@
 import com.android.systemui.statusbar.NotificationData.Entry;
 import com.android.systemui.statusbar.SignalClusterView;
 import com.android.systemui.statusbar.StatusBarIconView;
+import com.android.systemui.statusbar.policy.RotationLockController;
 import com.android.systemui.statusbar.policy.BatteryController;
 import com.android.systemui.statusbar.policy.BluetoothController;
 import com.android.systemui.statusbar.policy.DateView;
@@ -161,6 +162,7 @@
     BatteryController mBatteryController;
     LocationController mLocationController;
     NetworkController mNetworkController;
+    RotationLockController mRotationLockController;
 
     int mNaturalBarHeight = -1;
     int mIconSize = -1;
@@ -537,6 +539,7 @@
         mBatteryController.addIconView((ImageView)mStatusBarView.findViewById(R.id.battery));
         mNetworkController = new NetworkController(mContext);
         mBluetoothController = new BluetoothController(mContext);
+        mRotationLockController = new RotationLockController(mContext);
         final SignalClusterView signalCluster =
                 (SignalClusterView)mStatusBarView.findViewById(R.id.signal_cluster);
 
@@ -629,7 +632,7 @@
                 mQS.setService(this);
                 mQS.setBar(mStatusBarView);
                 mQS.setup(mNetworkController, mBluetoothController, mBatteryController,
-                        mLocationController);
+                        mLocationController, mRotationLockController);
             } else {
                 mQS = null; // fly away, be free
             }
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 85bcd8b..b20a8bb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
@@ -16,7 +16,6 @@
 
 package com.android.systemui.statusbar.phone;
 
-import com.android.internal.view.RotationPolicy;
 import com.android.systemui.R;
 
 import com.android.systemui.statusbar.phone.QuickSettingsModel.BluetoothState;
@@ -28,6 +27,7 @@
 import com.android.systemui.statusbar.policy.BluetoothController;
 import com.android.systemui.statusbar.policy.LocationController;
 import com.android.systemui.statusbar.policy.NetworkController;
+import com.android.systemui.statusbar.policy.RotationLockController;
 
 import android.app.ActivityManagerNative;
 import android.app.AlertDialog;
@@ -73,7 +73,6 @@
 
 import java.util.ArrayList;
 
-
 /**
  *
  */
@@ -97,6 +96,7 @@
     private WifiManager mWifiManager;
 
     private BluetoothController mBluetoothController;
+    private RotationLockController mRotationLockController;
 
     private AsyncTask<Void, Void, Pair<String, Drawable>> mUserInfoTask;
 
@@ -113,14 +113,6 @@
     private final ArrayList<QuickSettingsTileView> mDynamicSpannedTiles =
             new ArrayList<QuickSettingsTileView>();
 
-    private final RotationPolicy.RotationPolicyListener mRotationPolicyListener =
-            new RotationPolicy.RotationPolicyListener() {
-        @Override
-        public void onChange() {
-            mModel.onRotationLockChanged();
-        }
-    };
-
     public QuickSettings(Context context, QuickSettingsContainerView container) {
         mDisplayManager = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
         mContext = context;
@@ -170,8 +162,10 @@
     }
 
     void setup(NetworkController networkController, BluetoothController bluetoothController,
-            BatteryController batteryController, LocationController locationController) {
+            BatteryController batteryController, LocationController locationController,
+            RotationLockController rotationLockController) {
         mBluetoothController = bluetoothController;
+        mRotationLockController = rotationLockController;
 
         setupQuickSettings();
         updateWifiDisplayStatus();
@@ -181,8 +175,7 @@
         bluetoothController.addStateChangedCallback(mModel);
         batteryController.addStateChangedCallback(mModel);
         locationController.addStateChangedCallback(mModel);
-        RotationPolicy.registerRotationPolicyListener(mContext, mRotationPolicyListener,
-                UserHandle.USER_ALL);
+        rotationLockController.addRotationLockControllerCallback(mModel);
     }
 
     private void queryForUserInformation() {
@@ -471,13 +464,29 @@
                     = new QuickSettingsBasicTile(mContext);
             rotationLockTile.setOnClickListener(new View.OnClickListener() {
                 @Override
-                public void onClick(View v) {
-                    boolean locked = RotationPolicy.isRotationLocked(mContext);
-                    RotationPolicy.setRotationLock(mContext, !locked);
+                public void onClick(View view) {
+                    final boolean locked = mRotationLockController.isRotationLocked();
+                    mRotationLockController.setRotationLocked(!locked);
                 }
             });
-            mModel.addRotationLockTile(rotationLockTile,
-                    new QuickSettingsModel.BasicRefreshCallback(rotationLockTile));
+            mModel.addRotationLockTile(rotationLockTile, mRotationLockController,
+                    new QuickSettingsModel.RefreshCallback() {
+                        @Override
+                        public void refreshView(QuickSettingsTileView view, State state) {
+                            QuickSettingsModel.RotationLockState rotationLockState =
+                                    (QuickSettingsModel.RotationLockState) state;
+                            view.setVisibility(rotationLockState.visible
+                                    ? View.VISIBLE : View.GONE);
+                            if (state.iconId != 0) {
+                                // needed to flush any cached IDs
+                                rotationLockTile.setImageDrawable(null);
+                                rotationLockTile.setImageResource(state.iconId);
+                            }
+                            if (state.label != null) {
+                                rotationLockTile.setText(state.label);
+                            }
+                        }
+                    });
             parent.addView(rotationLockTile);
         }
 
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 38c46c4..cdfd52e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java
@@ -39,22 +39,23 @@
 import android.view.inputmethod.InputMethodManager;
 import android.view.inputmethod.InputMethodSubtype;
 
-import com.android.internal.view.RotationPolicy;
 import com.android.systemui.R;
 import com.android.systemui.settings.CurrentUserTracker;
 import com.android.systemui.settings.BrightnessController.BrightnessStateChangeCallback;
+import com.android.systemui.statusbar.policy.RotationLockController;
+import com.android.systemui.statusbar.policy.RotationLockController.RotationLockControllerCallback;
 import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback;
 import com.android.systemui.statusbar.policy.LocationController.LocationGpsStateChangeCallback;
 import com.android.systemui.statusbar.policy.NetworkController.NetworkSignalChangedCallback;
 
 import java.util.List;
 
-
 class QuickSettingsModel implements BluetoothStateChangeCallback,
         NetworkSignalChangedCallback,
         BatteryStateChangeCallback,
         LocationGpsStateChangeCallback,
-        BrightnessStateChangeCallback {
+        BrightnessStateChangeCallback,
+        RotationLockControllerCallback {
 
     // Sett InputMethoManagerService
     private static final String TAG_TRY_SUPPRESSING_IME_SWITCHER = "TrySuppressingImeSwitcher";
@@ -89,6 +90,9 @@
         boolean connected = false;
         String stateContentDescription;
     }
+    public static class RotationLockState extends State {
+        boolean visible = false;
+    }
 
     /** The callback to update a given tile. */
     interface RefreshCallback {
@@ -245,7 +249,7 @@
 
     private QuickSettingsTileView mRotationLockTile;
     private RefreshCallback mRotationLockCallback;
-    private State mRotationLockState = new State();
+    private RotationLockState mRotationLockState = new RotationLockState();
 
     private QuickSettingsTileView mBrightnessTile;
     private RefreshCallback mBrightnessCallback;
@@ -259,6 +263,8 @@
     private RefreshCallback mSettingsCallback;
     private State mSettingsState = new State();
 
+    private RotationLockController mRotationLockController;
+
     public QuickSettingsModel(Context context) {
         mContext = context;
         mHandler = new Handler();
@@ -681,25 +687,29 @@
     }
 
     // Rotation lock
-    void addRotationLockTile(QuickSettingsTileView view, RefreshCallback cb) {
+    void addRotationLockTile(QuickSettingsTileView view,
+            RotationLockController rotationLockController,
+            RefreshCallback cb) {
         mRotationLockTile = view;
         mRotationLockCallback = cb;
+        mRotationLockController = rotationLockController;
         onRotationLockChanged();
     }
     void onRotationLockChanged() {
-        boolean locked = RotationPolicy.isRotationLocked(mContext);
-        mRotationLockState.enabled = locked;
-        mRotationLockState.iconId = locked
+        onRotationLockStateChanged(mRotationLockController.isRotationLocked(),
+                mRotationLockController.isRotationLockAffordanceVisible());
+    }
+    @Override
+    public void onRotationLockStateChanged(boolean rotationLocked, boolean affordanceVisible) {
+        mRotationLockState.visible = affordanceVisible;
+        mRotationLockState.enabled = rotationLocked;
+        mRotationLockState.iconId = rotationLocked
                 ? R.drawable.ic_qs_rotation_locked
                 : R.drawable.ic_qs_auto_rotate;
-        mRotationLockState.label = locked
+        mRotationLockState.label = rotationLocked
                 ? mContext.getString(R.string.quick_settings_rotation_locked_label)
                 : mContext.getString(R.string.quick_settings_rotation_unlocked_label);
-
-        // may be called before addRotationLockTile due to RotationPolicyListener in QuickSettings
-        if (mRotationLockTile != null && mRotationLockCallback != null) {
-            mRotationLockCallback.refreshView(mRotationLockTile, mRotationLockState);
-        }
+        mRotationLockCallback.refreshView(mRotationLockTile, mRotationLockState);
     }
     void refreshRotationLockTile() {
         if (mRotationLockTile != null) {
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 33335631..1897589 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsPanelView.java
@@ -38,6 +38,7 @@
 import com.android.systemui.statusbar.policy.BluetoothController;
 import com.android.systemui.statusbar.policy.LocationController;
 import com.android.systemui.statusbar.policy.NetworkController;
+import com.android.systemui.statusbar.policy.RotationLockController;
 
 public class SettingsPanelView extends PanelView {
     public static final boolean DEBUG_GESTURES = true;
@@ -85,10 +86,11 @@
     }
 
     public void setup(NetworkController networkController, BluetoothController bluetoothController,
-            BatteryController batteryController, LocationController locationController) {
+            BatteryController batteryController, LocationController locationController,
+            RotationLockController rotationLockController) {
         if (mQS != null) {
             mQS.setup(networkController, bluetoothController, batteryController,
-                    locationController);
+                    locationController, rotationLockController);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AutoRotateController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AutoRotateController.java
deleted file mode 100644
index 7d58032..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AutoRotateController.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.policy;
-
-import com.android.internal.view.RotationPolicy;
-
-import android.content.Context;
-import android.os.UserHandle;
-import android.widget.CompoundButton;
-
-public final class AutoRotateController implements CompoundButton.OnCheckedChangeListener {
-    private final Context mContext;
-    private final CompoundButton mCheckbox;
-    private final RotationLockCallbacks mCallbacks;
-
-    private boolean mAutoRotation;
-
-    private final RotationPolicy.RotationPolicyListener mRotationPolicyListener =
-            new RotationPolicy.RotationPolicyListener() {
-        @Override
-        public void onChange() {
-            updateState();
-        }
-    };
-
-    public AutoRotateController(Context context, CompoundButton checkbox,
-            RotationLockCallbacks callbacks) {
-        mContext = context;
-        mCheckbox = checkbox;
-        mCallbacks = callbacks;
-
-        mCheckbox.setOnCheckedChangeListener(this);
-
-        RotationPolicy.registerRotationPolicyListener(context, mRotationPolicyListener,
-                UserHandle.USER_ALL);
-        updateState();
-    }
-
-    public void onCheckedChanged(CompoundButton view, boolean checked) {
-        if (checked != mAutoRotation) {
-            mAutoRotation = checked;
-            RotationPolicy.setRotationLock(mContext, !checked);
-        }
-    }
-
-    public void release() {
-        RotationPolicy.unregisterRotationPolicyListener(mContext,
-                mRotationPolicyListener);
-    }
-
-    private void updateState() {
-        mAutoRotation = !RotationPolicy.isRotationLocked(mContext);
-        mCheckbox.setChecked(mAutoRotation);
-
-        boolean visible = RotationPolicy.isRotationLockToggleVisible(mContext);
-        mCallbacks.setRotationLockControlVisibility(visible);
-        mCheckbox.setEnabled(visible);
-    }
-
-    public interface RotationLockCallbacks {
-        void setRotationLockControlVisibility(boolean show);
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RotationLockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RotationLockController.java
new file mode 100644
index 0000000..6f61ec8
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RotationLockController.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.policy;
+
+import android.content.Context;
+import android.os.UserHandle;
+
+import com.android.internal.view.RotationPolicy;
+
+import java.util.concurrent.CopyOnWriteArrayList;
+
+public final class RotationLockController {
+    private final Context mContext;
+    private final CopyOnWriteArrayList<RotationLockControllerCallback> mCallbacks =
+            new CopyOnWriteArrayList<RotationLockControllerCallback>();
+
+    private final RotationPolicy.RotationPolicyListener mRotationPolicyListener =
+            new RotationPolicy.RotationPolicyListener() {
+        @Override
+        public void onChange() {
+            notifyChanged();
+        }
+    };
+
+    public interface RotationLockControllerCallback {
+        public void onRotationLockStateChanged(boolean rotationLocked, boolean affordanceVisible);
+    }
+
+    public RotationLockController(Context context) {
+        mContext = context;
+        notifyChanged();
+        if (RotationPolicy.isRotationLockToggleSupported(mContext)) {
+            RotationPolicy.registerRotationPolicyListener(mContext,
+                    mRotationPolicyListener, UserHandle.USER_ALL);
+        }
+    }
+
+    public void addRotationLockControllerCallback(RotationLockControllerCallback callback) {
+        mCallbacks.add(callback);
+    }
+
+    public boolean isRotationLocked() {
+        if (RotationPolicy.isRotationLockToggleSupported(mContext)) {
+            return RotationPolicy.isRotationLocked(mContext);
+        }
+        return false;
+    }
+
+    public void setRotationLocked(boolean locked) {
+        if (RotationPolicy.isRotationLockToggleSupported(mContext)) {
+            RotationPolicy.setRotationLock(mContext, locked);
+        }
+    }
+
+    public boolean isRotationLockAffordanceVisible() {
+        if (RotationPolicy.isRotationLockToggleSupported(mContext)) {
+            return RotationPolicy.isRotationLockToggleVisible(mContext);
+        }
+        return false;
+    }
+
+    public void release() {
+        if (RotationPolicy.isRotationLockToggleSupported(mContext)) {
+            RotationPolicy.unregisterRotationPolicyListener(mContext,
+                    mRotationPolicyListener);
+        }
+    }
+
+    private void notifyChanged() {
+        for (RotationLockControllerCallback callback : mCallbacks) {
+            callback.onRotationLockStateChanged(RotationPolicy.isRotationLocked(mContext),
+                    RotationPolicy.isRotationLockToggleVisible(mContext));
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/SettingsView.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/SettingsView.java
index e0dcbcd..a55cc9d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/SettingsView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/SettingsView.java
@@ -22,26 +22,23 @@
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.util.AttributeSet;
-import android.util.Slog;
-import android.widget.LinearLayout;
 import android.view.View;
 import android.widget.CompoundButton;
 import android.widget.ImageView;
-import android.widget.TextView;
+import android.widget.LinearLayout;
 
 import com.android.systemui.R;
 import com.android.systemui.settings.BrightnessController;
 import com.android.systemui.settings.ToggleSlider;
 import com.android.systemui.statusbar.policy.AirplaneModeController;
-import com.android.systemui.statusbar.policy.AutoRotateController;
 import com.android.systemui.statusbar.policy.DoNotDisturbController;
-import com.android.systemui.statusbar.policy.VolumeController;
+import com.android.systemui.statusbar.policy.RotationLockController;
 
 public class SettingsView extends LinearLayout implements View.OnClickListener {
     static final String TAG = "SettingsView";
 
     AirplaneModeController mAirplane;
-    AutoRotateController mRotate;
+    RotationLockController mRotationController;
     BrightnessController mBrightness;
     DoNotDisturbController mDoNotDisturb;
     View mRotationLockContainer;
@@ -67,15 +64,25 @@
 
         mRotationLockContainer = findViewById(R.id.rotate);
         mRotationLockSeparator = findViewById(R.id.rotate_separator);
-        mRotate = new AutoRotateController(context,
-                (CompoundButton)findViewById(R.id.rotate_checkbox),
-                new AutoRotateController.RotationLockCallbacks() {
+        mRotationController = new RotationLockController(context);
+        mRotationController.addRotationLockControllerCallback(
+                new RotationLockController.RotationLockControllerCallback() {
                     @Override
-                    public void setRotationLockControlVisibility(boolean show) {
-                        mRotationLockContainer.setVisibility(show ? View.VISIBLE : View.GONE);
-                        mRotationLockSeparator.setVisibility(show ? View.VISIBLE : View.GONE);
+                    public void onRotationLockStateChanged(boolean locked, boolean visible) {
+                        mRotationLockContainer.setVisibility(visible ? View.VISIBLE : View.GONE);
+                        mRotationLockSeparator.setVisibility(visible ? View.VISIBLE : View.GONE);
                     }
                 });
+        CompoundButton rotateCheckbox = (CompoundButton) findViewById(R.id.rotate_checkbox);
+        rotateCheckbox.setChecked(!mRotationController.isRotationLocked());
+        rotateCheckbox.setVisibility(mRotationController.isRotationLockAffordanceVisible()
+                ? View.VISIBLE : View.GONE);
+        rotateCheckbox.setOnCheckedChangeListener(new CompoundButton. OnCheckedChangeListener() {
+            @Override
+            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+                mRotationController.setRotationLocked(!buttonView.isChecked());
+            }
+        });
 
         mBrightness = new BrightnessController(context,
                 (ImageView)findViewById(R.id.brightness_icon),
@@ -90,7 +97,7 @@
         super.onDetachedFromWindow();
         mAirplane.release();
         mDoNotDisturb.release();
-        mRotate.release();
+        mRotationController.release();
     }
 
     public void onClick(View v) {
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index 6b28e8e..085134d 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -139,6 +139,12 @@
     private ActionMenuPresenterCallback mActionMenuPresenterCallback;
     private PanelMenuPresenterCallback mPanelMenuPresenterCallback;
 
+    static final int FLAG_RESOURCE_SET_ICON = 1 << 0;
+    static final int FLAG_RESOURCE_SET_LOGO = 1 << 1;
+    int mResourcesSetFlags;
+    int mIconRes;
+    int mLogoRes;
+
     private DrawableFeatureState[] mDrawables;
 
     private PanelFeatureState[] mPanels;
@@ -1393,6 +1399,46 @@
         }
     }
 
+    @Override
+    public void setIcon(int resId) {
+        mIconRes = resId;
+        mResourcesSetFlags |= FLAG_RESOURCE_SET_ICON;
+        if (mActionBar != null) {
+            mActionBar.setIcon(resId);
+        }
+    }
+
+    @Override
+    public void setDefaultIcon(int resId) {
+        if ((mResourcesSetFlags & FLAG_RESOURCE_SET_ICON) != 0) {
+            return;
+        }
+        mIconRes = resId;
+        if (mActionBar != null && !mActionBar.hasIcon()) {
+            mActionBar.setIcon(resId);
+        }
+    }
+
+    @Override
+    public void setLogo(int resId) {
+        mLogoRes = resId;
+        mResourcesSetFlags |= FLAG_RESOURCE_SET_LOGO;
+        if (mActionBar != null) {
+            mActionBar.setLogo(resId);
+        }
+    }
+
+    @Override
+    public void setDefaultLogo(int resId) {
+        if ((mResourcesSetFlags & FLAG_RESOURCE_SET_LOGO) != 0) {
+            return;
+        }
+        mLogoRes = resId;
+        if (mActionBar != null && !mActionBar.hasLogo()) {
+            mActionBar.setLogo(resId);
+        }
+    }
+
     /**
      * Request that key events come to this activity. Use this if your activity
      * has no views with focus, but the activity still wants a chance to process
@@ -2946,6 +2992,15 @@
                                 "incompatible window decor! Ignoring request.");
                     }
 
+                    if ((mResourcesSetFlags & FLAG_RESOURCE_SET_ICON) != 0 ||
+                            (mIconRes != 0 && !mActionBar.hasIcon())) {
+                        mActionBar.setIcon(mIconRes);
+                    }
+                    if ((mResourcesSetFlags & FLAG_RESOURCE_SET_LOGO) != 0 ||
+                            (mLogoRes != 0 && !mActionBar.hasLogo())) {
+                        mActionBar.setLogo(mLogoRes);
+                    }
+
                     // Post the panel invalidate for later; avoid application onCreateOptionsMenu
                     // being called in the middle of onCreate or similar.
                     mDecor.post(new Runnable() {
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 79753a6..b8a9797 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -1582,7 +1582,7 @@
     @Override
     public View addStartingWindow(IBinder appToken, String packageName, int theme,
             CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes,
-            int icon, int windowFlags) {
+            int icon, int logo, int windowFlags) {
         if (!SHOW_STARTING_ANIMATIONS) {
             return null;
         }
@@ -1639,6 +1639,9 @@
                 win.addFlags(WindowManager.LayoutParams.FLAG_COMPATIBLE_WINDOW);
             }
 
+            win.setDefaultIcon(icon);
+            win.setDefaultLogo(logo);
+
             win.setLayout(WindowManager.LayoutParams.MATCH_PARENT,
                     WindowManager.LayoutParams.MATCH_PARENT);
 
diff --git a/services/java/com/android/server/AlarmManagerService.java b/services/java/com/android/server/AlarmManagerService.java
index fa758a8..bc06561 100644
--- a/services/java/com/android/server/AlarmManagerService.java
+++ b/services/java/com/android/server/AlarmManagerService.java
@@ -351,12 +351,11 @@
         }
 
         // iterator over the list removing any it where the intent match
-        Iterator<Alarm> it = alarmList.iterator();
-        
-        while (it.hasNext()) {
-            Alarm alarm = it.next();
+        for (int i=0; i<alarmList.size(); i++) {
+            Alarm alarm = alarmList.get(i);
             if (alarm.operation.equals(operation)) {
-                it.remove();
+                alarmList.remove(i);
+                i--;
             }
         }
     }
@@ -375,12 +374,11 @@
         }
 
         // iterator over the list removing any it where the intent match
-        Iterator<Alarm> it = alarmList.iterator();
-        
-        while (it.hasNext()) {
-            Alarm alarm = it.next();
+        for (int i=0; i<alarmList.size(); i++) {
+            Alarm alarm = alarmList.get(i);
             if (alarm.operation.getTargetPackage().equals(packageName)) {
-                it.remove();
+                alarmList.remove(i);
+                i--;
             }
         }
     }
@@ -398,12 +396,11 @@
         }
 
         // iterator over the list removing any it where the intent match
-        Iterator<Alarm> it = alarmList.iterator();
-
-        while (it.hasNext()) {
-            Alarm alarm = it.next();
+        for (int i=0; i<alarmList.size(); i++) {
+            Alarm alarm = alarmList.get(i);
             if (UserHandle.getUserId(alarm.operation.getCreatorUid()) == userHandle) {
-                it.remove();
+                alarmList.remove(i);
+                i--;
             }
         }
     }
@@ -666,12 +663,10 @@
                                      ArrayList<Alarm> triggerList,
                                      long now)
     {
-        Iterator<Alarm> it = alarmList.iterator();
-        ArrayList<Alarm> repeats = new ArrayList<Alarm>();
-        
-        while (it.hasNext())
-        {
-            Alarm alarm = it.next();
+        ArrayList<Alarm> repeats = null;
+
+        for (int i=0; i<alarmList.size(); i++) {
+            Alarm alarm = alarmList.get(i);
 
             if (localLOGV) Slog.v(TAG, "Checking active alarm when=" + alarm.when + " " + alarm);
 
@@ -702,20 +697,25 @@
             triggerList.add(alarm);
             
             // remove the alarm from the list
-            it.remove();
-            
+            alarmList.remove(i);
+            i--;
+
             // if it repeats queue it up to be read-added to the list
             if (alarm.repeatInterval > 0) {
+                if (repeats == null) {
+                    repeats = new ArrayList<Alarm>();
+                }
                 repeats.add(alarm);
             }
         }
 
         // reset any repeating alarms.
-        it = repeats.iterator();
-        while (it.hasNext()) {
-            Alarm alarm = it.next();
-            alarm.when += alarm.count * alarm.repeatInterval;
-            addAlarmLocked(alarm);
+        if (repeats != null) {
+            for (int i=0; i<repeats.size(); i++) {
+                Alarm alarm = repeats.get(i);
+                alarm.when += alarm.count * alarm.repeatInterval;
+                addAlarmLocked(alarm);
+            }
         }
         
         if (alarmList.size() > 0) {
@@ -785,12 +785,14 @@
         
         public void run()
         {
+            ArrayList<Alarm> triggerList = new ArrayList<Alarm>();
+
             while (true)
             {
                 int result = waitForAlarm(mDescriptor);
-                
-                ArrayList<Alarm> triggerList = new ArrayList<Alarm>();
-                
+
+                triggerList.clear();
+
                 if ((result & TIME_CHANGED_MASK) != 0) {
                     remove(mTimeTickSender);
                     mClockReceiver.scheduleTimeTickEvent();
@@ -820,9 +822,8 @@
                         triggerAlarmsLocked(mElapsedRealtimeAlarms, triggerList, nowELAPSED);
                     
                     // now trigger the alarms
-                    Iterator<Alarm> it = triggerList.iterator();
-                    while (it.hasNext()) {
-                        Alarm alarm = it.next();
+                    for (int i=0; i<triggerList.size(); i++) {
+                        Alarm alarm = triggerList.get(i);
                         try {
                             if (localLOGV) Slog.v(TAG, "sending alarm " + alarm);
                             alarm.operation.send(mContext, 0,
@@ -913,10 +914,8 @@
                 }
                 
                 // now trigger the alarms without the lock held
-                Iterator<Alarm> it = triggerList.iterator();
-                while (it.hasNext())
-                {
-                    Alarm alarm = it.next();
+                for (int i=0; i<triggerList.size(); i++) {
+                    Alarm alarm = triggerList.get(i);
                     try {
                         alarm.operation.send();
                     } catch (PendingIntent.CanceledException e) {
diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java
index 016a664..0bf3a11 100644
--- a/services/java/com/android/server/LocationManagerService.java
+++ b/services/java/com/android/server/LocationManagerService.java
@@ -135,8 +135,8 @@
     // --- fields below are final after systemReady() ---
     private LocationFudger mLocationFudger;
     private GeofenceManager mGeofenceManager;
-    private PowerManager.WakeLock mWakeLock;
     private PackageManager mPackageManager;
+    private PowerManager mPowerManager;
     private GeocoderProxy mGeocodeProvider;
     private IGpsStatusProvider mGpsStatusProvider;
     private INetInitiatedListener mNetInitiatedListener;
@@ -144,9 +144,6 @@
     private PassiveProvider mPassiveProvider;  // track passive provider for special cases
     private LocationBlacklist mBlacklist;
 
-    // --- fields below are protected by mWakeLock ---
-    private int mPendingBroadcasts;
-
     // --- fields below are protected by mLock ---
     // Set of providers that are explicitly enabled
     private final Set<String> mEnabledProviders = new HashSet<String>();
@@ -209,10 +206,8 @@
             // fetch package manager
             mPackageManager = mContext.getPackageManager();
 
-            // prepare wake lock
-            PowerManager powerManager =
-                    (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
-            mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
+            // fetch power manager
+            mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
 
             // prepare worker thread
             mLocationHandler = new LocationWorkerHandler(BackgroundThread.get().getLooper());
@@ -466,6 +461,7 @@
         final HashMap<String,UpdateRecord> mUpdateRecords = new HashMap<String,UpdateRecord>();
 
         int mPendingBroadcasts;
+        PowerManager.WakeLock mWakeLock;
 
         Receiver(ILocationListener listener, PendingIntent intent, int pid, int uid,
                 String packageName) {
@@ -480,6 +476,10 @@
             mUid = uid;
             mPid = pid;
             mPackageName = packageName;
+
+            // construct/configure wakelock
+            mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
+            mWakeLock.setWorkSource(new WorkSource(mUid, mPackageName));
         }
 
         @Override
@@ -642,10 +642,7 @@
                 removeUpdatesLocked(this);
             }
             synchronized (this) {
-                if (mPendingBroadcasts > 0) {
-                    LocationManagerService.this.decrementPendingBroadcasts();
-                    mPendingBroadcasts = 0;
-                }
+                clearPendingBroadcastsLocked();
             }
         }
 
@@ -661,13 +658,24 @@
         // containing the sending of the broadcaset
         private void incrementPendingBroadcastsLocked() {
             if (mPendingBroadcasts++ == 0) {
-                LocationManagerService.this.incrementPendingBroadcasts();
+                mWakeLock.acquire();
             }
         }
 
         private void decrementPendingBroadcastsLocked() {
             if (--mPendingBroadcasts == 0) {
-                LocationManagerService.this.decrementPendingBroadcasts();
+                if (mWakeLock.isHeld()) {
+                    mWakeLock.release();
+                }
+            }
+        }
+
+        public void clearPendingBroadcastsLocked() {
+            if (mPendingBroadcasts > 0) {
+                mPendingBroadcasts = 0;
+                if (mWakeLock.isHeld()) {
+                    mWakeLock.release();
+                }
             }
         }
     }
@@ -1349,10 +1357,7 @@
         if (mReceivers.remove(receiver.mKey) != null && receiver.isListener()) {
             receiver.getListener().asBinder().unlinkToDeath(receiver, 0);
             synchronized (receiver) {
-                if (receiver.mPendingBroadcasts > 0) {
-                    decrementPendingBroadcasts();
-                    receiver.mPendingBroadcasts = 0;
-                }
+                receiver.clearPendingBroadcastsLocked();
             }
         }
 
@@ -1954,43 +1959,6 @@
         }
     };
 
-    // Wake locks
-
-    private void incrementPendingBroadcasts() {
-        synchronized (mWakeLock) {
-            if (mPendingBroadcasts++ == 0) {
-                try {
-                    mWakeLock.acquire();
-                    log("Acquired wakelock");
-                } catch (Exception e) {
-                    // This is to catch a runtime exception thrown when we try to release an
-                    // already released lock.
-                    Slog.e(TAG, "exception in acquireWakeLock()", e);
-                }
-            }
-        }
-    }
-
-    private void decrementPendingBroadcasts() {
-        synchronized (mWakeLock) {
-            if (--mPendingBroadcasts == 0) {
-                try {
-                    // Release wake lock
-                    if (mWakeLock.isHeld()) {
-                        mWakeLock.release();
-                        log("Released wakelock");
-                    } else {
-                        log("Can't release wakelock again!");
-                    }
-                } catch (Exception e) {
-                    // This is to catch a runtime exception thrown when we try to release an
-                    // already released lock.
-                    Slog.e(TAG, "exception in releaseWakeLock()", e);
-                }
-            }
-        }
-    }
-
     // Geocoder
 
     @Override
diff --git a/services/java/com/android/server/am/ActiveServices.java b/services/java/com/android/server/am/ActiveServices.java
index 10db70f..84e44bd 100644
--- a/services/java/com/android/server/am/ActiveServices.java
+++ b/services/java/com/android/server/am/ActiveServices.java
@@ -574,30 +574,26 @@
                     b.binder = service;
                     b.requested = true;
                     b.received = true;
-                    if (r.connections.size() > 0) {
-                        Iterator<ArrayList<ConnectionRecord>> it
-                                = r.connections.values().iterator();
-                        while (it.hasNext()) {
-                            ArrayList<ConnectionRecord> clist = it.next();
-                            for (int i=0; i<clist.size(); i++) {
-                                ConnectionRecord c = clist.get(i);
-                                if (!filter.equals(c.binding.intent.intent)) {
-                                    if (DEBUG_SERVICE) Slog.v(
-                                            TAG, "Not publishing to: " + c);
-                                    if (DEBUG_SERVICE) Slog.v(
-                                            TAG, "Bound intent: " + c.binding.intent.intent);
-                                    if (DEBUG_SERVICE) Slog.v(
-                                            TAG, "Published intent: " + intent);
-                                    continue;
-                                }
-                                if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
-                                try {
-                                    c.conn.connected(r.name, service);
-                                } catch (Exception e) {
-                                    Slog.w(TAG, "Failure sending service " + r.name +
-                                          " to connection " + c.conn.asBinder() +
-                                          " (in " + c.binding.client.processName + ")", e);
-                                }
+                    for (int conni=r.connections.size()-1; conni>=0; conni--) {
+                        ArrayList<ConnectionRecord> clist = r.connections.valueAt(conni);
+                        for (int i=0; i<clist.size(); i++) {
+                            ConnectionRecord c = clist.get(i);
+                            if (!filter.equals(c.binding.intent.intent)) {
+                                if (DEBUG_SERVICE) Slog.v(
+                                        TAG, "Not publishing to: " + c);
+                                if (DEBUG_SERVICE) Slog.v(
+                                        TAG, "Bound intent: " + c.binding.intent.intent);
+                                if (DEBUG_SERVICE) Slog.v(
+                                        TAG, "Published intent: " + intent);
+                                continue;
+                            }
+                            if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
+                            try {
+                                c.conn.connected(r.name, service);
+                            } catch (Exception e) {
+                                Slog.w(TAG, "Failure sending service " + r.name +
+                                      " to connection " + c.conn.asBinder() +
+                                      " (in " + c.binding.client.processName + ")", e);
                             }
                         }
                     }
@@ -1064,10 +1060,9 @@
     }
 
     private final void requestServiceBindingsLocked(ServiceRecord r) {
-        Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
-        while (bindings.hasNext()) {
-            IntentBindRecord i = bindings.next();
-            if (!requestServiceBindingLocked(r, i, false)) {
+        for (int i=r.bindings.size()-1; i>=0; i--) {
+            IntentBindRecord ibr = r.bindings.valueAt(i);
+            if (!requestServiceBindingLocked(r, ibr, false)) {
                 break;
             }
         }
@@ -1179,50 +1174,45 @@
         if (!force && r.startRequested) {
             return;
         }
-        if (r.connections.size() > 0) {
-            if (!force) {
-                // XXX should probably keep a count of the number of auto-create
-                // connections directly in the service.
-                Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
-                while (it.hasNext()) {
-                    ArrayList<ConnectionRecord> cr = it.next();
-                    for (int i=0; i<cr.size(); i++) {
-                        if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) {
-                            return;
-                        }
-                    }
-                }
-            }
-
-            // Report to all of the connections that the service is no longer
-            // available.
-            Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
-            while (it.hasNext()) {
-                ArrayList<ConnectionRecord> c = it.next();
-                for (int i=0; i<c.size(); i++) {
-                    ConnectionRecord cr = c.get(i);
-                    // There is still a connection to the service that is
-                    // being brought down.  Mark it as dead.
-                    cr.serviceDead = true;
-                    try {
-                        cr.conn.connected(r.name, null);
-                    } catch (Exception e) {
-                        Slog.w(TAG, "Failure disconnecting service " + r.name +
-                              " to connection " + c.get(i).conn.asBinder() +
-                              " (in " + c.get(i).binding.client.processName + ")", e);
+        if (!force) {
+            // XXX should probably keep a count of the number of auto-create
+            // connections directly in the service.
+            for (int conni=r.connections.size()-1; conni>=0; conni--) {
+                ArrayList<ConnectionRecord> cr = r.connections.valueAt(conni);
+                for (int i=0; i<cr.size(); i++) {
+                    if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) {
+                        return;
                     }
                 }
             }
         }
 
+        // Report to all of the connections that the service is no longer
+        // available.
+        for (int conni=r.connections.size()-1; conni>=0; conni--) {
+            ArrayList<ConnectionRecord> c = r.connections.valueAt(conni);
+            for (int i=0; i<c.size(); i++) {
+                ConnectionRecord cr = c.get(i);
+                // There is still a connection to the service that is
+                // being brought down.  Mark it as dead.
+                cr.serviceDead = true;
+                try {
+                    cr.conn.connected(r.name, null);
+                } catch (Exception e) {
+                    Slog.w(TAG, "Failure disconnecting service " + r.name +
+                          " to connection " + c.get(i).conn.asBinder() +
+                          " (in " + c.get(i).binding.client.processName + ")", e);
+                }
+            }
+        }
+
         // Tell the service that it has been unbound.
-        if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
-            Iterator<IntentBindRecord> it = r.bindings.values().iterator();
-            while (it.hasNext()) {
-                IntentBindRecord ibr = it.next();
+        if (r.app != null && r.app.thread != null) {
+            for (int i=r.bindings.size()-1; i>=0; i--) {
+                IntentBindRecord ibr = r.bindings.valueAt(i);
                 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
                         + ": hasBound=" + ibr.hasBound);
-                if (r.app != null && r.app.thread != null && ibr.hasBound) {
+                if (ibr.hasBound) {
                     try {
                         bumpServiceExecutingLocked(r, "bring down unbind");
                         mAm.updateOomAdjLocked(r.app);
@@ -1595,22 +1585,18 @@
                 Iterator<ServiceRecord> it = app.services.iterator();
                 while (it.hasNext()) {
                     ServiceRecord r = it.next();
-                    if (r.connections.size() > 0) {
-                        Iterator<ArrayList<ConnectionRecord>> jt
-                                = r.connections.values().iterator();
-                        while (jt.hasNext()) {
-                            ArrayList<ConnectionRecord> cl = jt.next();
-                            for (int i=0; i<cl.size(); i++) {
-                                ConnectionRecord c = cl.get(i);
-                                if (c.binding.client != app) {
-                                    try {
-                                        //c.conn.connected(r.className, null);
-                                    } catch (Exception e) {
-                                        // todo: this should be asynchronous!
-                                        Slog.w(TAG, "Exception thrown disconnected servce "
-                                              + r.shortName
-                                              + " from app " + app.processName, e);
-                                    }
+                    for (int conni=r.connections.size()-1; conni>=0; conni--) {
+                        ArrayList<ConnectionRecord> cl = r.connections.valueAt(conni);
+                        for (int i=0; i<cl.size(); i++) {
+                            ConnectionRecord c = cl.get(i);
+                            if (c.binding.client != app) {
+                                try {
+                                    //c.conn.connected(r.className, null);
+                                } catch (Exception e) {
+                                    // todo: this should be asynchronous!
+                                    Slog.w(TAG, "Exception thrown disconnected servce "
+                                          + r.shortName
+                                          + " from app " + app.processName, e);
                                 }
                             }
                         }
@@ -1645,17 +1631,13 @@
                     if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
                 }
 
-                boolean hasClients = sr.bindings.size() > 0;
-                if (hasClients) {
-                    Iterator<IntentBindRecord> bindings
-                            = sr.bindings.values().iterator();
-                    while (bindings.hasNext()) {
-                        IntentBindRecord b = bindings.next();
-                        if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
-                                + ": shouldUnbind=" + b.hasBound);
-                        b.binder = null;
-                        b.requested = b.received = b.hasBound = false;
-                    }
+                final int numClients = sr.bindings.size();
+                for (int bindingi=numClients-1; bindingi>=0; bindingi--) {
+                    IntentBindRecord b = sr.bindings.valueAt(bindingi);
+                    if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
+                            + ": shouldUnbind=" + b.hasBound);
+                    b.binder = null;
+                    b.requested = b.received = b.hasBound = false;
                 }
 
                 if (sr.crashCount >= 2 && (sr.serviceInfo.applicationInfo.flags
@@ -1676,7 +1658,7 @@
                     if (sr.startRequested && (sr.stopIfKilled || canceled)) {
                         if (sr.pendingStarts.size() == 0) {
                             sr.startRequested = false;
-                            if (!hasClients) {
+                            if (numClients > 0) {
                                 // Whoops, no reason to restart!
                                 bringDownServiceLocked(sr, true);
                             }
@@ -1732,7 +1714,8 @@
             info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
         }
 
-        for (ArrayList<ConnectionRecord> connl : r.connections.values()) {
+        for (int conni=r.connections.size()-1; conni>=0; conni--) {
+            ArrayList<ConnectionRecord> connl = r.connections.valueAt(conni);
             for (int i=0; i<connl.size(); i++) {
                 ConnectionRecord conn = connl.get(i);
                 if (conn.clientLabel != 0) {
@@ -1805,7 +1788,8 @@
         int userId = UserHandle.getUserId(Binder.getCallingUid());
         ServiceRecord r = mServiceMap.getServiceByName(name, userId);
         if (r != null) {
-            for (ArrayList<ConnectionRecord> conn : r.connections.values()) {
+            for (int conni=r.connections.size()-1; conni>=0; conni--) {
+                ArrayList<ConnectionRecord> conn = r.connections.valueAt(conni);
                 for (int i=0; i<conn.size(); i++) {
                     if (conn.get(i).clientIntent != null) {
                         return conn.get(i).clientIntent;
@@ -1859,6 +1843,7 @@
     boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
             int opti, boolean dumpAll, boolean dumpClient, String dumpPackage) {
         boolean needSep = false;
+        boolean needSepResult = false;
 
         ItemMatcher matcher = new ItemMatcher();
         matcher.build(args, opti);
@@ -1881,6 +1866,7 @@
                         if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
                             continue;
                         }
+                        needSepResult = true;
                         if (!printed) {
                             if (user != 0) {
                                 pw.println();
@@ -1907,7 +1893,8 @@
                             pw.println(r.connections.size());
                             if (r.connections.size() > 0) {
                                 pw.println("    Connections:");
-                                for (ArrayList<ConnectionRecord> clist : r.connections.values()) {
+                                for (int conni=0; conni<=r.connections.size(); conni++) {
+                                    ArrayList<ConnectionRecord> clist = r.connections.valueAt(conni);
                                     for (int i = 0; i < clist.size(); i++) {
                                         ConnectionRecord conn = clist.get(i);
                                         pw.print("      ");
@@ -1960,6 +1947,7 @@
                 if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
                     continue;
                 }
+                needSepResult = true;
                 if (!printed) {
                     if (needSep) pw.println(" ");
                     needSep = true;
@@ -1982,6 +1970,7 @@
                 if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
                     continue;
                 }
+                needSepResult = true;
                 if (!printed) {
                     if (needSep) pw.println(" ");
                     needSep = true;
@@ -2004,6 +1993,7 @@
                 if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
                     continue;
                 }
+                needSepResult = true;
                 if (!printed) {
                     if (needSep) pw.println(" ");
                     needSep = true;
@@ -2032,6 +2022,7 @@
                                 || !dumpPackage.equals(cr.binding.client.info.packageName))) {
                             continue;
                         }
+                        needSepResult = true;
                         if (!printed) {
                             if (needSep) pw.println(" ");
                             needSep = true;
@@ -2042,11 +2033,10 @@
                         cr.dump(pw, "    ");
                     }
                 }
-                needSep = true;
             }
         }
 
-        return needSep;
+        return needSepResult;
     }
 
     /**
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index ed6dcce..8d71cf9 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -6515,6 +6515,7 @@
         int userId = app.userId;
         if (providers != null) {
             int N = providers.size();
+            app.pubProviders.ensureCapacity(N + app.pubProviders.size());
             for (int i=0; i<N; i++) {
                 ProviderInfo cpi =
                     (ProviderInfo)providers.get(i);
@@ -6527,6 +6528,7 @@
                     // it runs in the process of the default user.  Get rid of it.
                     providers.remove(i);
                     N--;
+                    i--;
                     continue;
                 }
 
@@ -10098,6 +10100,7 @@
 
     boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
             int opti, boolean dumpAll, String dumpPackage) {
+        boolean dumpedHeader = false;
         boolean needSep = false;
         boolean onlyHistory = false;
 
@@ -10193,14 +10196,14 @@
 
     boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
             int opti, boolean dumpAll, String dumpPackage) {
-        boolean needSep = true;
+        boolean needSep;
 
         ItemMatcher matcher = new ItemMatcher();
         matcher.build(args, opti);
 
         pw.println("ACTIVITY MANAGER CONTENT PROVIDERS (dumpsys activity providers)");
 
-        mProviderMap.dumpProvidersLocked(pw, dumpAll);
+        needSep = mProviderMap.dumpProvidersLocked(pw, dumpAll, dumpPackage);
 
         if (mLaunchingProviders.size() > 0) {
             boolean printed = false;
@@ -10221,13 +10224,28 @@
         }
 
         if (mGrantedUriPermissions.size() > 0) {
-            if (needSep) pw.println();
-            needSep = true;
-            pw.println("Granted Uri Permissions:");
+            boolean printed = false;
+            int dumpUid = -1;
+            if (dumpPackage != null) {
+                try {
+                    dumpUid = mContext.getPackageManager().getPackageUid(dumpPackage, 0);
+                } catch (NameNotFoundException e) {
+                    dumpUid = -1;
+                }
+            }
             for (int i=0; i<mGrantedUriPermissions.size(); i++) {
                 int uid = mGrantedUriPermissions.keyAt(i);
+                if (dumpUid >= 0 && UserHandle.getAppId(uid) != dumpUid) {
+                    continue;
+                }
                 HashMap<Uri, UriPermission> perms
                         = mGrantedUriPermissions.valueAt(i);
+                if (!printed) {
+                    if (needSep) pw.println();
+                    needSep = true;
+                    pw.println("  Granted Uri Permissions:");
+                    printed = true;
+                }
                 pw.print("  * UID "); pw.print(uid);
                         pw.println(" holds:");
                 for (UriPermission perm : perms.values()) {
@@ -10237,7 +10255,6 @@
                     }
                 }
             }
-            needSep = true;
         }
         
         return needSep;
@@ -11024,24 +11041,20 @@
         boolean restart = false;
 
         // Remove published content providers.
-        if (!app.pubProviders.isEmpty()) {
-            Iterator<ContentProviderRecord> it = app.pubProviders.values().iterator();
-            while (it.hasNext()) {
-                ContentProviderRecord cpr = it.next();
-
-                final boolean always = app.bad || !allowRestart;
-                if (removeDyingProviderLocked(app, cpr, always) || always) {
-                    // We left the provider in the launching list, need to
-                    // restart it.
-                    restart = true;
-                }
-
-                cpr.provider = null;
-                cpr.proc = null;
+        for (int i=app.pubProviders.size()-1; i>=0; i--) {
+            ContentProviderRecord cpr = app.pubProviders.valueAt(i);
+            final boolean always = app.bad || !allowRestart;
+            if (removeDyingProviderLocked(app, cpr, always) || always) {
+                // We left the provider in the launching list, need to
+                // restart it.
+                restart = true;
             }
-            app.pubProviders.clear();
+
+            cpr.provider = null;
+            cpr.proc = null;
         }
-        
+        app.pubProviders.clear();
+
         // Take care of any launching providers waiting for this process.
         if (checkAppInLaunchingProvidersLocked(app, false)) {
             restart = true;
@@ -13118,158 +13131,159 @@
                     // has said it is doing work.
                     app.keeping = true;
                 }
-                if (s.connections.size() > 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
-                        || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
-                    Iterator<ArrayList<ConnectionRecord>> kt
-                            = s.connections.values().iterator();
-                    while (kt.hasNext() && adj > ProcessList.FOREGROUND_APP_ADJ) {
-                        ArrayList<ConnectionRecord> clist = kt.next();
-                        for (int i=0; i<clist.size() && adj > ProcessList.FOREGROUND_APP_ADJ; i++) {
-                            // XXX should compute this based on the max of
-                            // all connected clients.
-                            ConnectionRecord cr = clist.get(i);
-                            if (cr.binding.client == app) {
-                                // Binding to ourself is not interesting.
-                                continue;
+                for (int conni = s.connections.size()-1;
+                        conni >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
+                                || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE);
+                        conni--) {
+                    ArrayList<ConnectionRecord> clist = s.connections.valueAt(conni);
+                    for (int i = 0;
+                            i < clist.size() && (adj > ProcessList.FOREGROUND_APP_ADJ
+                                    || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE);
+                            i++) {
+                        // XXX should compute this based on the max of
+                        // all connected clients.
+                        ConnectionRecord cr = clist.get(i);
+                        if (cr.binding.client == app) {
+                            // Binding to ourself is not interesting.
+                            continue;
+                        }
+                        if ((cr.flags&Context.BIND_WAIVE_PRIORITY) == 0) {
+                            ProcessRecord client = cr.binding.client;
+                            int clientAdj = adj;
+                            int myHiddenAdj = hiddenAdj;
+                            if (myHiddenAdj > client.hiddenAdj) {
+                                if (client.hiddenAdj >= ProcessList.VISIBLE_APP_ADJ) {
+                                    myHiddenAdj = client.hiddenAdj;
+                                } else {
+                                    myHiddenAdj = ProcessList.VISIBLE_APP_ADJ;
+                                }
                             }
-                            if ((cr.flags&Context.BIND_WAIVE_PRIORITY) == 0) {
-                                ProcessRecord client = cr.binding.client;
-                                int clientAdj = adj;
-                                int myHiddenAdj = hiddenAdj;
-                                if (myHiddenAdj > client.hiddenAdj) {
-                                    if (client.hiddenAdj >= ProcessList.VISIBLE_APP_ADJ) {
-                                        myHiddenAdj = client.hiddenAdj;
-                                    } else {
-                                        myHiddenAdj = ProcessList.VISIBLE_APP_ADJ;
-                                    }
+                            int myClientHiddenAdj = clientHiddenAdj;
+                            if (myClientHiddenAdj > client.clientHiddenAdj) {
+                                if (client.clientHiddenAdj >= ProcessList.VISIBLE_APP_ADJ) {
+                                    myClientHiddenAdj = client.clientHiddenAdj;
+                                } else {
+                                    myClientHiddenAdj = ProcessList.VISIBLE_APP_ADJ;
                                 }
-                                int myClientHiddenAdj = clientHiddenAdj;
-                                if (myClientHiddenAdj > client.clientHiddenAdj) {
-                                    if (client.clientHiddenAdj >= ProcessList.VISIBLE_APP_ADJ) {
-                                        myClientHiddenAdj = client.clientHiddenAdj;
-                                    } else {
-                                        myClientHiddenAdj = ProcessList.VISIBLE_APP_ADJ;
-                                    }
+                            }
+                            int myEmptyAdj = emptyAdj;
+                            if (myEmptyAdj > client.emptyAdj) {
+                                if (client.emptyAdj >= ProcessList.VISIBLE_APP_ADJ) {
+                                    myEmptyAdj = client.emptyAdj;
+                                } else {
+                                    myEmptyAdj = ProcessList.VISIBLE_APP_ADJ;
                                 }
-                                int myEmptyAdj = emptyAdj;
-                                if (myEmptyAdj > client.emptyAdj) {
-                                    if (client.emptyAdj >= ProcessList.VISIBLE_APP_ADJ) {
-                                        myEmptyAdj = client.emptyAdj;
-                                    } else {
-                                        myEmptyAdj = ProcessList.VISIBLE_APP_ADJ;
-                                    }
-                                }
-                                clientAdj = computeOomAdjLocked(client, myHiddenAdj,
-                                        myClientHiddenAdj, myEmptyAdj, TOP_APP, true, doingAll);
-                                String adjType = null;
-                                if ((cr.flags&Context.BIND_ALLOW_OOM_MANAGEMENT) != 0) {
-                                    // Not doing bind OOM management, so treat
-                                    // this guy more like a started service.
-                                    if (app.hasShownUi && app != mHomeProcess) {
-                                        // If this process has shown some UI, let it immediately
-                                        // go to the LRU list because it may be pretty heavy with
-                                        // UI stuff.  We'll tag it with a label just to help
-                                        // debug and understand what is going on.
-                                        if (adj > clientAdj) {
-                                            adjType = "bound-bg-ui-services";
-                                        }
-                                        app.hidden = false;
-                                        clientAdj = adj;
-                                    } else {
-                                        if (now >= (s.lastActivity
-                                                + ActiveServices.MAX_SERVICE_INACTIVITY)) {
-                                            // This service has not seen activity within
-                                            // recent memory, so allow it to drop to the
-                                            // LRU list if there is no other reason to keep
-                                            // it around.  We'll also tag it with a label just
-                                            // to help debug and undertand what is going on.
-                                            if (adj > clientAdj) {
-                                                adjType = "bound-bg-services";
-                                            }
-                                            clientAdj = adj;
-                                        }
-                                    }
-                                } else if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
-                                    if ((cr.flags&Context.BIND_NOT_VISIBLE) == 0) {
-                                        // If this connection is keeping the service
-                                        // created, then we want to try to better follow
-                                        // its memory management semantics for activities.
-                                        // That is, if it is sitting in the background
-                                        // LRU list as a hidden process (with activities),
-                                        // we don't want the service it is connected to
-                                        // to go into the empty LRU and quickly get killed,
-                                        // because I'll we'll do is just end up restarting
-                                        // the service.
-                                        app.hasClientActivities |= client.hasActivities;
-                                    }
-                                }
-                                if (adj > clientAdj) {
-                                    // If this process has recently shown UI, and
-                                    // the process that is binding to it is less
-                                    // important than being visible, then we don't
-                                    // care about the binding as much as we care
-                                    // about letting this process get into the LRU
-                                    // list to be killed and restarted if needed for
-                                    // memory.
-                                    if (app.hasShownUi && app != mHomeProcess
-                                            && clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
+                            }
+                            clientAdj = computeOomAdjLocked(client, myHiddenAdj,
+                                    myClientHiddenAdj, myEmptyAdj, TOP_APP, true, doingAll);
+                            String adjType = null;
+                            if ((cr.flags&Context.BIND_ALLOW_OOM_MANAGEMENT) != 0) {
+                                // Not doing bind OOM management, so treat
+                                // this guy more like a started service.
+                                if (app.hasShownUi && app != mHomeProcess) {
+                                    // If this process has shown some UI, let it immediately
+                                    // go to the LRU list because it may be pretty heavy with
+                                    // UI stuff.  We'll tag it with a label just to help
+                                    // debug and understand what is going on.
+                                    if (adj > clientAdj) {
                                         adjType = "bound-bg-ui-services";
-                                    } else {
-                                        if ((cr.flags&(Context.BIND_ABOVE_CLIENT
-                                                |Context.BIND_IMPORTANT)) != 0) {
-                                            adj = clientAdj;
-                                        } else if ((cr.flags&Context.BIND_NOT_VISIBLE) != 0
-                                                && clientAdj < ProcessList.PERCEPTIBLE_APP_ADJ
-                                                && adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
-                                            adj = ProcessList.PERCEPTIBLE_APP_ADJ;
-                                        } else if (clientAdj > ProcessList.VISIBLE_APP_ADJ) {
-                                            adj = clientAdj;
-                                        } else {
-                                            app.pendingUiClean = true;
-                                            if (adj > ProcessList.VISIBLE_APP_ADJ) {
-                                                adj = ProcessList.VISIBLE_APP_ADJ;
-                                            }
-                                        }
-                                        if (!client.hidden) {
-                                            app.hidden = false;
-                                        }
-                                        if (client.keeping) {
-                                            app.keeping = true;
-                                        }
-                                        adjType = "service";
-                                    }
-                                }
-                                if (adjType != null) {
-                                    app.adjType = adjType;
-                                    app.adjTypeCode = ActivityManager.RunningAppProcessInfo
-                                            .REASON_SERVICE_IN_USE;
-                                    app.adjSource = cr.binding.client;
-                                    app.adjSourceOom = clientAdj;
-                                    app.adjTarget = s.name;
-                                }
-                                if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
-                                    if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
-                                        schedGroup = Process.THREAD_GROUP_DEFAULT;
-                                    }
-                                }
-                            }
-                            final ActivityRecord a = cr.activity;
-                            if ((cr.flags&Context.BIND_ADJUST_WITH_ACTIVITY) != 0) {
-                                if (a != null && adj > ProcessList.FOREGROUND_APP_ADJ &&
-                                        (a.visible || a.state == ActivityState.RESUMED
-                                         || a.state == ActivityState.PAUSING)) {
-                                    adj = ProcessList.FOREGROUND_APP_ADJ;
-                                    if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
-                                        schedGroup = Process.THREAD_GROUP_DEFAULT;
                                     }
                                     app.hidden = false;
-                                    app.adjType = "service";
-                                    app.adjTypeCode = ActivityManager.RunningAppProcessInfo
-                                            .REASON_SERVICE_IN_USE;
-                                    app.adjSource = a;
-                                    app.adjSourceOom = adj;
-                                    app.adjTarget = s.name;
+                                    clientAdj = adj;
+                                } else {
+                                    if (now >= (s.lastActivity
+                                            + ActiveServices.MAX_SERVICE_INACTIVITY)) {
+                                        // This service has not seen activity within
+                                        // recent memory, so allow it to drop to the
+                                        // LRU list if there is no other reason to keep
+                                        // it around.  We'll also tag it with a label just
+                                        // to help debug and undertand what is going on.
+                                        if (adj > clientAdj) {
+                                            adjType = "bound-bg-services";
+                                        }
+                                        clientAdj = adj;
+                                    }
                                 }
+                            } else if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
+                                if ((cr.flags&Context.BIND_NOT_VISIBLE) == 0) {
+                                    // If this connection is keeping the service
+                                    // created, then we want to try to better follow
+                                    // its memory management semantics for activities.
+                                    // That is, if it is sitting in the background
+                                    // LRU list as a hidden process (with activities),
+                                    // we don't want the service it is connected to
+                                    // to go into the empty LRU and quickly get killed,
+                                    // because I'll we'll do is just end up restarting
+                                    // the service.
+                                    app.hasClientActivities |= client.hasActivities;
+                                }
+                            }
+                            if (adj > clientAdj) {
+                                // If this process has recently shown UI, and
+                                // the process that is binding to it is less
+                                // important than being visible, then we don't
+                                // care about the binding as much as we care
+                                // about letting this process get into the LRU
+                                // list to be killed and restarted if needed for
+                                // memory.
+                                if (app.hasShownUi && app != mHomeProcess
+                                        && clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
+                                    adjType = "bound-bg-ui-services";
+                                } else {
+                                    if ((cr.flags&(Context.BIND_ABOVE_CLIENT
+                                            |Context.BIND_IMPORTANT)) != 0) {
+                                        adj = clientAdj;
+                                    } else if ((cr.flags&Context.BIND_NOT_VISIBLE) != 0
+                                            && clientAdj < ProcessList.PERCEPTIBLE_APP_ADJ
+                                            && adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
+                                        adj = ProcessList.PERCEPTIBLE_APP_ADJ;
+                                    } else if (clientAdj > ProcessList.VISIBLE_APP_ADJ) {
+                                        adj = clientAdj;
+                                    } else {
+                                        app.pendingUiClean = true;
+                                        if (adj > ProcessList.VISIBLE_APP_ADJ) {
+                                            adj = ProcessList.VISIBLE_APP_ADJ;
+                                        }
+                                    }
+                                    if (!client.hidden) {
+                                        app.hidden = false;
+                                    }
+                                    if (client.keeping) {
+                                        app.keeping = true;
+                                    }
+                                    adjType = "service";
+                                }
+                            }
+                            if (adjType != null) {
+                                app.adjType = adjType;
+                                app.adjTypeCode = ActivityManager.RunningAppProcessInfo
+                                        .REASON_SERVICE_IN_USE;
+                                app.adjSource = cr.binding.client;
+                                app.adjSourceOom = clientAdj;
+                                app.adjTarget = s.name;
+                            }
+                            if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
+                                if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
+                                    schedGroup = Process.THREAD_GROUP_DEFAULT;
+                                }
+                            }
+                        }
+                        final ActivityRecord a = cr.activity;
+                        if ((cr.flags&Context.BIND_ADJUST_WITH_ACTIVITY) != 0) {
+                            if (a != null && adj > ProcessList.FOREGROUND_APP_ADJ &&
+                                    (a.visible || a.state == ActivityState.RESUMED
+                                     || a.state == ActivityState.PAUSING)) {
+                                adj = ProcessList.FOREGROUND_APP_ADJ;
+                                if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
+                                    schedGroup = Process.THREAD_GROUP_DEFAULT;
+                                }
+                                app.hidden = false;
+                                app.adjType = "service";
+                                app.adjTypeCode = ActivityManager.RunningAppProcessInfo
+                                        .REASON_SERVICE_IN_USE;
+                                app.adjSource = a;
+                                app.adjSourceOom = adj;
+                                app.adjTarget = s.name;
                             }
                         }
                     }
@@ -13288,86 +13302,84 @@
             }
         }
 
-        if (app.pubProviders.size() != 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
-                || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
-            Iterator<ContentProviderRecord> jt = app.pubProviders.values().iterator();
-            while (jt.hasNext() && (adj > ProcessList.FOREGROUND_APP_ADJ
-                    || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
-                ContentProviderRecord cpr = jt.next();
-                for (int i = cpr.connections.size()-1;
-                        i >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
-                                || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE);
-                        i--) {
-                    ContentProviderConnection conn = cpr.connections.get(i);
-                    ProcessRecord client = conn.client;
-                    if (client == app) {
-                        // Being our own client is not interesting.
-                        continue;
-                    }
-                    int myHiddenAdj = hiddenAdj;
-                    if (myHiddenAdj > client.hiddenAdj) {
-                        if (client.hiddenAdj > ProcessList.FOREGROUND_APP_ADJ) {
-                            myHiddenAdj = client.hiddenAdj;
-                        } else {
-                            myHiddenAdj = ProcessList.FOREGROUND_APP_ADJ;
-                        }
-                    }
-                    int myClientHiddenAdj = clientHiddenAdj;
-                    if (myClientHiddenAdj > client.clientHiddenAdj) {
-                        if (client.clientHiddenAdj >= ProcessList.FOREGROUND_APP_ADJ) {
-                            myClientHiddenAdj = client.clientHiddenAdj;
-                        } else {
-                            myClientHiddenAdj = ProcessList.FOREGROUND_APP_ADJ;
-                        }
-                    }
-                    int myEmptyAdj = emptyAdj;
-                    if (myEmptyAdj > client.emptyAdj) {
-                        if (client.emptyAdj > ProcessList.FOREGROUND_APP_ADJ) {
-                            myEmptyAdj = client.emptyAdj;
-                        } else {
-                            myEmptyAdj = ProcessList.FOREGROUND_APP_ADJ;
-                        }
-                    }
-                    int clientAdj = computeOomAdjLocked(client, myHiddenAdj,
-                            myClientHiddenAdj, myEmptyAdj, TOP_APP, true, doingAll);
-                    if (adj > clientAdj) {
-                        if (app.hasShownUi && app != mHomeProcess
-                                && clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
-                            app.adjType = "bg-ui-provider";
-                        } else {
-                            adj = clientAdj > ProcessList.FOREGROUND_APP_ADJ
-                                    ? clientAdj : ProcessList.FOREGROUND_APP_ADJ;
-                            app.adjType = "provider";
-                        }
-                        if (!client.hidden) {
-                            app.hidden = false;
-                        }
-                        if (client.keeping) {
-                            app.keeping = true;
-                        }
-                        app.adjTypeCode = ActivityManager.RunningAppProcessInfo
-                                .REASON_PROVIDER_IN_USE;
-                        app.adjSource = client;
-                        app.adjSourceOom = clientAdj;
-                        app.adjTarget = cpr.name;
-                    }
-                    if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
-                        schedGroup = Process.THREAD_GROUP_DEFAULT;
+        for (int provi = app.pubProviders.size()-1;
+                provi >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
+                        || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE);
+                provi--) {
+            ContentProviderRecord cpr = app.pubProviders.valueAt(provi);
+            for (int i = cpr.connections.size()-1;
+                    i >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
+                            || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE);
+                    i--) {
+                ContentProviderConnection conn = cpr.connections.get(i);
+                ProcessRecord client = conn.client;
+                if (client == app) {
+                    // Being our own client is not interesting.
+                    continue;
+                }
+                int myHiddenAdj = hiddenAdj;
+                if (myHiddenAdj > client.hiddenAdj) {
+                    if (client.hiddenAdj > ProcessList.FOREGROUND_APP_ADJ) {
+                        myHiddenAdj = client.hiddenAdj;
+                    } else {
+                        myHiddenAdj = ProcessList.FOREGROUND_APP_ADJ;
                     }
                 }
-                // If the provider has external (non-framework) process
-                // dependencies, ensure that its adjustment is at least
-                // FOREGROUND_APP_ADJ.
-                if (cpr.hasExternalProcessHandles()) {
-                    if (adj > ProcessList.FOREGROUND_APP_ADJ) {
-                        adj = ProcessList.FOREGROUND_APP_ADJ;
-                        schedGroup = Process.THREAD_GROUP_DEFAULT;
-                        app.hidden = false;
-                        app.keeping = true;
-                        app.adjType = "provider";
-                        app.adjTarget = cpr.name;
+                int myClientHiddenAdj = clientHiddenAdj;
+                if (myClientHiddenAdj > client.clientHiddenAdj) {
+                    if (client.clientHiddenAdj >= ProcessList.FOREGROUND_APP_ADJ) {
+                        myClientHiddenAdj = client.clientHiddenAdj;
+                    } else {
+                        myClientHiddenAdj = ProcessList.FOREGROUND_APP_ADJ;
                     }
                 }
+                int myEmptyAdj = emptyAdj;
+                if (myEmptyAdj > client.emptyAdj) {
+                    if (client.emptyAdj > ProcessList.FOREGROUND_APP_ADJ) {
+                        myEmptyAdj = client.emptyAdj;
+                    } else {
+                        myEmptyAdj = ProcessList.FOREGROUND_APP_ADJ;
+                    }
+                }
+                int clientAdj = computeOomAdjLocked(client, myHiddenAdj,
+                        myClientHiddenAdj, myEmptyAdj, TOP_APP, true, doingAll);
+                if (adj > clientAdj) {
+                    if (app.hasShownUi && app != mHomeProcess
+                            && clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
+                        app.adjType = "bg-ui-provider";
+                    } else {
+                        adj = clientAdj > ProcessList.FOREGROUND_APP_ADJ
+                                ? clientAdj : ProcessList.FOREGROUND_APP_ADJ;
+                        app.adjType = "provider";
+                    }
+                    if (!client.hidden) {
+                        app.hidden = false;
+                    }
+                    if (client.keeping) {
+                        app.keeping = true;
+                    }
+                    app.adjTypeCode = ActivityManager.RunningAppProcessInfo
+                            .REASON_PROVIDER_IN_USE;
+                    app.adjSource = client;
+                    app.adjSourceOom = clientAdj;
+                    app.adjTarget = cpr.name;
+                }
+                if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
+                    schedGroup = Process.THREAD_GROUP_DEFAULT;
+                }
+            }
+            // If the provider has external (non-framework) process
+            // dependencies, ensure that its adjustment is at least
+            // FOREGROUND_APP_ADJ.
+            if (cpr.hasExternalProcessHandles()) {
+                if (adj > ProcessList.FOREGROUND_APP_ADJ) {
+                    adj = ProcessList.FOREGROUND_APP_ADJ;
+                    schedGroup = Process.THREAD_GROUP_DEFAULT;
+                    app.hidden = false;
+                    app.keeping = true;
+                    app.adjType = "provider";
+                    app.adjTarget = cpr.name;
+                }
             }
         }
 
diff --git a/services/java/com/android/server/am/ActivityRecord.java b/services/java/com/android/server/am/ActivityRecord.java
index a40b13c..561dd0f 100644
--- a/services/java/com/android/server/am/ActivityRecord.java
+++ b/services/java/com/android/server/am/ActivityRecord.java
@@ -86,6 +86,7 @@
     CharSequence nonLocalizedLabel;  // the label information from the package mgr.
     int labelRes;           // the label information from the package mgr.
     int icon;               // resource identifier of activity's icon.
+    int logo;               // resource identifier of activity's logo.
     int theme;              // resource identifier of activity's theme.
     int realTheme;          // actual theme resource we will use, never 0.
     int windowFlags;        // custom window flags for preview window.
@@ -399,6 +400,7 @@
                 labelRes = app.labelRes;
             }
             icon = aInfo.getIconResource();
+            logo = aInfo.getLogoResource();
             theme = aInfo.getThemeResource();
             realTheme = theme;
             if (realTheme == 0) {
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index d6a6eb8..5e88d3b 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -1465,8 +1465,8 @@
                     mWindowManager.setAppStartingWindow(
                             next.appToken, next.packageName, next.theme,
                             mService.compatibilityInfoForPackageLocked(next.info.applicationInfo),
-                            next.nonLocalizedLabel, next.labelRes, next.icon, next.windowFlags,
-                            null, true);
+                            next.nonLocalizedLabel, next.labelRes, next.icon, next.logo,
+                            next.windowFlags, null, true);
                 }
                 mStackSupervisor.startSpecificActivityLocked(next, true, false);
                 if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
@@ -1500,7 +1500,7 @@
                             mService.compatibilityInfoForPackageLocked(
                                     next.info.applicationInfo),
                             next.nonLocalizedLabel,
-                            next.labelRes, next.icon, next.windowFlags,
+                            next.labelRes, next.icon, next.logo, next.windowFlags,
                             null, true);
                 }
                 if (DEBUG_SWITCH) Slog.v(TAG, "Restarting: " + next);
@@ -1639,7 +1639,7 @@
                         r.appToken, r.packageName, r.theme,
                         mService.compatibilityInfoForPackageLocked(
                                 r.info.applicationInfo), r.nonLocalizedLabel,
-                        r.labelRes, r.icon, r.windowFlags,
+                        r.labelRes, r.icon, r.logo, r.windowFlags,
                         prev != null ? prev.appToken : null, showStartingIcon);
             }
         } else {
@@ -3333,14 +3333,16 @@
         }
     }
 
-    void dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll,
-            boolean dumpClient, String dumpPackage) {
+    boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll,
+            boolean dumpClient, String dumpPackage, boolean needSep) {
+        boolean printed = false;
         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
             final TaskRecord task = mTaskHistory.get(taskNdx);
-            pw.print("  Task "); pw.print(taskNdx); pw.print(": id #"); pw.println(task.taskId);
-            ActivityStackSupervisor.dumpHistoryList(fd, pw, mTaskHistory.get(taskNdx).mActivities,
-                "    ", "Hist", true, !dumpAll, dumpClient, dumpPackage);
+            printed |= ActivityStackSupervisor.dumpHistoryList(fd, pw,
+                    mTaskHistory.get(taskNdx).mActivities, "    ", "Hist", true, !dumpAll,
+                    dumpClient, dumpPackage, needSep, "    Task " + taskNdx + ": id #" + task.taskId);
         }
+        return printed;
     }
 
     ArrayList<ActivityRecord> getDumpActivitiesLocked(String name) {
diff --git a/services/java/com/android/server/am/ActivityStackSupervisor.java b/services/java/com/android/server/am/ActivityStackSupervisor.java
index bddca2b..a638981 100644
--- a/services/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/java/com/android/server/am/ActivityStackSupervisor.java
@@ -2215,82 +2215,95 @@
         return getFocusedStack().getDumpActivitiesLocked(name);
     }
 
+    static boolean printThisActivity(PrintWriter pw, ActivityRecord activity, String dumpPackage,
+            boolean needSep, String prefix) {
+        if (activity != null) {
+            if (dumpPackage == null || dumpPackage.equals(activity.packageName)) {
+                if (needSep) {
+                    pw.println();
+                    needSep = false;
+                }
+                pw.print(prefix);
+                pw.println(activity);
+            }
+        }
+        return needSep;
+    }
+
     boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll,
             boolean dumpClient, String dumpPackage) {
-        pw.print("  mStackState="); pw.println(stackStateToString(mStackState));
-        if (mGoingToSleepActivities.size() > 0) {
-            pw.println("  Activities waiting to sleep:");
-            dumpHistoryList(fd, pw, mGoingToSleepActivities, "  ", "Sleep", false, !dumpAll, false,
-                    dumpPackage);
-        }
-        if (dumpAll) {
-            pw.println("  mSleepTimeout: " + mSleepTimeout);
-        }
         final int numStacks = mStacks.size();
         for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
             final ActivityStack stack = mStacks.get(stackNdx);
+            if (stackNdx != 0) {
+                pw.println();
+            }
             pw.print("  Stack #"); pw.print(mStacks.indexOf(stack)); pw.println(":");
-            stack.dumpActivitiesLocked(fd, pw, dumpAll, dumpClient, dumpPackage);
-            pw.println(" ");
-            pw.println("  Running activities (most recent first):");
-            dumpHistoryList(fd, pw, stack.mLRUActivities, "  ", "Run", false, !dumpAll, false,
-                    dumpPackage);
+            stack.dumpActivitiesLocked(fd, pw, dumpAll, dumpClient, dumpPackage, false);
+            dumpHistoryList(fd, pw, stack.mLRUActivities, "    ", "Run", false, !dumpAll, false,
+                    dumpPackage, true, "    Running activities (most recent first):");
 
-            pw.print("  Stack #"); pw.println(mStacks.indexOf(stack));
-            if (stack.mPausingActivity != null) {
-                pw.println("  mPausingActivity: " + stack.mPausingActivity);
-            }
-            pw.println("  mResumedActivity: " + stack.mResumedActivity);
+            boolean needSep = true;
+            needSep = printThisActivity(pw, stack.mPausingActivity, dumpPackage, needSep,
+                    "    mPausingActivity: ");
+            needSep = printThisActivity(pw, stack.mResumedActivity, dumpPackage, needSep,
+                    "    mResumedActivity: ");
             if (dumpAll) {
-                pw.println("  mLastPausedActivity: " + stack.mLastPausedActivity);
+                printThisActivity(pw, stack.mLastPausedActivity, dumpPackage, needSep,
+                        "    mLastPausedActivity: ");
             }
         }
 
-        if (mFinishingActivities.size() > 0) {
-            pw.println(" ");
-            pw.println("  Activities waiting to finish:");
-            dumpHistoryList(fd, pw, mFinishingActivities, "  ", "Fin", false, !dumpAll, false,
-                    dumpPackage);
-        }
+        dumpHistoryList(fd, pw, mFinishingActivities, "  ", "Fin", false, !dumpAll, false,
+                dumpPackage, true, "  Activities waiting to finish:");
+        dumpHistoryList(fd, pw, mStoppingActivities, "  ", "Stop", false, !dumpAll, false,
+                dumpPackage, true, "  Activities waiting to stop:");
+        dumpHistoryList(fd, pw, mWaitingVisibleActivities, "  ", "Wait", false, !dumpAll,
+                false, dumpPackage, true, "  Activities waiting for another to become visible:");
+        dumpHistoryList(fd, pw, mGoingToSleepActivities, "  ", "Sleep", false, !dumpAll, false,
+                dumpPackage, true, "  Activities waiting to sleep:");
+        dumpHistoryList(fd, pw, mGoingToSleepActivities, "  ", "Sleep", false, !dumpAll, false,
+                dumpPackage, true, "  Activities waiting to sleep:");
 
-        if (mStoppingActivities.size() > 0) {
-            pw.println(" ");
-            pw.println("  Activities waiting to stop:");
-            dumpHistoryList(fd, pw, mStoppingActivities, "  ", "Stop", false, !dumpAll, false,
-                    dumpPackage);
-        }
-
-        if (mWaitingVisibleActivities.size() > 0) {
-            pw.println(" ");
-            pw.println("  Activities waiting for another to become visible:");
-            dumpHistoryList(fd, pw, mWaitingVisibleActivities, "  ", "Wait", false, !dumpAll,
-                    false, dumpPackage);
-        }
-
-        if (dumpAll) {
-            pw.println(" ");
-            pw.println("  mCurTaskId: " + mCurTaskId);
+        if (dumpPackage == null) {
+            pw.println();
+            pw.print("  mStackState="); pw.println(stackStateToString(mStackState));
+            if (dumpAll) {
+                pw.println("  mSleepTimeout: " + mSleepTimeout);
+            }
+            if (dumpAll) {
+                pw.println("  mCurTaskId: " + mCurTaskId);
+            }
         }
         return true;
     }
 
-    static void dumpHistoryList(FileDescriptor fd, PrintWriter pw, List<ActivityRecord> list,
+    static boolean dumpHistoryList(FileDescriptor fd, PrintWriter pw, List<ActivityRecord> list,
             String prefix, String label, boolean complete, boolean brief, boolean client,
-            String dumpPackage) {
+            String dumpPackage, boolean needNL, String header) {
         TaskRecord lastTask = null;
-        boolean needNL = false;
-        final String innerPrefix = prefix + "      ";
-        final String[] args = new String[0];
+        String innerPrefix = null;
+        String[] args = null;
+        boolean printed = false;
         for (int i=list.size()-1; i>=0; i--) {
             final ActivityRecord r = list.get(i);
             if (dumpPackage != null && !dumpPackage.equals(r.packageName)) {
                 continue;
             }
+            if (innerPrefix == null) {
+                innerPrefix = prefix + "      ";
+                args = new String[0];
+            }
+            printed = true;
             final boolean full = !brief && (complete || !r.isInHistory());
             if (needNL) {
-                pw.println(" ");
+                pw.println("");
                 needNL = false;
             }
+            if (header != null) {
+                pw.println(header);
+                header = null;
+            }
             if (lastTask != r.task) {
                 lastTask = r.task;
                 pw.print(prefix);
@@ -2341,6 +2354,7 @@
                 needNL = true;
             }
         }
+        return printed;
     }
 
     void scheduleIdleTimeoutLocked(ActivityRecord next) {
diff --git a/services/java/com/android/server/am/ProcessRecord.java b/services/java/com/android/server/am/ProcessRecord.java
index 7929f96..3a4a34c 100644
--- a/services/java/com/android/server/am/ProcessRecord.java
+++ b/services/java/com/android/server/am/ProcessRecord.java
@@ -32,12 +32,12 @@
 import android.os.Process;
 import android.os.SystemClock;
 import android.os.UserHandle;
+import android.util.ArrayMap;
 import android.util.PrintWriterPrinter;
 import android.util.TimeUtils;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.HashSet;
 
 /**
@@ -129,8 +129,8 @@
     // all IIntentReceivers that are registered from this process.
     final HashSet<ReceiverList> receivers = new HashSet<ReceiverList>();
     // class (String) -> ContentProviderRecord
-    final HashMap<String, ContentProviderRecord> pubProviders
-            = new HashMap<String, ContentProviderRecord>(); 
+    final ArrayMap<String, ContentProviderRecord> pubProviders
+            = new ArrayMap<String, ContentProviderRecord>();
     // All ContentProviderRecord process is using
     final ArrayList<ContentProviderConnection> conProviders
             = new ArrayList<ContentProviderConnection>();
@@ -302,9 +302,9 @@
         }
         if (pubProviders.size() > 0) {
             pw.print(prefix); pw.println("Published Providers:");
-            for (HashMap.Entry<String, ContentProviderRecord> ent : pubProviders.entrySet()) {
-                pw.print(prefix); pw.print("  - "); pw.println(ent.getKey());
-                pw.print(prefix); pw.print("    -> "); pw.println(ent.getValue());
+            for (int i=0; i<pubProviders.size(); i++) {
+                pw.print(prefix); pw.print("  - "); pw.println(pubProviders.keyAt(i));
+                pw.print(prefix); pw.print("    -> "); pw.println(pubProviders.valueAt(i));
             }
         }
         if (conProviders.size() > 0) {
diff --git a/services/java/com/android/server/am/ProviderMap.java b/services/java/com/android/server/am/ProviderMap.java
index 9dbf5f5..3249e1e 100644
--- a/services/java/com/android/server/am/ProviderMap.java
+++ b/services/java/com/android/server/am/ProviderMap.java
@@ -230,58 +230,88 @@
         return didSomething;
     }
 
-    private void dumpProvidersByClassLocked(PrintWriter pw, boolean dumpAll,
-            HashMap<ComponentName, ContentProviderRecord> map) {
+    private boolean dumpProvidersByClassLocked(PrintWriter pw, boolean dumpAll, String dumpPackage,
+            String header, boolean needSep, HashMap<ComponentName, ContentProviderRecord> map) {
         Iterator<Map.Entry<ComponentName, ContentProviderRecord>> it = map.entrySet().iterator();
+        boolean written = false;
         while (it.hasNext()) {
             Map.Entry<ComponentName, ContentProviderRecord> e = it.next();
             ContentProviderRecord r = e.getValue();
+            if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
+                continue;
+            }
+            if (needSep) {
+                pw.println("");
+                needSep = false;
+            }
+            if (header != null) {
+                pw.println(header);
+                header = null;
+            }
+            written = true;
             pw.print("  * ");
             pw.println(r);
             r.dump(pw, "    ", dumpAll);
         }
+        return written;
     }
 
-    private void dumpProvidersByNameLocked(PrintWriter pw,
-            HashMap<String, ContentProviderRecord> map) {
+    private boolean dumpProvidersByNameLocked(PrintWriter pw, String dumpPackage,
+            String header, boolean needSep, HashMap<String, ContentProviderRecord> map) {
         Iterator<Map.Entry<String, ContentProviderRecord>> it = map.entrySet().iterator();
+        boolean written = false;
         while (it.hasNext()) {
             Map.Entry<String, ContentProviderRecord> e = it.next();
             ContentProviderRecord r = e.getValue();
+            if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
+                continue;
+            }
+            if (needSep) {
+                pw.println("");
+                needSep = false;
+            }
+            if (header != null) {
+                pw.println(header);
+                header = null;
+            }
+            written = true;
             pw.print("  ");
             pw.print(e.getKey());
             pw.print(": ");
             pw.println(r.toShortString());
         }
+        return written;
     }
 
-    void dumpProvidersLocked(PrintWriter pw, boolean dumpAll) {
+    boolean dumpProvidersLocked(PrintWriter pw, boolean dumpAll, String dumpPackage) {
+        boolean needSep = false;
+
         if (mSingletonByClass.size() > 0) {
             pw.println("  Published single-user content providers (by class):");
-            dumpProvidersByClassLocked(pw, dumpAll, mSingletonByClass);
+            needSep = dumpProvidersByClassLocked(pw, dumpAll, dumpPackage,
+                    "  Published single-user content providers (by class):", needSep,
+                    mSingletonByClass);
         }
 
-        pw.println("");
         for (int i = 0; i < mProvidersByClassPerUser.size(); i++) {
             HashMap<ComponentName, ContentProviderRecord> map = mProvidersByClassPerUser.valueAt(i);
-            pw.println("");
-            pw.println("  Published user " + mProvidersByClassPerUser.keyAt(i)
-                    + " content providers (by class):");
-            dumpProvidersByClassLocked(pw, dumpAll, map);
+            needSep |= dumpProvidersByClassLocked(pw, dumpAll, dumpPackage,
+                    "  Published user " + mProvidersByClassPerUser.keyAt(i)
+                            + " content providers (by class):", needSep, map);
         }
 
         if (dumpAll) {
-            pw.println("");
-            pw.println("  Single-user authority to provider mappings:");
-            dumpProvidersByNameLocked(pw, mSingletonByName);
+            needSep |= dumpProvidersByNameLocked(pw, dumpPackage,
+                    "  Single-user authority to provider mappings:", needSep, mSingletonByName);
 
             for (int i = 0; i < mProvidersByNamePerUser.size(); i++) {
-                pw.println("");
-                pw.println("  User " + mProvidersByNamePerUser.keyAt(i)
-                        + " authority to provider mappings:");
-                dumpProvidersByNameLocked(pw, mProvidersByNamePerUser.valueAt(i));
+                needSep |= dumpProvidersByNameLocked(pw, dumpPackage,
+                        "  User " + mProvidersByNamePerUser.keyAt(i)
+                                + " authority to provider mappings:", needSep,
+                        mProvidersByNamePerUser.valueAt(i));
             }
         }
+        return needSep;
     }
 
     protected boolean dumpProvider(FileDescriptor fd, PrintWriter pw, String name, String[] args,
diff --git a/services/java/com/android/server/am/ServiceRecord.java b/services/java/com/android/server/am/ServiceRecord.java
index 9fdd293..707e8ee 100644
--- a/services/java/com/android/server/am/ServiceRecord.java
+++ b/services/java/com/android/server/am/ServiceRecord.java
@@ -16,34 +16,32 @@
 
 package com.android.server.am;
 
-import android.app.PendingIntent;
-import android.net.Uri;
-import android.provider.Settings;
 import com.android.internal.os.BatteryStatsImpl;
 import com.android.server.NotificationManagerService;
 
 import android.app.INotificationManager;
 import android.app.Notification;
 import android.app.NotificationManager;
+import android.app.PendingIntent;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ServiceInfo;
+import android.net.Uri;
 import android.os.Binder;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.os.UserHandle;
+import android.provider.Settings;
+import android.util.ArrayMap;
 import android.util.Slog;
 import android.util.TimeUtils;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
 import java.util.List;
 
 /**
@@ -76,11 +74,11 @@
     final boolean exported; // from ServiceInfo.exported
     final Runnable restarter; // used to schedule retries of starting the service
     final long createTime;  // when this service was created
-    final HashMap<Intent.FilterComparison, IntentBindRecord> bindings
-            = new HashMap<Intent.FilterComparison, IntentBindRecord>();
+    final ArrayMap<Intent.FilterComparison, IntentBindRecord> bindings
+            = new ArrayMap<Intent.FilterComparison, IntentBindRecord>();
                             // All active bindings to the service.
-    final HashMap<IBinder, ArrayList<ConnectionRecord>> connections
-            = new HashMap<IBinder, ArrayList<ConnectionRecord>>();
+    final ArrayMap<IBinder, ArrayList<ConnectionRecord>> connections
+            = new ArrayMap<IBinder, ArrayList<ConnectionRecord>>();
                             // IBinder -> ConnectionRecord of all bound clients
 
     ProcessRecord app;      // where this service is running or null.
@@ -258,10 +256,9 @@
             dumpStartList(pw, prefix, pendingStarts, 0);
         }
         if (bindings.size() > 0) {
-            Iterator<IntentBindRecord> it = bindings.values().iterator();
             pw.print(prefix); pw.println("Bindings:");
-            while (it.hasNext()) {
-                IntentBindRecord b = it.next();
+            for (int i=0; i<bindings.size(); i++) {
+                IntentBindRecord b = bindings.valueAt(i);
                 pw.print(prefix); pw.print("* IntentBindRecord{");
                         pw.print(Integer.toHexString(System.identityHashCode(b)));
                         if ((b.collectFlags()&Context.BIND_AUTO_CREATE) != 0) {
@@ -273,9 +270,8 @@
         }
         if (connections.size() > 0) {
             pw.print(prefix); pw.println("All Connections:");
-            Iterator<ArrayList<ConnectionRecord>> it = connections.values().iterator();
-            while (it.hasNext()) {
-                ArrayList<ConnectionRecord> c = it.next();
+            for (int conni=0; conni<connections.size(); conni++) {
+                ArrayList<ConnectionRecord> c = connections.valueAt(conni);
                 for (int i=0; i<c.size(); i++) {
                     pw.print(prefix); pw.print("  "); pw.println(c.get(i));
                 }
diff --git a/services/java/com/android/server/wifi/WifiController.java b/services/java/com/android/server/wifi/WifiController.java
index 228fabf..87b4394 100644
--- a/services/java/com/android/server/wifi/WifiController.java
+++ b/services/java/com/android/server/wifi/WifiController.java
@@ -150,7 +150,11 @@
             addState(mStaDisabledWithScanState, mDefaultState);
             addState(mApEnabledState, mDefaultState);
             addState(mEcmState, mDefaultState);
-        setInitialState(mApStaDisabledState);
+        if (mSettingsStore.isScanAlwaysAvailable()) {
+            setInitialState(mStaDisabledWithScanState);
+        } else {
+            setInitialState(mApStaDisabledState);
+        }
         setLogRecSize(100);
         setLogOnlyTransitions(false);
 
diff --git a/services/java/com/android/server/wifi/WifiService.java b/services/java/com/android/server/wifi/WifiService.java
index 8ddc776..66ef978 100644
--- a/services/java/com/android/server/wifi/WifiService.java
+++ b/services/java/com/android/server/wifi/WifiService.java
@@ -651,7 +651,12 @@
         Slog.i(TAG, "WifiService trying to set country code to " + countryCode +
                 " with persist set to " + persist);
         enforceChangePermission();
-        mWifiStateMachine.setCountryCode(countryCode, persist);
+        final long token = Binder.clearCallingIdentity();
+        try {
+            mWifiStateMachine.setCountryCode(countryCode, persist);
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
     }
 
     /**
@@ -668,7 +673,12 @@
         if (!isDualBandSupported()) return;
         Slog.i(TAG, "WifiService trying to set frequency band to " + band +
                 " with persist set to " + persist);
-        mWifiStateMachine.setFrequencyBand(band, persist);
+        final long token = Binder.clearCallingIdentity();
+        try {
+            mWifiStateMachine.setFrequencyBand(band, persist);
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
     }
 
 
diff --git a/services/java/com/android/server/wm/StartingData.java b/services/java/com/android/server/wm/StartingData.java
index 46bb480..7115b0f 100644
--- a/services/java/com/android/server/wm/StartingData.java
+++ b/services/java/com/android/server/wm/StartingData.java
@@ -25,17 +25,19 @@
     final CharSequence nonLocalizedLabel;
     final int labelRes;
     final int icon;
+    final int logo;
     final int windowFlags;
 
     StartingData(String _pkg, int _theme, CompatibilityInfo _compatInfo,
             CharSequence _nonLocalizedLabel,
-            int _labelRes, int _icon, int _windowFlags) {
+            int _labelRes, int _icon, int _logo, int _windowFlags) {
         pkg = _pkg;
         theme = _theme;
         compatInfo = _compatInfo;
         nonLocalizedLabel = _nonLocalizedLabel;
         labelRes = _labelRes;
         icon = _icon;
+        logo = _logo;
         windowFlags = _windowFlags;
     }
 }
\ No newline at end of file
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index a1e07dc..b4dcdec 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -3878,7 +3878,7 @@
     @Override
     public void setAppStartingWindow(IBinder token, String pkg,
             int theme, CompatibilityInfo compatInfo,
-            CharSequence nonLocalizedLabel, int labelRes, int icon,
+            CharSequence nonLocalizedLabel, int labelRes, int icon, int logo,
             int windowFlags, IBinder transferFrom, boolean createIfNeeded) {
         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
                 "setAppStartingWindow()")) {
@@ -4079,7 +4079,7 @@
             if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Creating StartingData");
             mStartingIconInTransition = true;
             wtoken.startingData = new StartingData(pkg, theme, compatInfo, nonLocalizedLabel,
-                    labelRes, icon, windowFlags);
+                    labelRes, icon, logo, windowFlags);
             Message m = mH.obtainMessage(H.ADD_STARTING, wtoken);
             // Note: we really want to do sendMessageAtFrontOfQueue() because we
             // want to process the message ASAP, before any other queued
@@ -7083,7 +7083,7 @@
                     try {
                         view = mPolicy.addStartingWindow(
                             wtoken.token, sd.pkg, sd.theme, sd.compatInfo,
-                            sd.nonLocalizedLabel, sd.labelRes, sd.icon, sd.windowFlags);
+                            sd.nonLocalizedLabel, sd.labelRes, sd.icon, sd.logo, sd.windowFlags);
                     } catch (Exception e) {
                         Slog.w(TAG, "Exception when adding starting window", e);
                     }
diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java
index 8b85d8c..3ae2106 100644
--- a/telephony/java/android/telephony/PhoneNumberUtils.java
+++ b/telephony/java/android/telephony/PhoneNumberUtils.java
@@ -152,6 +152,11 @@
         String number = null;
 
         Uri uri = intent.getData();
+
+        if (uri == null) {
+            return null;
+        }
+
         String scheme = uri.getScheme();
 
         if (scheme.equals("tel") || scheme.equals("sip")) {
diff --git a/tests/CanvasCompare/src/com/android/test/hwuicompare/errorCalculator.rs b/tests/CanvasCompare/src/com/android/test/hwuicompare/errorCalculator.rs
index 668f61d..3681784 100644
--- a/tests/CanvasCompare/src/com/android/test/hwuicompare/errorCalculator.rs
+++ b/tests/CanvasCompare/src/com/android/test/hwuicompare/errorCalculator.rs
@@ -49,8 +49,8 @@
     float4 diff = idealPixel - givenPixel;
     float totalDiff = diff.x + diff.y + diff.z + diff.w;
     if (totalDiff < 0) {
-        v_out[0] = rsPackColorTo8888(0, 0, clamp(-totalDiff/2, 0, 1));
+        v_out[0] = rsPackColorTo8888(0, 0, clamp(-totalDiff/2.f, 0.f, 1.f));
     } else {
-        v_out[0] = rsPackColorTo8888(clamp(totalDiff/2, 0, 1), 0, 0);
+        v_out[0] = rsPackColorTo8888(clamp(totalDiff/2.f, 0.f, 1.f), 0, 0);
     }
 }
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 10baac5..53318a4 100644
--- a/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java
+++ b/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java
@@ -164,7 +164,7 @@
         }
         
         try {
-            mWm.setAppStartingWindow(null, "foo", 0, null, null, 0, 0, 0, null, false);
+            mWm.setAppStartingWindow(null, "foo", 0, null, null, 0, 0, 0, 0, null, false);
             fail("IWindowManager.setAppStartingWindow did not throw SecurityException as"
                     + " expected");
         } catch (SecurityException e) {
diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
index 0ca230c..a7b48bb 100644
--- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
+++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
@@ -304,7 +304,7 @@
 
     @Override
     public void setAppStartingWindow(IBinder arg0, String arg1, int arg2, CompatibilityInfo arg3,
-            CharSequence arg4, int arg5, int arg6, int arg7, IBinder arg8, boolean arg9)
+            CharSequence arg4, int arg5, int arg6, int arg7, int arg8, IBinder arg9, boolean arg10)
             throws RemoteException {
         // TODO Auto-generated method stub
     }
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index d53c320..9f3a0d3 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -347,6 +347,8 @@
     public static final int CMD_DISABLE_P2P_REQ           = BASE + 132;
     public static final int CMD_DISABLE_P2P_RSP           = BASE + 133;
 
+    public static final int CMD_BOOT_COMPLETED            = BASE + 134;
+
     public static final int CONNECT_MODE                   = 1;
     public static final int SCAN_ONLY_MODE                 = 2;
     public static final int SCAN_ONLY_WITH_WIFI_OFF_MODE   = 3;
@@ -410,6 +412,10 @@
     private int mDelayedStopCounter;
     private boolean mInDelayedStop = false;
 
+    // sometimes telephony gives us this data before boot is complete and we can't store it
+    // until after, so the write is deferred
+    private volatile String mPersistedCountryCode;
+
     private static final int MIN_RSSI = -200;
     private static final int MAX_RSSI = 256;
 
@@ -637,6 +643,15 @@
                     }
                 });
 
+        mContext.registerReceiver(
+                new BroadcastReceiver() {
+                    @Override
+                    public void onReceive(Context context, Intent intent) {
+                        sendMessage(CMD_BOOT_COMPLETED);
+                    }
+                },
+                new IntentFilter(Intent.ACTION_BOOT_COMPLETED));
+
         mScanResultCache = new LruCache<String, ScanResult>(SCAN_RESULT_CACHE_SIZE);
 
         PowerManager powerManager = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE);
@@ -1004,6 +1019,7 @@
      */
     public void setCountryCode(String countryCode, boolean persist) {
         if (persist) {
+            mPersistedCountryCode = countryCode;
             Settings.Global.putString(mContext.getContentResolver(),
                     Settings.Global.WIFI_COUNTRY_CODE,
                     countryCode);
@@ -1889,6 +1905,19 @@
                         setSuspendOptimizations(SUSPEND_DUE_TO_HIGH_PERF, true);
                     }
                     break;
+                case CMD_BOOT_COMPLETED:
+                    String countryCode = mPersistedCountryCode;
+                    if (TextUtils.isEmpty(countryCode) == false) {
+                        Settings.Global.putString(mContext.getContentResolver(),
+                                Settings.Global.WIFI_COUNTRY_CODE,
+                                countryCode);
+                        // it may be that the state transition that should send this info
+                        // to the driver happened between mPersistedCountryCode getting set
+                        // and now, so simply persisting it here would mean we have sent
+                        // nothing to the driver.  Send the cmd so it might be set now.
+                        sendMessageAtFrontOfQueue(CMD_SET_COUNTRY_CODE, countryCode);
+                    }
+                    break;
                     /* Discard */
                 case CMD_START_SUPPLICANT:
                 case CMD_STOP_SUPPLICANT:
@@ -2359,7 +2388,6 @@
             mInDelayedStop = false;
             mDelayedStopCounter++;
             updateBatteryWorkSource(null);
-
             /**
              * Enable bluetooth coexistence scan mode when bluetooth connection is active.
              * When this mode is on, some of the low-level scan parameters used by the