Merge "Add tests for text layout cache"
diff --git a/api/current.txt b/api/current.txt
index b296672..1eb37b3 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -241,10 +241,10 @@
     field public static final int activatedBackgroundIndicator = 16843517; // 0x10102fd
     field public static final int activityCloseEnterAnimation = 16842938; // 0x10100ba
     field public static final int activityCloseExitAnimation = 16842939; // 0x10100bb
-    field public static final int activityHeight = 16844019; // 0x10104f3
+    field public static final int activityHeight = 16844021; // 0x10104f5
     field public static final int activityOpenEnterAnimation = 16842936; // 0x10100b8
     field public static final int activityOpenExitAnimation = 16842937; // 0x10100b9
-    field public static final int activityWidth = 16844018; // 0x10104f2
+    field public static final int activityWidth = 16844020; // 0x10104f4
     field public static final int addPrintersActivity = 16843750; // 0x10103e6
     field public static final int addStatesFromChildren = 16842992; // 0x10100f0
     field public static final int adjustViewBounds = 16843038; // 0x101011e
@@ -786,6 +786,7 @@
     field public static final int listChoiceIndicatorSingle = 16843289; // 0x1010219
     field public static final int listDivider = 16843284; // 0x1010214
     field public static final int listDividerAlertDialog = 16843525; // 0x1010305
+    field public static final int listMenuViewStyle = 16844018; // 0x10104f2
     field public static final int listPopupWindowStyle = 16843519; // 0x10102ff
     field public static final int listPreferredItemHeight = 16842829; // 0x101004d
     field public static final int listPreferredItemHeightLarge = 16843654; // 0x1010386
@@ -1148,6 +1149,7 @@
     field public static final int strokeLineJoin = 16843788; // 0x101040c
     field public static final int strokeMiterLimit = 16843789; // 0x101040d
     field public static final int strokeWidth = 16843783; // 0x1010407
+    field public static final int subMenuArrow = 16844019; // 0x10104f3
     field public static final int submitBackground = 16843912; // 0x1010488
     field public static final int subtitle = 16843473; // 0x10102d1
     field public static final int subtitleTextAppearance = 16843823; // 0x101042f
@@ -11588,6 +11590,7 @@
     method public void getTextBounds(java.lang.String, int, int, android.graphics.Rect);
     method public void getTextBounds(char[], int, int, android.graphics.Rect);
     method public java.util.Locale getTextLocale();
+    method public android.util.LocaleList getTextLocales();
     method public void getTextPath(char[], int, int, float, float, android.graphics.Path);
     method public void getTextPath(java.lang.String, int, int, float, float, android.graphics.Path);
     method public float getTextScaleX();
@@ -11643,6 +11646,7 @@
     method public void setSubpixelText(boolean);
     method public void setTextAlign(android.graphics.Paint.Align);
     method public void setTextLocale(java.util.Locale);
+    method public void setTextLocales(android.util.LocaleList);
     method public void setTextScaleX(float);
     method public void setTextSize(float);
     method public void setTextSkewX(float);
@@ -34207,6 +34211,7 @@
     ctor public LocaleList(java.util.Locale[]);
     method public static android.util.LocaleList forLanguageTags(java.lang.String);
     method public java.util.Locale get(int);
+    method public static android.util.LocaleList getDefault();
     method public static android.util.LocaleList getEmptyLocaleList();
     method public java.util.Locale getPrimary();
     method public boolean isEmpty();
@@ -41719,6 +41724,7 @@
     method public java.lang.CharSequence getText();
     method public final android.content.res.ColorStateList getTextColors();
     method public java.util.Locale getTextLocale();
+    method public android.util.LocaleList getTextLocales();
     method public float getTextScaleX();
     method public float getTextSize();
     method public int getTotalPaddingBottom();
@@ -41831,6 +41837,7 @@
     method public final void setTextKeepState(java.lang.CharSequence);
     method public final void setTextKeepState(java.lang.CharSequence, android.widget.TextView.BufferType);
     method public void setTextLocale(java.util.Locale);
+    method public void setTextLocales(android.util.LocaleList);
     method public void setTextScaleX(float);
     method public void setTextSize(float);
     method public void setTextSize(int, float);
diff --git a/api/system-current.txt b/api/system-current.txt
index 7cc66cf..f913e6c 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -333,10 +333,10 @@
     field public static final int activatedBackgroundIndicator = 16843517; // 0x10102fd
     field public static final int activityCloseEnterAnimation = 16842938; // 0x10100ba
     field public static final int activityCloseExitAnimation = 16842939; // 0x10100bb
-    field public static final int activityHeight = 16844019; // 0x10104f3
+    field public static final int activityHeight = 16844021; // 0x10104f5
     field public static final int activityOpenEnterAnimation = 16842936; // 0x10100b8
     field public static final int activityOpenExitAnimation = 16842937; // 0x10100b9
-    field public static final int activityWidth = 16844018; // 0x10104f2
+    field public static final int activityWidth = 16844020; // 0x10104f4
     field public static final int addPrintersActivity = 16843750; // 0x10103e6
     field public static final int addStatesFromChildren = 16842992; // 0x10100f0
     field public static final int adjustViewBounds = 16843038; // 0x101011e
@@ -878,6 +878,7 @@
     field public static final int listChoiceIndicatorSingle = 16843289; // 0x1010219
     field public static final int listDivider = 16843284; // 0x1010214
     field public static final int listDividerAlertDialog = 16843525; // 0x1010305
+    field public static final int listMenuViewStyle = 16844018; // 0x10104f2
     field public static final int listPopupWindowStyle = 16843519; // 0x10102ff
     field public static final int listPreferredItemHeight = 16842829; // 0x101004d
     field public static final int listPreferredItemHeightLarge = 16843654; // 0x1010386
@@ -1244,6 +1245,7 @@
     field public static final int strokeLineJoin = 16843788; // 0x101040c
     field public static final int strokeMiterLimit = 16843789; // 0x101040d
     field public static final int strokeWidth = 16843783; // 0x1010407
+    field public static final int subMenuArrow = 16844019; // 0x10104f3
     field public static final int submitBackground = 16843912; // 0x1010488
     field public static final int subtitle = 16843473; // 0x10102d1
     field public static final int subtitleTextAppearance = 16843823; // 0x101042f
@@ -11925,6 +11927,7 @@
     method public void getTextBounds(java.lang.String, int, int, android.graphics.Rect);
     method public void getTextBounds(char[], int, int, android.graphics.Rect);
     method public java.util.Locale getTextLocale();
+    method public android.util.LocaleList getTextLocales();
     method public void getTextPath(char[], int, int, float, float, android.graphics.Path);
     method public void getTextPath(java.lang.String, int, int, float, float, android.graphics.Path);
     method public float getTextScaleX();
@@ -11980,6 +11983,7 @@
     method public void setSubpixelText(boolean);
     method public void setTextAlign(android.graphics.Paint.Align);
     method public void setTextLocale(java.util.Locale);
+    method public void setTextLocales(android.util.LocaleList);
     method public void setTextScaleX(float);
     method public void setTextSize(float);
     method public void setTextSkewX(float);
@@ -36501,6 +36505,7 @@
     ctor public LocaleList(java.util.Locale[]);
     method public static android.util.LocaleList forLanguageTags(java.lang.String);
     method public java.util.Locale get(int);
+    method public static android.util.LocaleList getDefault();
     method public static android.util.LocaleList getEmptyLocaleList();
     method public java.util.Locale getPrimary();
     method public boolean isEmpty();
@@ -44327,6 +44332,7 @@
     method public java.lang.CharSequence getText();
     method public final android.content.res.ColorStateList getTextColors();
     method public java.util.Locale getTextLocale();
+    method public android.util.LocaleList getTextLocales();
     method public float getTextScaleX();
     method public float getTextSize();
     method public int getTotalPaddingBottom();
@@ -44439,6 +44445,7 @@
     method public final void setTextKeepState(java.lang.CharSequence);
     method public final void setTextKeepState(java.lang.CharSequence, android.widget.TextView.BufferType);
     method public void setTextLocale(java.util.Locale);
+    method public void setTextLocales(android.util.LocaleList);
     method public void setTextScaleX(float);
     method public void setTextSize(float);
     method public void setTextSize(int, float);
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 412e3cd..e15ba74 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -4718,7 +4718,13 @@
             mInstrumentedSplitAppDirs = data.info.getSplitAppDirs();
             mInstrumentedLibDir = data.info.getLibDir();
 
-            ApplicationInfo instrApp = new ApplicationInfo();
+            // The app context's info was created against this thread, but
+            // the class loader may have already been loaded and cached with
+            // outdated paths. Clear it so we can load it again using the
+            // instrumentation paths.
+            data.info.clearClassLoader();
+
+            final ApplicationInfo instrApp = new ApplicationInfo();
             instrApp.packageName = ii.packageName;
             instrApp.sourceDir = ii.sourceDir;
             instrApp.publicSourceDir = ii.publicSourceDir;
@@ -4731,6 +4737,7 @@
             ContextImpl instrContext = ContextImpl.createAppContext(this, pi);
 
             try {
+
                 java.lang.ClassLoader cl = instrContext.getClassLoader();
                 mInstrumentation = (Instrumentation)
                     cl.loadClass(data.instrumentationName.getClassName()).newInstance();
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index c2bf28a..3b1c60b 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -255,6 +255,13 @@
         return ai.sharedLibraryFiles;
     }
 
+    /** @hide */
+    public void clearClassLoader() {
+        synchronized (this) {
+            mClassLoader = null;
+        }
+    }
+
     public ClassLoader getClassLoader() {
         synchronized (this) {
             if (mClassLoader != null) {
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index e3414d9..7ffac0a 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -213,7 +213,8 @@
 
      * @see DeviceAdminReceiver
      * @deprecated Use {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME}. This extra is still
-     * supported.
+     * supported, but only if there is only one device admin receiver in the package that requires
+     * the permission {@link android.Manifest.permission#BIND_DEVICE_ADMIN}.
      */
     @Deprecated
     public static final String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME
diff --git a/core/java/android/os/Trace.java b/core/java/android/os/Trace.java
index 4da88ee..7529c52 100644
--- a/core/java/android/os/Trace.java
+++ b/core/java/android/os/Trace.java
@@ -77,6 +77,8 @@
     public static final long TRACE_TAG_POWER = 1L << 17;
     /** @hide */
     public static final long TRACE_TAG_PACKAGE_MANAGER = 1L << 18;
+    /** @hide */
+    public static final long TRACE_TAG_SYSTEM_SERVER = 1L << 19;
 
     private static final long TRACE_TAG_NOT_READY = 1L << 63;
     private static final int MAX_SECTION_NAME_LEN = 127;
diff --git a/core/java/android/util/LocaleList.java b/core/java/android/util/LocaleList.java
index afae9ac..379651e 100644
--- a/core/java/android/util/LocaleList.java
+++ b/core/java/android/util/LocaleList.java
@@ -16,7 +16,11 @@
 
 package android.util;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.Size;
+
+import com.android.internal.annotations.GuardedBy;
 
 import java.util.HashSet;
 import java.util.Locale;
@@ -164,4 +168,22 @@
             return new LocaleList(localeArray);
         }
     }
+
+    private final static Object sLock = new Object();
+
+    @GuardedBy("sLock")
+    private static LocaleList sDefaultLocaleList;
+
+    // TODO: fix this to return the default system locale list once we have that
+    @NonNull @Size(min=1)
+    public static LocaleList getDefault() {
+        Locale defaultLocale = Locale.getDefault();
+        synchronized (sLock) {
+            if (sDefaultLocaleList == null || sDefaultLocaleList.size() != 1
+                    || !defaultLocale.equals(sDefaultLocaleList.getPrimary())) {
+                sDefaultLocaleList = new LocaleList(defaultLocale);
+            }
+        }
+        return sDefaultLocaleList;
+    }
 }
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 665069c..5976f09 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -6687,14 +6687,15 @@
     }
 
     /**
-     * Gets the {@link View} description. It briefly describes the view and is
-     * primarily used for accessibility support. Set this property to enable
-     * better accessibility support for your application. This is especially
-     * true for views that do not have textual representation (For example,
-     * ImageButton).
+     * Returns the {@link View}'s content description.
+     * <p>
+     * <strong>Note:</strong> Do not override this method, as it will have no
+     * effect on the content description presented to accessibility services.
+     * You must call {@link #setContentDescription(CharSequence)} to modify the
+     * content description.
      *
-     * @return The content description.
-     *
+     * @return the content description
+     * @see #setContentDescription(CharSequence)
      * @attr ref android.R.styleable#View_contentDescription
      */
     @ViewDebug.ExportedProperty(category = "accessibility")
@@ -6703,14 +6704,18 @@
     }
 
     /**
-     * Sets the {@link View} description. It briefly describes the view and is
-     * primarily used for accessibility support. Set this property to enable
-     * better accessibility support for your application. This is especially
-     * true for views that do not have textual representation (For example,
-     * ImageButton).
+     * Sets the {@link View}'s content description.
+     * <p>
+     * A content description briefly describes the view and is primarily used
+     * for accessibility support to determine how a view should be presented to
+     * the user. In the case of a view with no textual representation, such as
+     * {@link ImageButton}, a useful content description explains what the view
+     * does. For example, an image button with a phone icon that is used to
+     * place a call may use "Call" as its content description. An image of a
+     * floppy disk that is used to save a file may use "Save".
      *
      * @param contentDescription The content description.
-     *
+     * @see #getContentDescription()
      * @attr ref android.R.styleable#View_contentDescription
      */
     @RemotableViewMethod
diff --git a/core/java/android/widget/ActionMenuPresenter.java b/core/java/android/widget/ActionMenuPresenter.java
index a5696ee..64c4103 100644
--- a/core/java/android/widget/ActionMenuPresenter.java
+++ b/core/java/android/widget/ActionMenuPresenter.java
@@ -37,7 +37,6 @@
 import android.view.ViewGroup;
 import android.view.ViewTreeObserver;
 import android.view.accessibility.AccessibilityNodeInfo;
-import android.widget.ListPopupWindow.ForwardingListener;
 import com.android.internal.view.ActionBarPolicy;
 import com.android.internal.view.menu.ActionMenuItemView;
 import com.android.internal.view.menu.BaseMenuPresenter;
@@ -45,6 +44,7 @@
 import com.android.internal.view.menu.MenuItemImpl;
 import com.android.internal.view.menu.MenuPopupHelper;
 import com.android.internal.view.menu.MenuView;
+import com.android.internal.view.menu.ShowableListMenu;
 import com.android.internal.view.menu.SubMenuBuilder;
 
 import java.util.ArrayList;
@@ -828,7 +828,7 @@
 
             setOnTouchListener(new ForwardingListener(this) {
                 @Override
-                public ListPopupWindow getPopup() {
+                public ShowableListMenu getPopup() {
                     if (mOverflowPopup == null) {
                         return null;
                     }
@@ -1003,7 +1003,7 @@
 
     private class ActionMenuPopupCallback extends ActionMenuItemView.PopupCallback {
         @Override
-        public ListPopupWindow getPopup() {
+        public ShowableListMenu getPopup() {
             return mActionButtonPopup != null ? mActionButtonPopup.getPopup() : null;
         }
     }
diff --git a/core/java/android/widget/ActivityChooserView.java b/core/java/android/widget/ActivityChooserView.java
index f34ad71..f5c46db 100644
--- a/core/java/android/widget/ActivityChooserView.java
+++ b/core/java/android/widget/ActivityChooserView.java
@@ -17,6 +17,7 @@
 package android.widget;
 
 import com.android.internal.R;
+import com.android.internal.view.menu.ShowableListMenu;
 
 import android.annotation.StringRes;
 import android.content.Context;
@@ -37,7 +38,6 @@
 import android.view.ViewTreeObserver.OnGlobalLayoutListener;
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.widget.ActivityChooserModel.ActivityChooserModelClient;
-import android.widget.ListPopupWindow.ForwardingListener;
 
 /**
  * This class is a view for choosing an activity for handling a given {@link Intent}.
@@ -263,7 +263,7 @@
         });
         expandButton.setOnTouchListener(new ForwardingListener(expandButton) {
             @Override
-            public ListPopupWindow getPopup() {
+            public ShowableListMenu getPopup() {
                 return getListPopupWindow();
             }
 
diff --git a/core/java/android/widget/DropDownListView.java b/core/java/android/widget/DropDownListView.java
new file mode 100644
index 0000000..5536513
--- /dev/null
+++ b/core/java/android/widget/DropDownListView.java
@@ -0,0 +1,344 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.widget;
+
+
+import com.android.internal.widget.AutoScrollHelper.AbsListViewAutoScroller;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.util.IntProperty;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.accessibility.AccessibilityManager;
+import android.view.animation.AccelerateDecelerateInterpolator;
+import android.widget.TextView;
+import android.widget.ListView;
+
+
+/**
+ * Wrapper class for a ListView. This wrapper can hijack the focus to
+ * make sure the list uses the appropriate drawables and states when
+ * displayed on screen within a drop down. The focus is never actually
+ * passed to the drop down in this mode; the list only looks focused.
+ *
+ * @hide
+ */
+public class DropDownListView extends ListView {
+    /** Duration in milliseconds of the drag-to-open click animation. */
+    private static final long CLICK_ANIM_DURATION = 150;
+
+    /** Target alpha value for drag-to-open click animation. */
+    private static final int CLICK_ANIM_ALPHA = 0x80;
+
+    /** Wrapper around Drawable's <code>alpha</code> property. */
+    private static final IntProperty<Drawable> DRAWABLE_ALPHA =
+            new IntProperty<Drawable>("alpha") {
+                @Override
+                public void setValue(Drawable object, int value) {
+                    object.setAlpha(value);
+                }
+
+                @Override
+                public Integer get(Drawable object) {
+                    return object.getAlpha();
+                }
+            };
+
+    /*
+     * WARNING: This is a workaround for a touch mode issue.
+     *
+     * Touch mode is propagated lazily to windows. This causes problems in
+     * the following scenario:
+     * - Type something in the AutoCompleteTextView and get some results
+     * - Move down with the d-pad to select an item in the list
+     * - Move up with the d-pad until the selection disappears
+     * - Type more text in the AutoCompleteTextView *using the soft keyboard*
+     *   and get new results; you are now in touch mode
+     * - The selection comes back on the first item in the list, even though
+     *   the list is supposed to be in touch mode
+     *
+     * Using the soft keyboard triggers the touch mode change but that change
+     * is propagated to our window only after the first list layout, therefore
+     * after the list attempts to resurrect the selection.
+     *
+     * The trick to work around this issue is to pretend the list is in touch
+     * mode when we know that the selection should not appear, that is when
+     * we know the user moved the selection away from the list.
+     *
+     * This boolean is set to true whenever we explicitly hide the list's
+     * selection and reset to false whenever we know the user moved the
+     * selection back to the list.
+     *
+     * When this boolean is true, isInTouchMode() returns true, otherwise it
+     * returns super.isInTouchMode().
+     */
+    private boolean mListSelectionHidden;
+
+    /**
+     * True if this wrapper should fake focus.
+     */
+    private boolean mHijackFocus;
+
+    /** Whether to force drawing of the pressed state selector. */
+    private boolean mDrawsInPressedState;
+
+    /** Current drag-to-open click animation, if any. */
+    private Animator mClickAnimation;
+
+    /** Helper for drag-to-open auto scrolling. */
+    private AbsListViewAutoScroller mScrollHelper;
+
+    /**
+     * Creates a new list view wrapper.
+     *
+     * @param context this view's context
+     */
+    public DropDownListView(Context context, boolean hijackFocus) {
+        this(context, hijackFocus, com.android.internal.R.attr.dropDownListViewStyle);
+    }
+
+    /**
+     * Creates a new list view wrapper.
+     *
+     * @param context this view's context
+     */
+    public DropDownListView(Context context, boolean hijackFocus, int defStyleAttr) {
+        super(context, null, defStyleAttr);
+        mHijackFocus = hijackFocus;
+        // TODO: Add an API to control this
+        setCacheColorHint(0); // Transparent, since the background drawable could be anything.
+    }
+
+    /**
+     * Handles forwarded events.
+     *
+     * @param activePointerId id of the pointer that activated forwarding
+     * @return whether the event was handled
+     */
+    public boolean onForwardedEvent(MotionEvent event, int activePointerId) {
+        boolean handledEvent = true;
+        boolean clearPressedItem = false;
+
+        final int actionMasked = event.getActionMasked();
+        switch (actionMasked) {
+            case MotionEvent.ACTION_CANCEL:
+                handledEvent = false;
+                break;
+            case MotionEvent.ACTION_UP:
+                handledEvent = false;
+                // $FALL-THROUGH$
+            case MotionEvent.ACTION_MOVE:
+                final int activeIndex = event.findPointerIndex(activePointerId);
+                if (activeIndex < 0) {
+                    handledEvent = false;
+                    break;
+                }
+
+                final int x = (int) event.getX(activeIndex);
+                final int y = (int) event.getY(activeIndex);
+                final int position = pointToPosition(x, y);
+                if (position == INVALID_POSITION) {
+                    clearPressedItem = true;
+                    break;
+                }
+
+                final View child = getChildAt(position - getFirstVisiblePosition());
+                setPressedItem(child, position, x, y);
+                handledEvent = true;
+
+                if (actionMasked == MotionEvent.ACTION_UP) {
+                    clickPressedItem(child, position);
+                }
+                break;
+        }
+
+        // Failure to handle the event cancels forwarding.
+        if (!handledEvent || clearPressedItem) {
+            clearPressedItem();
+        }
+
+        // Manage automatic scrolling.
+        if (handledEvent) {
+            if (mScrollHelper == null) {
+                mScrollHelper = new AbsListViewAutoScroller(this);
+            }
+            mScrollHelper.setEnabled(true);
+            mScrollHelper.onTouch(this, event);
+        } else if (mScrollHelper != null) {
+            mScrollHelper.setEnabled(false);
+        }
+
+        return handledEvent;
+    }
+
+    /**
+     * Sets whether the list selection is hidden, as part of a workaround for a touch mode issue
+     * (see the declaration for mListSelectionHidden).
+     * @param listSelectionHidden
+     */
+    public void setListSelectionHidden(boolean listSelectionHidden) {
+        this.mListSelectionHidden = listSelectionHidden;
+    }
+
+    /**
+     * Starts an alpha animation on the selector. When the animation ends,
+     * the list performs a click on the item.
+     */
+    private void clickPressedItem(final View child, final int position) {
+        final long id = getItemIdAtPosition(position);
+        final Animator anim = ObjectAnimator.ofInt(
+                mSelector, DRAWABLE_ALPHA, 0xFF, CLICK_ANIM_ALPHA, 0xFF);
+        anim.setDuration(CLICK_ANIM_DURATION);
+        anim.setInterpolator(new AccelerateDecelerateInterpolator());
+        anim.addListener(new AnimatorListenerAdapter() {
+                @Override
+            public void onAnimationEnd(Animator animation) {
+                performItemClick(child, position, id);
+            }
+        });
+        anim.start();
+
+        if (mClickAnimation != null) {
+            mClickAnimation.cancel();
+        }
+        mClickAnimation = anim;
+    }
+
+    private void clearPressedItem() {
+        mDrawsInPressedState = false;
+        setPressed(false);
+        updateSelectorState();
+
+        final View motionView = getChildAt(mMotionPosition - mFirstPosition);
+        if (motionView != null) {
+            motionView.setPressed(false);
+        }
+
+        if (mClickAnimation != null) {
+            mClickAnimation.cancel();
+            mClickAnimation = null;
+        }
+    }
+
+    private void setPressedItem(View child, int position, float x, float y) {
+        mDrawsInPressedState = true;
+
+        // Ordering is essential. First, update the container's pressed state.
+        drawableHotspotChanged(x, y);
+        if (!isPressed()) {
+            setPressed(true);
+        }
+
+        // Next, run layout if we need to stabilize child positions.
+        if (mDataChanged) {
+            layoutChildren();
+        }
+
+        // Manage the pressed view based on motion position. This allows us to
+        // play nicely with actual touch and scroll events.
+        final View motionView = getChildAt(mMotionPosition - mFirstPosition);
+        if (motionView != null && motionView != child && motionView.isPressed()) {
+            motionView.setPressed(false);
+        }
+        mMotionPosition = position;
+
+        // Offset for child coordinates.
+        final float childX = x - child.getLeft();
+        final float childY = y - child.getTop();
+        child.drawableHotspotChanged(childX, childY);
+        if (!child.isPressed()) {
+            child.setPressed(true);
+        }
+
+        // Ensure that keyboard focus starts from the last touched position.
+        setSelectedPositionInt(position);
+        positionSelectorLikeTouch(position, child, x, y);
+
+        // Refresh the drawable state to reflect the new pressed state,
+        // which will also update the selector state.
+        refreshDrawableState();
+
+        if (mClickAnimation != null) {
+            mClickAnimation.cancel();
+            mClickAnimation = null;
+        }
+    }
+
+    @Override
+    boolean touchModeDrawsInPressedState() {
+        return mDrawsInPressedState || super.touchModeDrawsInPressedState();
+    }
+
+    /**
+     * Avoids jarring scrolling effect by ensuring that list elements
+     * made of a text view fit on a single line.
+     *
+     * @param position the item index in the list to get a view for
+     * @return the view for the specified item
+     */
+    @Override
+    View obtainView(int position, boolean[] isScrap) {
+        View view = super.obtainView(position, isScrap);
+
+        if (view instanceof TextView) {
+            ((TextView) view).setHorizontallyScrolling(true);
+        }
+
+        return view;
+    }
+
+    @Override
+    public boolean isInTouchMode() {
+        // WARNING: Please read the comment where mListSelectionHidden is declared
+        return (mHijackFocus && mListSelectionHidden) || super.isInTouchMode();
+    }
+
+    /**
+     * Returns the focus state in the drop down.
+     *
+     * @return true always if hijacking focus
+     */
+    @Override
+    public boolean hasWindowFocus() {
+        return mHijackFocus || super.hasWindowFocus();
+    }
+
+    /**
+     * Returns the focus state in the drop down.
+     *
+     * @return true always if hijacking focus
+     */
+    @Override
+    public boolean isFocused() {
+        return mHijackFocus || super.isFocused();
+    }
+
+    /**
+     * Returns the focus state in the drop down.
+     *
+     * @return true always if hijacking focus
+     */
+    @Override
+    public boolean hasFocus() {
+        return mHijackFocus || super.hasFocus();
+    }
+}
\ No newline at end of file
diff --git a/core/java/android/widget/ForwardingListener.java b/core/java/android/widget/ForwardingListener.java
new file mode 100644
index 0000000..fd7140f
--- /dev/null
+++ b/core/java/android/widget/ForwardingListener.java
@@ -0,0 +1,299 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.widget;
+
+import android.os.SystemClock;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewConfiguration;
+import android.view.ViewParent;
+
+import com.android.internal.view.menu.ShowableListMenu;
+
+/**
+ * Abstract class that forwards touch events to a {@link ListPopupWindow}.
+ *
+ * @hide
+ */
+public abstract class ForwardingListener
+        implements View.OnTouchListener, View.OnAttachStateChangeListener {
+
+    /** Scaled touch slop, used for detecting movement outside bounds. */
+    private final float mScaledTouchSlop;
+
+    /** Timeout before disallowing intercept on the source's parent. */
+    private final int mTapTimeout;
+
+    /** Timeout before accepting a long-press to start forwarding. */
+    private final int mLongPressTimeout;
+
+    /** Source view from which events are forwarded. */
+    private final View mSrc;
+
+    /** Runnable used to prevent conflicts with scrolling parents. */
+    private Runnable mDisallowIntercept;
+
+    /** Runnable used to trigger forwarding on long-press. */
+    private Runnable mTriggerLongPress;
+
+    /** Whether this listener is currently forwarding touch events. */
+    private boolean mForwarding;
+
+    /**
+     * Whether forwarding was initiated by a long-press. If so, we won't
+     * force the window to dismiss when the touch stream ends.
+     */
+    private boolean mWasLongPress;
+
+    /** The id of the first pointer down in the current event stream. */
+    private int mActivePointerId;
+
+    public ForwardingListener(View src) {
+        mSrc = src;
+        mScaledTouchSlop = ViewConfiguration.get(src.getContext()).getScaledTouchSlop();
+        mTapTimeout = ViewConfiguration.getTapTimeout();
+
+        // Use a medium-press timeout. Halfway between tap and long-press.
+        mLongPressTimeout = (mTapTimeout + ViewConfiguration.getLongPressTimeout()) / 2;
+
+        src.addOnAttachStateChangeListener(this);
+    }
+
+    /**
+     * Returns the popup to which this listener is forwarding events.
+     * <p>
+     * Override this to return the correct popup. If the popup is displayed
+     * asynchronously, you may also need to override
+     * {@link #onForwardingStopped} to prevent premature cancellation of
+     * forwarding.
+     *
+     * @return the popup to which this listener is forwarding events
+     */
+    public abstract ShowableListMenu getPopup();
+
+    @Override
+    public boolean onTouch(View v, MotionEvent event) {
+        final boolean wasForwarding = mForwarding;
+        final boolean forwarding;
+        if (wasForwarding) {
+            forwarding = onTouchForwarded(event) || !onForwardingStopped();
+        } else {
+            forwarding = onTouchObserved(event) && onForwardingStarted();
+
+            if (forwarding) {
+                // Make sure we cancel any ongoing source event stream.
+                final long now = SystemClock.uptimeMillis();
+                final MotionEvent e = MotionEvent.obtain(now, now, MotionEvent.ACTION_CANCEL,
+                        0.0f, 0.0f, 0);
+                mSrc.onTouchEvent(e);
+                e.recycle();
+            }
+        }
+
+        mForwarding = forwarding;
+        return forwarding || wasForwarding;
+    }
+
+    @Override
+    public void onViewAttachedToWindow(View v) {
+    }
+
+    @Override
+    public void onViewDetachedFromWindow(View v) {
+        mForwarding = false;
+        mActivePointerId = MotionEvent.INVALID_POINTER_ID;
+
+        if (mDisallowIntercept != null) {
+            mSrc.removeCallbacks(mDisallowIntercept);
+        }
+    }
+
+    /**
+     * Called when forwarding would like to start.
+     * <p>
+     * By default, this will show the popup returned by {@link #getPopup()}.
+     * It may be overridden to perform another action, like clicking the
+     * source view or preparing the popup before showing it.
+     *
+     * @return true to start forwarding, false otherwise
+     */
+    protected boolean onForwardingStarted() {
+        final ShowableListMenu popup = getPopup();
+        if (popup != null && !popup.isShowing()) {
+            popup.show();
+        }
+        return true;
+    }
+
+    /**
+     * Called when forwarding would like to stop.
+     * <p>
+     * By default, this will dismiss the popup returned by
+     * {@link #getPopup()}. It may be overridden to perform some other
+     * action.
+     *
+     * @return true to stop forwarding, false otherwise
+     */
+    protected boolean onForwardingStopped() {
+        final ShowableListMenu popup = getPopup();
+        if (popup != null && popup.isShowing()) {
+            popup.dismiss();
+        }
+        return true;
+    }
+
+    /**
+     * Observes motion events and determines when to start forwarding.
+     *
+     * @param srcEvent motion event in source view coordinates
+     * @return true to start forwarding motion events, false otherwise
+     */
+    private boolean onTouchObserved(MotionEvent srcEvent) {
+        final View src = mSrc;
+        if (!src.isEnabled()) {
+            return false;
+        }
+
+        final int actionMasked = srcEvent.getActionMasked();
+        switch (actionMasked) {
+            case MotionEvent.ACTION_DOWN:
+                mActivePointerId = srcEvent.getPointerId(0);
+                mWasLongPress = false;
+
+                if (mDisallowIntercept == null) {
+                    mDisallowIntercept = new DisallowIntercept();
+                }
+                src.postDelayed(mDisallowIntercept, mTapTimeout);
+
+                if (mTriggerLongPress == null) {
+                    mTriggerLongPress = new TriggerLongPress();
+                }
+                src.postDelayed(mTriggerLongPress, mLongPressTimeout);
+                break;
+            case MotionEvent.ACTION_MOVE:
+                final int activePointerIndex = srcEvent.findPointerIndex(mActivePointerId);
+                if (activePointerIndex >= 0) {
+                    final float x = srcEvent.getX(activePointerIndex);
+                    final float y = srcEvent.getY(activePointerIndex);
+
+                    // Has the pointer moved outside of the view?
+                    if (!src.pointInView(x, y, mScaledTouchSlop)) {
+                        clearCallbacks();
+
+                        // Don't let the parent intercept our events.
+                        src.getParent().requestDisallowInterceptTouchEvent(true);
+                        return true;
+                    }
+                }
+                break;
+            case MotionEvent.ACTION_CANCEL:
+            case MotionEvent.ACTION_UP:
+                clearCallbacks();
+                break;
+        }
+
+        return false;
+    }
+
+    private void clearCallbacks() {
+        if (mTriggerLongPress != null) {
+            mSrc.removeCallbacks(mTriggerLongPress);
+        }
+
+        if (mDisallowIntercept != null) {
+            mSrc.removeCallbacks(mDisallowIntercept);
+        }
+    }
+
+    private void onLongPress() {
+        clearCallbacks();
+
+        final View src = mSrc;
+        if (!src.isEnabled() || src.isLongClickable()) {
+            // Ignore long-press if the view is disabled or has its own
+            // handler.
+            return;
+        }
+
+        if (!onForwardingStarted()) {
+            return;
+        }
+
+        // Don't let the parent intercept our events.
+        src.getParent().requestDisallowInterceptTouchEvent(true);
+
+        // Make sure we cancel any ongoing source event stream.
+        final long now = SystemClock.uptimeMillis();
+        final MotionEvent e = MotionEvent.obtain(now, now, MotionEvent.ACTION_CANCEL, 0, 0, 0);
+        src.onTouchEvent(e);
+        e.recycle();
+
+        mForwarding = true;
+        mWasLongPress = true;
+    }
+
+    /**
+     * Handles forwarded motion events and determines when to stop
+     * forwarding.
+     *
+     * @param srcEvent motion event in source view coordinates
+     * @return true to continue forwarding motion events, false to cancel
+     */
+    private boolean onTouchForwarded(MotionEvent srcEvent) {
+        final View src = mSrc;
+        final ShowableListMenu popup = getPopup();
+        if (popup == null || !popup.isShowing()) {
+            return false;
+        }
+
+        final DropDownListView dst = (DropDownListView) popup.getListView();
+        if (dst == null || !dst.isShown()) {
+            return false;
+        }
+
+        // Convert event to destination-local coordinates.
+        final MotionEvent dstEvent = MotionEvent.obtainNoHistory(srcEvent);
+        src.toGlobalMotionEvent(dstEvent);
+        dst.toLocalMotionEvent(dstEvent);
+
+        // Forward converted event to destination view, then recycle it.
+        final boolean handled = dst.onForwardedEvent(dstEvent, mActivePointerId);
+        dstEvent.recycle();
+
+        // Always cancel forwarding when the touch stream ends.
+        final int action = srcEvent.getActionMasked();
+        final boolean keepForwarding = action != MotionEvent.ACTION_UP
+                && action != MotionEvent.ACTION_CANCEL;
+
+        return handled && keepForwarding;
+    }
+
+    private class DisallowIntercept implements Runnable {
+        @Override
+        public void run() {
+            final ViewParent parent = mSrc.getParent();
+            parent.requestDisallowInterceptTouchEvent(true);
+        }
+    }
+
+    private class TriggerLongPress implements Runnable {
+        @Override
+        public void run() {
+            onLongPress();
+        }
+    }
+}
\ No newline at end of file
diff --git a/core/java/android/widget/ListPopupWindow.java b/core/java/android/widget/ListPopupWindow.java
index a02efcf..3d07d87 100644
--- a/core/java/android/widget/ListPopupWindow.java
+++ b/core/java/android/widget/ListPopupWindow.java
@@ -25,7 +25,6 @@
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.os.Handler;
-import android.os.SystemClock;
 import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.util.IntProperty;
@@ -36,13 +35,13 @@
 import android.view.View;
 import android.view.View.MeasureSpec;
 import android.view.View.OnTouchListener;
-import android.view.ViewConfiguration;
 import android.view.ViewGroup;
 import android.view.ViewParent;
 import android.view.WindowManager;
 import android.view.animation.AccelerateDecelerateInterpolator;
 
 import com.android.internal.R;
+import com.android.internal.view.menu.ShowableListMenu;
 import com.android.internal.widget.AutoScrollHelper.AbsListViewAutoScroller;
 
 import java.util.Locale;
@@ -58,7 +57,7 @@
  * @see android.widget.AutoCompleteTextView
  * @see android.widget.Spinner
  */
-public class ListPopupWindow {
+public class ListPopupWindow implements ShowableListMenu {
     private static final String TAG = "ListPopupWindow";
     private static final boolean DEBUG = false;
 
@@ -580,6 +579,7 @@
      * Show the popup list. If the list is already showing, this method
      * will recalculate the popup's size and position.
      */
+    @Override
     public void show() {
         int height = buildDropDown();
 
@@ -671,6 +671,7 @@
     /**
      * Dismiss the popup window.
      */
+    @Override
     public void dismiss() {
         mPopup.dismiss();
         removePromptView();
@@ -732,7 +733,7 @@
     public void setSelection(int position) {
         DropDownListView list = mDropDownList;
         if (isShowing() && list != null) {
-            list.mListSelectionHidden = false;
+            list.setListSelectionHidden(false);
             list.setSelection(position);
             if (list.getChoiceMode() != ListView.CHOICE_MODE_NONE) {
                 list.setItemChecked(position, true);
@@ -748,7 +749,7 @@
         final DropDownListView list = mDropDownList;
         if (list != null) {
             // WARNING: Please read the comment where mListSelectionHidden is declared
-            list.mListSelectionHidden = true;
+            list.setListSelectionHidden(true);
             list.hideSelector();
             list.requestLayout();
         }
@@ -757,6 +758,7 @@
     /**
      * @return {@code true} if the popup is currently showing, {@code false} otherwise.
      */
+    @Override
     public boolean isShowing() {
         return mPopup.isShowing();
     }
@@ -842,6 +844,7 @@
      * @return The {@link ListView} displayed within the popup window.
      * Only valid when {@link #isShowing()} == {@code true}.
      */
+    @Override
     public ListView getListView() {
         return mDropDownList;
     }
@@ -911,7 +914,7 @@
                 } else {
                     // WARNING: Please read the comment where mListSelectionHidden
                     //          is declared
-                    mDropDownList.mListSelectionHidden = false;
+                    mDropDownList.setListSelectionHidden(false);
                 }
 
                 consumed = mDropDownList.onKeyDown(keyCode, event);
@@ -1037,7 +1040,7 @@
     public OnTouchListener createDragToOpenListener(View src) {
         return new ForwardingListener(src) {
             @Override
-            public ListPopupWindow getPopup() {
+            public ShowableListMenu getPopup() {
                 return ListPopupWindow.this;
             }
         };
@@ -1088,7 +1091,7 @@
                         DropDownListView dropDownList = mDropDownList;
 
                         if (dropDownList != null) {
-                            dropDownList.mListSelectionHidden = false;
+                            dropDownList.setListSelectionHidden(false);
                         }
                     }
                 }
@@ -1219,568 +1222,6 @@
         return listContent + otherHeights;
     }
 
-    /**
-     * Abstract class that forwards touch events to a {@link ListPopupWindow}.
-     *
-     * @hide
-     */
-    public static abstract class ForwardingListener
-            implements View.OnTouchListener, View.OnAttachStateChangeListener {
-        /** Scaled touch slop, used for detecting movement outside bounds. */
-        private final float mScaledTouchSlop;
-
-        /** Timeout before disallowing intercept on the source's parent. */
-        private final int mTapTimeout;
-
-        /** Timeout before accepting a long-press to start forwarding. */
-        private final int mLongPressTimeout;
-
-        /** Source view from which events are forwarded. */
-        private final View mSrc;
-
-        /** Runnable used to prevent conflicts with scrolling parents. */
-        private Runnable mDisallowIntercept;
-
-        /** Runnable used to trigger forwarding on long-press. */
-        private Runnable mTriggerLongPress;
-
-        /** Whether this listener is currently forwarding touch events. */
-        private boolean mForwarding;
-
-        /**
-         * Whether forwarding was initiated by a long-press. If so, we won't
-         * force the window to dismiss when the touch stream ends.
-         */
-        private boolean mWasLongPress;
-
-        /** The id of the first pointer down in the current event stream. */
-        private int mActivePointerId;
-
-        public ForwardingListener(View src) {
-            mSrc = src;
-            mScaledTouchSlop = ViewConfiguration.get(src.getContext()).getScaledTouchSlop();
-            mTapTimeout = ViewConfiguration.getTapTimeout();
-
-            // Use a medium-press timeout. Halfway between tap and long-press.
-            mLongPressTimeout = (mTapTimeout + ViewConfiguration.getLongPressTimeout()) / 2;
-
-            src.addOnAttachStateChangeListener(this);
-        }
-
-        /**
-         * Returns the popup to which this listener is forwarding events.
-         * <p>
-         * Override this to return the correct popup. If the popup is displayed
-         * asynchronously, you may also need to override
-         * {@link #onForwardingStopped} to prevent premature cancelation of
-         * forwarding.
-         *
-         * @return the popup to which this listener is forwarding events
-         */
-        public abstract ListPopupWindow getPopup();
-
-        @Override
-        public boolean onTouch(View v, MotionEvent event) {
-            final boolean wasForwarding = mForwarding;
-            final boolean forwarding;
-            if (wasForwarding) {
-                forwarding = onTouchForwarded(event) || !onForwardingStopped();
-            } else {
-                forwarding = onTouchObserved(event) && onForwardingStarted();
-
-                if (forwarding) {
-                    // Make sure we cancel any ongoing source event stream.
-                    final long now = SystemClock.uptimeMillis();
-                    final MotionEvent e = MotionEvent.obtain(now, now, MotionEvent.ACTION_CANCEL,
-                            0.0f, 0.0f, 0);
-                    mSrc.onTouchEvent(e);
-                    e.recycle();
-                }
-            }
-
-            mForwarding = forwarding;
-            return forwarding || wasForwarding;
-        }
-
-        @Override
-        public void onViewAttachedToWindow(View v) {
-        }
-
-        @Override
-        public void onViewDetachedFromWindow(View v) {
-            mForwarding = false;
-            mActivePointerId = MotionEvent.INVALID_POINTER_ID;
-
-            if (mDisallowIntercept != null) {
-                mSrc.removeCallbacks(mDisallowIntercept);
-            }
-        }
-
-        /**
-         * Called when forwarding would like to start.
-         * <p>
-         * By default, this will show the popup returned by {@link #getPopup()}.
-         * It may be overridden to perform another action, like clicking the
-         * source view or preparing the popup before showing it.
-         *
-         * @return true to start forwarding, false otherwise
-         */
-        protected boolean onForwardingStarted() {
-            final ListPopupWindow popup = getPopup();
-            if (popup != null && !popup.isShowing()) {
-                popup.show();
-            }
-            return true;
-        }
-
-        /**
-         * Called when forwarding would like to stop.
-         * <p>
-         * By default, this will dismiss the popup returned by
-         * {@link #getPopup()}. It may be overridden to perform some other
-         * action.
-         *
-         * @return true to stop forwarding, false otherwise
-         */
-        protected boolean onForwardingStopped() {
-            final ListPopupWindow popup = getPopup();
-            if (popup != null && popup.isShowing()) {
-                popup.dismiss();
-            }
-            return true;
-        }
-
-        /**
-         * Observes motion events and determines when to start forwarding.
-         *
-         * @param srcEvent motion event in source view coordinates
-         * @return true to start forwarding motion events, false otherwise
-         */
-        private boolean onTouchObserved(MotionEvent srcEvent) {
-            final View src = mSrc;
-            if (!src.isEnabled()) {
-                return false;
-            }
-
-            final int actionMasked = srcEvent.getActionMasked();
-            switch (actionMasked) {
-                case MotionEvent.ACTION_DOWN:
-                    mActivePointerId = srcEvent.getPointerId(0);
-                    mWasLongPress = false;
-
-                    if (mDisallowIntercept == null) {
-                        mDisallowIntercept = new DisallowIntercept();
-                    }
-                    src.postDelayed(mDisallowIntercept, mTapTimeout);
-
-                    if (mTriggerLongPress == null) {
-                        mTriggerLongPress = new TriggerLongPress();
-                    }
-                    src.postDelayed(mTriggerLongPress, mLongPressTimeout);
-                    break;
-                case MotionEvent.ACTION_MOVE:
-                    final int activePointerIndex = srcEvent.findPointerIndex(mActivePointerId);
-                    if (activePointerIndex >= 0) {
-                        final float x = srcEvent.getX(activePointerIndex);
-                        final float y = srcEvent.getY(activePointerIndex);
-
-                        // Has the pointer has moved outside of the view?
-                        if (!src.pointInView(x, y, mScaledTouchSlop)) {
-                            clearCallbacks();
-
-                            // Don't let the parent intercept our events.
-                            src.getParent().requestDisallowInterceptTouchEvent(true);
-                            return true;
-                        }
-                    }
-                    break;
-                case MotionEvent.ACTION_CANCEL:
-                case MotionEvent.ACTION_UP:
-                    clearCallbacks();
-                    break;
-            }
-
-            return false;
-        }
-
-        private void clearCallbacks() {
-            if (mTriggerLongPress != null) {
-                mSrc.removeCallbacks(mTriggerLongPress);
-            }
-
-            if (mDisallowIntercept != null) {
-                mSrc.removeCallbacks(mDisallowIntercept);
-            }
-        }
-
-        private void onLongPress() {
-            clearCallbacks();
-
-            final View src = mSrc;
-            if (!src.isEnabled() || src.isLongClickable()) {
-                // Ignore long-press if the view is disabled or has its own
-                // handler.
-                return;
-            }
-
-            if (!onForwardingStarted()) {
-                return;
-            }
-
-            // Don't let the parent intercept our events.
-            src.getParent().requestDisallowInterceptTouchEvent(true);
-
-            // Make sure we cancel any ongoing source event stream.
-            final long now = SystemClock.uptimeMillis();
-            final MotionEvent e = MotionEvent.obtain(now, now, MotionEvent.ACTION_CANCEL, 0, 0, 0);
-            src.onTouchEvent(e);
-            e.recycle();
-
-            mForwarding = true;
-            mWasLongPress = true;
-        }
-
-        /**
-         * Handled forwarded motion events and determines when to stop
-         * forwarding.
-         *
-         * @param srcEvent motion event in source view coordinates
-         * @return true to continue forwarding motion events, false to cancel
-         */
-        private boolean onTouchForwarded(MotionEvent srcEvent) {
-            final View src = mSrc;
-            final ListPopupWindow popup = getPopup();
-            if (popup == null || !popup.isShowing()) {
-                return false;
-            }
-
-            final DropDownListView dst = popup.mDropDownList;
-            if (dst == null || !dst.isShown()) {
-                return false;
-            }
-
-            // Convert event to destination-local coordinates.
-            final MotionEvent dstEvent = MotionEvent.obtainNoHistory(srcEvent);
-            src.toGlobalMotionEvent(dstEvent);
-            dst.toLocalMotionEvent(dstEvent);
-
-            // Forward converted event to destination view, then recycle it.
-            final boolean handled = dst.onForwardedEvent(dstEvent, mActivePointerId);
-            dstEvent.recycle();
-
-            // Always cancel forwarding when the touch stream ends.
-            final int action = srcEvent.getActionMasked();
-            final boolean keepForwarding = action != MotionEvent.ACTION_UP
-                    && action != MotionEvent.ACTION_CANCEL;
-
-            return handled && keepForwarding;
-        }
-
-        private class DisallowIntercept implements Runnable {
-            @Override
-            public void run() {
-                final ViewParent parent = mSrc.getParent();
-                parent.requestDisallowInterceptTouchEvent(true);
-            }
-        }
-
-        private class TriggerLongPress implements Runnable {
-            @Override
-            public void run() {
-                onLongPress();
-            }
-        }
-    }
-
-    /**
-     * <p>Wrapper class for a ListView. This wrapper can hijack the focus to
-     * make sure the list uses the appropriate drawables and states when
-     * displayed on screen within a drop down. The focus is never actually
-     * passed to the drop down in this mode; the list only looks focused.</p>
-     */
-    static class DropDownListView extends ListView {
-        /** Duration in milliseconds of the drag-to-open click animation. */
-        private static final long CLICK_ANIM_DURATION = 150;
-
-        /** Target alpha value for drag-to-open click animation. */
-        private static final int CLICK_ANIM_ALPHA = 0x80;
-
-        /** Wrapper around Drawable's <code>alpha</code> property. */
-        private static final IntProperty<Drawable> DRAWABLE_ALPHA =
-                new IntProperty<Drawable>("alpha") {
-                    @Override
-                    public void setValue(Drawable object, int value) {
-                        object.setAlpha(value);
-                    }
-
-                    @Override
-                    public Integer get(Drawable object) {
-                        return object.getAlpha();
-                    }
-                };
-
-        /*
-         * WARNING: This is a workaround for a touch mode issue.
-         *
-         * Touch mode is propagated lazily to windows. This causes problems in
-         * the following scenario:
-         * - Type something in the AutoCompleteTextView and get some results
-         * - Move down with the d-pad to select an item in the list
-         * - Move up with the d-pad until the selection disappears
-         * - Type more text in the AutoCompleteTextView *using the soft keyboard*
-         *   and get new results; you are now in touch mode
-         * - The selection comes back on the first item in the list, even though
-         *   the list is supposed to be in touch mode
-         *
-         * Using the soft keyboard triggers the touch mode change but that change
-         * is propagated to our window only after the first list layout, therefore
-         * after the list attempts to resurrect the selection.
-         *
-         * The trick to work around this issue is to pretend the list is in touch
-         * mode when we know that the selection should not appear, that is when
-         * we know the user moved the selection away from the list.
-         *
-         * This boolean is set to true whenever we explicitly hide the list's
-         * selection and reset to false whenever we know the user moved the
-         * selection back to the list.
-         *
-         * When this boolean is true, isInTouchMode() returns true, otherwise it
-         * returns super.isInTouchMode().
-         */
-        private boolean mListSelectionHidden;
-        
-        /**
-         * True if this wrapper should fake focus.
-         */
-        private boolean mHijackFocus;
-
-        /** Whether to force drawing of the pressed state selector. */
-        private boolean mDrawsInPressedState;
-
-        /** Current drag-to-open click animation, if any. */
-        private Animator mClickAnimation;
-
-        /** Helper for drag-to-open auto scrolling. */
-        private AbsListViewAutoScroller mScrollHelper;
-
-        /**
-         * <p>Creates a new list view wrapper.</p>
-         *
-         * @param context this view's context
-         */
-        public DropDownListView(Context context, boolean hijackFocus) {
-            super(context, null, com.android.internal.R.attr.dropDownListViewStyle);
-            mHijackFocus = hijackFocus;
-            // TODO: Add an API to control this
-            setCacheColorHint(0); // Transparent, since the background drawable could be anything.
-        }
-
-        /**
-         * Handles forwarded events.
-         *
-         * @param activePointerId id of the pointer that activated forwarding
-         * @return whether the event was handled
-         */
-        public boolean onForwardedEvent(MotionEvent event, int activePointerId) {
-            boolean handledEvent = true;
-            boolean clearPressedItem = false;
-
-            final int actionMasked = event.getActionMasked();
-            switch (actionMasked) {
-                case MotionEvent.ACTION_CANCEL:
-                    handledEvent = false;
-                    break;
-                case MotionEvent.ACTION_UP:
-                    handledEvent = false;
-                    // $FALL-THROUGH$
-                case MotionEvent.ACTION_MOVE:
-                    final int activeIndex = event.findPointerIndex(activePointerId);
-                    if (activeIndex < 0) {
-                        handledEvent = false;
-                        break;
-                    }
-
-                    final int x = (int) event.getX(activeIndex);
-                    final int y = (int) event.getY(activeIndex);
-                    final int position = pointToPosition(x, y);
-                    if (position == INVALID_POSITION) {
-                        clearPressedItem = true;
-                        break;
-                    }
-
-                    final View child = getChildAt(position - getFirstVisiblePosition());
-                    setPressedItem(child, position, x, y);
-                    handledEvent = true;
-
-                    if (actionMasked == MotionEvent.ACTION_UP) {
-                        clickPressedItem(child, position);
-                    }
-                    break;
-            }
-
-            // Failure to handle the event cancels forwarding.
-            if (!handledEvent || clearPressedItem) {
-                clearPressedItem();
-            }
-
-            // Manage automatic scrolling.
-            if (handledEvent) {
-                if (mScrollHelper == null) {
-                    mScrollHelper = new AbsListViewAutoScroller(this);
-                }
-                mScrollHelper.setEnabled(true);
-                mScrollHelper.onTouch(this, event);
-            } else if (mScrollHelper != null) {
-                mScrollHelper.setEnabled(false);
-            }
-
-            return handledEvent;
-        }
-
-        /**
-         * Starts an alpha animation on the selector. When the animation ends,
-         * the list performs a click on the item.
-         */
-        private void clickPressedItem(final View child, final int position) {
-            final long id = getItemIdAtPosition(position);
-            final Animator anim = ObjectAnimator.ofInt(
-                    mSelector, DRAWABLE_ALPHA, 0xFF, CLICK_ANIM_ALPHA, 0xFF);
-            anim.setDuration(CLICK_ANIM_DURATION);
-            anim.setInterpolator(new AccelerateDecelerateInterpolator());
-            anim.addListener(new AnimatorListenerAdapter() {
-                    @Override
-                public void onAnimationEnd(Animator animation) {
-                    performItemClick(child, position, id);
-                }
-            });
-            anim.start();
-
-            if (mClickAnimation != null) {
-                mClickAnimation.cancel();
-            }
-            mClickAnimation = anim;
-        }
-
-        private void clearPressedItem() {
-            mDrawsInPressedState = false;
-            setPressed(false);
-            updateSelectorState();
-
-            final View motionView = getChildAt(mMotionPosition - mFirstPosition);
-            if (motionView != null) {
-                motionView.setPressed(false);
-            }
-
-            if (mClickAnimation != null) {
-                mClickAnimation.cancel();
-                mClickAnimation = null;
-            }
-        }
-
-        private void setPressedItem(View child, int position, float x, float y) {
-            mDrawsInPressedState = true;
-
-            // Ordering is essential. First, update the container's pressed state.
-            drawableHotspotChanged(x, y);
-            if (!isPressed()) {
-                setPressed(true);
-            }
-
-            // Next, run layout if we need to stabilize child positions.
-            if (mDataChanged) {
-                layoutChildren();
-            }
-
-            // Manage the pressed view based on motion position. This allows us to
-            // play nicely with actual touch and scroll events.
-            final View motionView = getChildAt(mMotionPosition - mFirstPosition);
-            if (motionView != null && motionView != child && motionView.isPressed()) {
-                motionView.setPressed(false);
-            }
-            mMotionPosition = position;
-
-            // Offset for child coordinates.
-            final float childX = x - child.getLeft();
-            final float childY = y - child.getTop();
-            child.drawableHotspotChanged(childX, childY);
-            if (!child.isPressed()) {
-                child.setPressed(true);
-            }
-
-            // Ensure that keyboard focus starts from the last touched position.
-            setSelectedPositionInt(position);
-            positionSelectorLikeTouch(position, child, x, y);
-
-            // Refresh the drawable state to reflect the new pressed state,
-            // which will also update the selector state.
-            refreshDrawableState();
-
-            if (mClickAnimation != null) {
-                mClickAnimation.cancel();
-                mClickAnimation = null;
-            }
-        }
-
-        @Override
-        boolean touchModeDrawsInPressedState() {
-            return mDrawsInPressedState || super.touchModeDrawsInPressedState();
-        }
-
-        /**
-         * <p>Avoids jarring scrolling effect by ensuring that list elements
-         * made of a text view fit on a single line.</p>
-         *
-         * @param position the item index in the list to get a view for
-         * @return the view for the specified item
-         */
-        @Override
-        View obtainView(int position, boolean[] isScrap) {
-            View view = super.obtainView(position, isScrap);
-
-            if (view instanceof TextView) {
-                ((TextView) view).setHorizontallyScrolling(true);
-            }
-
-            return view;
-        }
-
-        @Override
-        public boolean isInTouchMode() {
-            // WARNING: Please read the comment where mListSelectionHidden is declared
-            return (mHijackFocus && mListSelectionHidden) || super.isInTouchMode();
-        }
-
-        /**
-         * <p>Returns the focus state in the drop down.</p>
-         *
-         * @return true always if hijacking focus
-         */
-        @Override
-        public boolean hasWindowFocus() {
-            return mHijackFocus || super.hasWindowFocus();
-        }
-
-        /**
-         * <p>Returns the focus state in the drop down.</p>
-         *
-         * @return true always if hijacking focus
-         */
-        @Override
-        public boolean isFocused() {
-            return mHijackFocus || super.isFocused();
-        }
-
-        /**
-         * <p>Returns the focus state in the drop down.</p>
-         *
-         * @return true always if hijacking focus
-         */
-        @Override
-        public boolean hasFocus() {
-            return mHijackFocus || super.hasFocus();
-        }
-    }
-
     private class PopupDataSetObserver extends DataSetObserver {
         @Override
         public void onChanged() {
diff --git a/core/java/android/widget/MenuPopupWindow.java b/core/java/android/widget/MenuPopupWindow.java
index 8d42c73..9e47e85 100644
--- a/core/java/android/widget/MenuPopupWindow.java
+++ b/core/java/android/widget/MenuPopupWindow.java
@@ -36,11 +36,11 @@
     }
 
     @Override
-    ListPopupWindow.DropDownListView createDropDownListView(Context context, boolean hijackFocus) {
+    DropDownListView createDropDownListView(Context context, boolean hijackFocus) {
         return new MenuDropDownListView(context, hijackFocus);
     }
 
-    static class MenuDropDownListView extends ListPopupWindow.DropDownListView {
+    static class MenuDropDownListView extends DropDownListView {
         private boolean mHoveredOnDisabledItem = false;
         private AccessibilityManager mAccessibilityManager;
 
diff --git a/core/java/android/widget/PopupMenu.java b/core/java/android/widget/PopupMenu.java
index 1507dfb..3b2d60d 100644
--- a/core/java/android/widget/PopupMenu.java
+++ b/core/java/android/widget/PopupMenu.java
@@ -20,6 +20,7 @@
 import com.android.internal.view.menu.MenuBuilder;
 import com.android.internal.view.menu.MenuPopupHelper;
 import com.android.internal.view.menu.MenuPresenter;
+import com.android.internal.view.menu.ShowableListMenu;
 import com.android.internal.view.menu.SubMenuBuilder;
 
 import android.annotation.MenuRes;
@@ -30,7 +31,6 @@
 import android.view.MenuItem;
 import android.view.View;
 import android.view.View.OnTouchListener;
-import android.widget.ListPopupWindow.ForwardingListener;
 
 /**
  * A PopupMenu displays a {@link Menu} in a modal popup window anchored to a {@link View}.
@@ -170,7 +170,7 @@
                 }
 
                 @Override
-                public ListPopupWindow getPopup() {
+                public ShowableListMenu getPopup() {
                     // This will be null until show() is called.
                     return mPopup.getPopup();
                 }
diff --git a/core/java/android/widget/Spinner.java b/core/java/android/widget/Spinner.java
index f3cf61c..c79e184 100644
--- a/core/java/android/widget/Spinner.java
+++ b/core/java/android/widget/Spinner.java
@@ -17,6 +17,7 @@
 package android.widget;
 
 import com.android.internal.R;
+import com.android.internal.view.menu.ShowableListMenu;
 
 import android.annotation.DrawableRes;
 import android.annotation.Nullable;
@@ -44,7 +45,6 @@
 import android.view.ViewTreeObserver;
 import android.view.ViewTreeObserver.OnGlobalLayoutListener;
 import android.view.accessibility.AccessibilityNodeInfo;
-import android.widget.ListPopupWindow.ForwardingListener;
 import android.widget.PopupWindow.OnDismissListener;
 
 /**
@@ -278,7 +278,7 @@
                 mPopup = popup;
                 mForwardingListener = new ForwardingListener(this) {
                     @Override
-                    public ListPopupWindow getPopup() {
+                    public ShowableListMenu getPopup() {
                         return popup;
                     }
 
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 7a64377..61402ab 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -21,6 +21,7 @@
 import android.annotation.DrawableRes;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.Size;
 import android.annotation.StringRes;
 import android.annotation.StyleRes;
 import android.annotation.XmlRes;
@@ -103,6 +104,7 @@
 import android.text.style.UpdateAppearance;
 import android.text.util.Linkify;
 import android.util.AttributeSet;
+import android.util.LocaleList;
 import android.util.Log;
 import android.util.TypedValue;
 import android.view.AccessibilityIterators.TextSegmentIterator;
@@ -553,7 +555,7 @@
     private final TextPaint mTextPaint;
     private boolean mUserSetTextScaleX;
     private Layout mLayout;
-    private boolean mLocaleChanged = false;
+    private boolean mLocalesChanged = false;
 
     @ViewDebug.ExportedProperty(category = "text")
     private int mGravity = Gravity.TOP | Gravity.START;
@@ -2817,32 +2819,58 @@
     }
 
     /**
-     * Get the default {@link Locale} of the text in this TextView.
-     * @return the default {@link Locale} of the text in this TextView.
+     * Get the default primary {@link Locale} of the text in this TextView. This will always be
+     * the first member of {@link #getTextLocales()}.
+     * @return the default primary {@link Locale} of the text in this TextView.
      */
+    @NonNull
     public Locale getTextLocale() {
         return mTextPaint.getTextLocale();
     }
 
     /**
-     * Set the default {@link Locale} of the text in this TextView to the given value. This value
-     * is used to choose appropriate typefaces for ambiguous characters. Typically used for CJK
-     * locales to disambiguate Hanzi/Kanji/Hanja characters.
+     * Get the default {@link LocaleList} of the text in this TextView.
+     * @return the default {@link LocaleList} of the text in this TextView.
+     */
+    @NonNull @Size(min=1)
+    public LocaleList getTextLocales() {
+        return mTextPaint.getTextLocales();
+    }
+
+    /**
+     * Set the default {@link LocaleList} of the text in this TextView to a one-member list
+     * containing just the given value.
      *
      * @param locale the {@link Locale} for drawing text, must not be null.
      *
-     * @see Paint#setTextLocale
+     * @see #setTextLocales
      */
-    public void setTextLocale(Locale locale) {
-        mLocaleChanged = true;
+    public void setTextLocale(@NonNull Locale locale) {
+        mLocalesChanged = true;
         mTextPaint.setTextLocale(locale);
     }
 
+    /**
+     * Set the default {@link LocaleList} of the text in this TextView to the given value.
+     *
+     * This value is used to choose appropriate typefaces for ambiguous characters (typically used
+     * for CJK locales to disambiguate Hanzi/Kanji/Hanja characters). It also affects
+     * other aspects of text display, including line breaking.
+     *
+     * @param locales the {@link LocaleList} for drawing text, must not be null or empty.
+     *
+     * @see Paint#setTextLocales
+     */
+    public void setTextLocales(@NonNull @Size(min=1) LocaleList locales) {
+        mLocalesChanged = true;
+        mTextPaint.setTextLocales(locales);
+    }
+
     @Override
     protected void onConfigurationChanged(Configuration newConfig) {
         super.onConfigurationChanged(newConfig);
-        if (!mLocaleChanged) {
-            mTextPaint.setTextLocale(Locale.getDefault());
+        if (!mLocalesChanged) {
+            mTextPaint.setTextLocales(LocaleList.getDefault());
         }
     }
 
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 9ca937c..959d249 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -179,8 +179,18 @@
 
     static void preload() {
         Log.d(TAG, "begin preload");
-        preloadClasses();
-        preloadResources();
+        try {
+            Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadClasses");
+            preloadClasses();
+        } finally {
+            Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
+        }
+        try {
+            Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadResources");
+            preloadResources();
+        } finally {
+            Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
+        }
         preloadOpenGL();
         preloadSharedLibraries();
         preloadTextResources();
@@ -266,6 +276,7 @@
                 }
 
                 try {
+                    Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadClass " + line);
                     if (false) {
                         Log.v(TAG, "Preloading " + line + "...");
                     }
@@ -289,6 +300,8 @@
                         throw (RuntimeException) t;
                     }
                     throw new RuntimeException(t);
+                } finally {
+                    Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
                 }
             }
 
@@ -302,7 +315,9 @@
             runtime.setTargetHeapUtilization(defaultUtilization);
 
             // Fill in dex caches with classes, fields, and methods brought in by preloading.
+            Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadDexCaches");
             runtime.preloadDexCaches();
+            Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
 
             // Bring back root. We'll need it later if we're in the zygote.
             if (droppedPriviliges) {
@@ -564,42 +579,57 @@
 
     public static void main(String argv[]) {
         try {
-            RuntimeInit.enableDdms();
-            // Start profiling the zygote initialization.
-            SamplingProfilerIntegration.start();
-
             boolean startSystemServer = false;
             String socketName = "zygote";
             String abiList = null;
-            for (int i = 1; i < argv.length; i++) {
-                if ("start-system-server".equals(argv[i])) {
-                    startSystemServer = true;
-                } else if (argv[i].startsWith(ABI_LIST_ARG)) {
-                    abiList = argv[i].substring(ABI_LIST_ARG.length());
-                } else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
-                    socketName = argv[i].substring(SOCKET_NAME_ARG.length());
-                } else {
-                    throw new RuntimeException("Unknown command line argument: " + argv[i]);
+            try {
+                Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "ZygoteInit");
+                RuntimeInit.enableDdms();
+                // Start profiling the zygote initialization.
+                SamplingProfilerIntegration.start();
+
+                for (int i = 1; i < argv.length; i++) {
+                    if ("start-system-server".equals(argv[i])) {
+                        startSystemServer = true;
+                    } else if (argv[i].startsWith(ABI_LIST_ARG)) {
+                        abiList = argv[i].substring(ABI_LIST_ARG.length());
+                    } else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
+                        socketName = argv[i].substring(SOCKET_NAME_ARG.length());
+                    } else {
+                        throw new RuntimeException("Unknown command line argument: " + argv[i]);
+                    }
                 }
+
+                if (abiList == null) {
+                    throw new RuntimeException("No ABI list supplied.");
+                }
+
+                registerZygoteSocket(socketName);
+                try {
+                    Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "ZygotePreload");
+                    EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
+                            SystemClock.uptimeMillis());
+                    preload();
+                    EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
+                            SystemClock.uptimeMillis());
+                } finally {
+                    Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
+                }
+
+                // Finish profiling the zygote initialization.
+                SamplingProfilerIntegration.writeZygoteSnapshot();
+
+                // Do an initial gc to clean up after startup
+                try {
+                    Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PostZygoteInitGC");
+                    gcAndFinalize();
+                } finally {
+                    Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
+                }
+            } finally {
+                Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
             }
 
-            if (abiList == null) {
-                throw new RuntimeException("No ABI list supplied.");
-            }
-
-            registerZygoteSocket(socketName);
-            EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
-                SystemClock.uptimeMillis());
-            preload();
-            EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
-                SystemClock.uptimeMillis());
-
-            // Finish profiling the zygote initialization.
-            SamplingProfilerIntegration.writeZygoteSnapshot();
-
-            // Do an initial gc to clean up after startup
-            gcAndFinalize();
-
             // Disable tracing so that forked processes do not inherit stale tracing tags from
             // Zygote.
             Trace.setTracingEnabled(false);
diff --git a/core/java/com/android/internal/view/menu/ActionMenuItemView.java b/core/java/com/android/internal/view/menu/ActionMenuItemView.java
index 8db363d..ce5bc90 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuItemView.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuItemView.java
@@ -29,10 +29,10 @@
 import android.view.View;
 import android.view.accessibility.AccessibilityEvent;
 import android.widget.ActionMenuView;
+import android.widget.ForwardingListener;
 import android.widget.ListPopupWindow;
 import android.widget.TextView;
 import android.widget.Toast;
-import android.widget.ListPopupWindow.ForwardingListener;
 
 /**
  * @hide
@@ -320,7 +320,7 @@
         }
 
         @Override
-        public ListPopupWindow getPopup() {
+        public ShowableListMenu getPopup() {
             if (mPopupCallback != null) {
                 return mPopupCallback.getPopup();
             }
@@ -331,7 +331,7 @@
         protected boolean onForwardingStarted() {
             // Call the invoker, then check if the expected popup is showing.
             if (mItemInvoker != null && mItemInvoker.invokeItem(mItemData)) {
-                final ListPopupWindow popup = getPopup();
+                final ShowableListMenu popup = getPopup();
                 return popup != null && popup.isShowing();
             }
             return false;
@@ -339,7 +339,7 @@
 
         @Override
         protected boolean onForwardingStopped() {
-            final ListPopupWindow popup = getPopup();
+            final ShowableListMenu popup = getPopup();
             if (popup != null) {
                 popup.dismiss();
                 return true;
@@ -349,6 +349,6 @@
     }
 
     public static abstract class PopupCallback {
-        public abstract ListPopupWindow getPopup();
+        public abstract ShowableListMenu getPopup();
     }
 }
diff --git a/core/java/com/android/internal/view/menu/ListMenuItemView.java b/core/java/com/android/internal/view/menu/ListMenuItemView.java
index 29ac3f3..2526393 100644
--- a/core/java/com/android/internal/view/menu/ListMenuItemView.java
+++ b/core/java/com/android/internal/view/menu/ListMenuItemView.java
@@ -43,11 +43,13 @@
     private TextView mTitleView;
     private CheckBox mCheckBox;
     private TextView mShortcutView;
+    private ImageView mSubMenuArrowView;
     
     private Drawable mBackground;
     private int mTextAppearance;
     private Context mTextAppearanceContext;
     private boolean mPreserveIconSpacing;
+    private Drawable mSubMenuArrow;
     
     private int mMenuType;
     
@@ -68,6 +70,7 @@
         mPreserveIconSpacing = a.getBoolean(
                 com.android.internal.R.styleable.MenuView_preserveIconSpacing, false);
         mTextAppearanceContext = context;
+        mSubMenuArrow = a.getDrawable(com.android.internal.R.styleable.MenuView_subMenuArrow);
         
         a.recycle();
     }
@@ -77,7 +80,7 @@
     }
 
     public ListMenuItemView(Context context, AttributeSet attrs) {
-        this(context, attrs, 0);
+        this(context, attrs, com.android.internal.R.attr.listMenuViewStyle);
     }
 
     @Override
@@ -93,6 +96,10 @@
         }
         
         mShortcutView = (TextView) findViewById(com.android.internal.R.id.shortcut);
+        mSubMenuArrowView = (ImageView) findViewById(com.android.internal.R.id.submenuarrow);
+        if (mSubMenuArrowView != null) {
+            mSubMenuArrowView.setImageDrawable(mSubMenuArrow);
+        }
     }
 
     public void initialize(MenuItemImpl itemData, int menuType) {
@@ -106,6 +113,7 @@
         setShortcut(itemData.shouldShowShortcut(), itemData.getShortcut());
         setIcon(itemData.getIcon());
         setEnabled(itemData.isEnabled());
+        setSubMenuArrowVisible(itemData.hasSubMenu());
     }
 
     public void setForceShowIcon(boolean forceShow) {
@@ -186,6 +194,12 @@
         compoundButton.setChecked(checked);
     }
 
+    private void setSubMenuArrowVisible(boolean hasSubmenu) {
+        if (mSubMenuArrowView != null) {
+            mSubMenuArrowView.setVisibility(hasSubmenu ? View.VISIBLE : View.GONE);
+        }
+    }
+
     public void setShortcut(boolean showShortcut, char shortcutKey) {
         final int newVisibility = (showShortcut && mItemData.shouldShowShortcut())
                 ? VISIBLE : GONE;
diff --git a/core/java/com/android/internal/view/menu/MenuAdapter.java b/core/java/com/android/internal/view/menu/MenuAdapter.java
new file mode 100644
index 0000000..1e03b1f
--- /dev/null
+++ b/core/java/com/android/internal/view/menu/MenuAdapter.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.view.menu;
+
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+
+import java.util.ArrayList;
+
+public class MenuAdapter extends BaseAdapter {
+    static final int ITEM_LAYOUT = com.android.internal.R.layout.popup_menu_item_layout;
+
+    MenuBuilder mAdapterMenu;
+
+    private int mExpandedIndex = -1;
+
+    private boolean mForceShowIcon;
+    private final boolean mOverflowOnly;
+    private final LayoutInflater mInflater;
+
+    public MenuAdapter(MenuBuilder menu, LayoutInflater inflater, boolean overflowOnly) {
+        mOverflowOnly = overflowOnly;
+        mInflater = inflater;
+        mAdapterMenu = menu;
+        findExpandedIndex();
+    }
+
+    public void setForceShowIcon(boolean forceShow) {
+        mForceShowIcon = forceShow;
+    }
+
+    public int getCount() {
+        ArrayList<MenuItemImpl> items = mOverflowOnly ?
+                mAdapterMenu.getNonActionItems() : mAdapterMenu.getVisibleItems();
+        if (mExpandedIndex < 0) {
+            return items.size();
+        }
+        return items.size() - 1;
+    }
+
+    public MenuBuilder getAdapterMenu() {
+        return mAdapterMenu;
+    }
+
+    public MenuItemImpl getItem(int position) {
+        ArrayList<MenuItemImpl> items = mOverflowOnly ?
+                mAdapterMenu.getNonActionItems() : mAdapterMenu.getVisibleItems();
+        if (mExpandedIndex >= 0 && position >= mExpandedIndex) {
+            position++;
+        }
+        return items.get(position);
+    }
+
+    public long getItemId(int position) {
+        // Since a menu item's ID is optional, we'll use the position as an
+        // ID for the item in the AdapterView
+        return position;
+    }
+
+    public View getView(int position, View convertView, ViewGroup parent) {
+        if (convertView == null) {
+            convertView = mInflater.inflate(ITEM_LAYOUT, parent, false);
+        }
+
+        MenuView.ItemView itemView = (MenuView.ItemView) convertView;
+        if (mForceShowIcon) {
+            ((ListMenuItemView) convertView).setForceShowIcon(true);
+        }
+        itemView.initialize(getItem(position), 0);
+        return convertView;
+    }
+
+    void findExpandedIndex() {
+        final MenuItemImpl expandedItem = mAdapterMenu.getExpandedItem();
+        if (expandedItem != null) {
+            final ArrayList<MenuItemImpl> items = mAdapterMenu.getNonActionItems();
+            final int count = items.size();
+            for (int i = 0; i < count; i++) {
+                final MenuItemImpl item = items.get(i);
+                if (item == expandedItem) {
+                    mExpandedIndex = i;
+                    return;
+                }
+            }
+        }
+        mExpandedIndex = -1;
+    }
+
+    @Override
+    public void notifyDataSetChanged() {
+        findExpandedIndex();
+        super.notifyDataSetChanged();
+    }
+}
\ No newline at end of file
diff --git a/core/java/com/android/internal/view/menu/MenuPopupHelper.java b/core/java/com/android/internal/view/menu/MenuPopupHelper.java
index 13654a6..e6bc6c3 100644
--- a/core/java/com/android/internal/view/menu/MenuPopupHelper.java
+++ b/core/java/com/android/internal/view/menu/MenuPopupHelper.java
@@ -89,7 +89,7 @@
         mContext = context;
         mInflater = LayoutInflater.from(context);
         mMenu = menu;
-        mAdapter = new MenuAdapter(mMenu);
+        mAdapter = new MenuAdapter(mMenu, mInflater, overflowOnly);
         mOverflowOnly = overflowOnly;
         mPopupStyleAttr = popupStyleAttr;
         mPopupStyleRes = popupStyleRes;
@@ -358,73 +358,4 @@
     @Override
     public void onRestoreInstanceState(Parcelable state) {
     }
-
-    private class MenuAdapter extends BaseAdapter {
-        private MenuBuilder mAdapterMenu;
-        private int mExpandedIndex = -1;
-
-        public MenuAdapter(MenuBuilder menu) {
-            mAdapterMenu = menu;
-            findExpandedIndex();
-        }
-
-        public int getCount() {
-            ArrayList<MenuItemImpl> items = mOverflowOnly ?
-                    mAdapterMenu.getNonActionItems() : mAdapterMenu.getVisibleItems();
-            if (mExpandedIndex < 0) {
-                return items.size();
-            }
-            return items.size() - 1;
-        }
-
-        public MenuItemImpl getItem(int position) {
-            ArrayList<MenuItemImpl> items = mOverflowOnly ?
-                    mAdapterMenu.getNonActionItems() : mAdapterMenu.getVisibleItems();
-            if (mExpandedIndex >= 0 && position >= mExpandedIndex) {
-                position++;
-            }
-            return items.get(position);
-        }
-
-        public long getItemId(int position) {
-            // Since a menu item's ID is optional, we'll use the position as an
-            // ID for the item in the AdapterView
-            return position;
-        }
-
-        public View getView(int position, View convertView, ViewGroup parent) {
-            if (convertView == null) {
-                convertView = mInflater.inflate(ITEM_LAYOUT, parent, false);
-            }
-
-            MenuView.ItemView itemView = (MenuView.ItemView) convertView;
-            if (mForceShowIcon) {
-                ((ListMenuItemView) convertView).setForceShowIcon(true);
-            }
-            itemView.initialize(getItem(position), 0);
-            return convertView;
-        }
-
-        void findExpandedIndex() {
-            final MenuItemImpl expandedItem = mMenu.getExpandedItem();
-            if (expandedItem != null) {
-                final ArrayList<MenuItemImpl> items = mMenu.getNonActionItems();
-                final int count = items.size();
-                for (int i = 0; i < count; i++) {
-                    final MenuItemImpl item = items.get(i);
-                    if (item == expandedItem) {
-                        mExpandedIndex = i;
-                        return;
-                    }
-                }
-            }
-            mExpandedIndex = -1;
-        }
-
-        @Override
-        public void notifyDataSetChanged() {
-            findExpandedIndex();
-            super.notifyDataSetChanged();
-        }
-    }
 }
diff --git a/core/java/com/android/internal/view/menu/ShowableListMenu.java b/core/java/com/android/internal/view/menu/ShowableListMenu.java
new file mode 100644
index 0000000..ca158fd
--- /dev/null
+++ b/core/java/com/android/internal/view/menu/ShowableListMenu.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.view.menu;
+
+import android.widget.ListView;
+
+/**
+ * A list menu which can be shown and hidden and which is internally represented by a ListView.
+ */
+public interface ShowableListMenu {
+    public void show();
+
+    public void dismiss();
+
+    public boolean isShowing();
+
+    /**
+     * @return The internal ListView for the visible menu.
+     */
+    public ListView getListView();
+}
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index f7a2f9f..e4bc800 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#define ATRACE_TAG ATRACE_TAG_DALVIK
 #define LOG_TAG "AndroidRuntime"
 //#define LOG_NDEBUG 0
 
@@ -23,6 +24,7 @@
 #include <binder/IServiceManager.h>
 #include <utils/Log.h>
 #include <utils/misc.h>
+#include <utils/Trace.h>
 #include <binder/Parcel.h>
 #include <utils/threads.h>
 #include <cutils/properties.h>
@@ -1437,6 +1439,7 @@
  */
 /*static*/ int AndroidRuntime::startReg(JNIEnv* env)
 {
+    ATRACE_NAME("RegisterAndroidNatives");
     /*
      * This hook causes all future threads created in this process to be
      * attached to the JavaVM.  (This needs to go away in favor of JNI
diff --git a/core/res/res/drawable/ic_arrow_drop_right_black_24dp.xml b/core/res/res/drawable/ic_arrow_drop_right_black_24dp.xml
new file mode 100644
index 0000000..2dd0540
--- /dev/null
+++ b/core/res/res/drawable/ic_arrow_drop_right_black_24dp.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:height="25.0dp"
+    android:viewportHeight="25.0"
+    android:viewportWidth="24.0"
+    android:width="25.0dp"
+    android:tint="?attr/colorControlNormal"
+    android:autoMirrored="true">
+
+    <group
+        android:name="arrow"
+        android:rotation="90.0"
+        android:pivotX="12.0"
+        android:pivotY="13.0"
+        android:translateY="1.0">
+        <path android:fillColor="#000000" android:pathData="M7,14 L12,9 L17,14 L7,14 Z" />
+        <path android:pathData="M0,0 L24,0 L24,24 L0,24 L0,0 Z" />
+    </group>
+</vector>
\ No newline at end of file
diff --git a/core/res/res/layout/popup_menu_item_layout.xml b/core/res/res/layout/popup_menu_item_layout.xml
index 0bc636f..8b8c93a 100644
--- a/core/res/res/layout/popup_menu_item_layout.xml
+++ b/core/res/res/layout/popup_menu_item_layout.xml
@@ -57,6 +57,15 @@
 
     </RelativeLayout>
 
+    <ImageView
+        android:id="@+id/submenuarrow"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center"
+        android:layout_marginStart="8dp"
+        android:scaleType="center"
+        android:visibility="gone" />
+
     <!-- Checkbox, and/or radio button will be inserted here. -->
     
 </com.android.internal.view.menu.ListMenuItemView>
diff --git a/core/res/res/values-ca-watch/strings.xml b/core/res/res/values-ca-watch/strings.xml
index b01ca63..231450f 100644
--- a/core/res/res/values-ca-watch/strings.xml
+++ b/core/res/res/values-ca-watch/strings.xml
@@ -31,7 +31,7 @@
     <string name="permgrouplab_camerawear" msgid="4543951283103407017">"fer fotos i enregistrar vídeos"</string>
     <string name="permgrouplab_phonewear" msgid="134365036753766126">"fer i gestionar trucades telefòniques"</string>
     <string name="permgrouplab_sensorswear" msgid="1429324744329327663">"accedir a les dades del sensor sobre els signes vitals"</string>
-    <string name="permlab_statusBarServicewear" msgid="2469402818964691034">"ser la barra d\'estat"</string>
+    <string name="permlab_statusBarServicewear" msgid="2469402818964691034">"aparèixer a la barra d\'estat"</string>
     <string name="permlab_bodySensorswear" msgid="7857941041202791873">"accedir als sensors corporals (com ara monitors de freqüència cardíaca)"</string>
     <string name="permlab_accessFineLocationwear" msgid="5584423486924377563">"accedir a la ubicació precisa (basada en el GPS i la xarxa)"</string>
     <string name="permlab_accessCoarseLocationwear" msgid="5880746016230166090">"accedir a la ubicació aproximada (basada en la xarxa)"</string>
@@ -40,7 +40,7 @@
     <string name="permlab_manageProfileAndDeviceOwnerswear" msgid="7313340516937821847">"gestionar els propietaris del perfil i del dispositiu"</string>
     <string name="permlab_changeWimaxStatewear" msgid="3828470843939853744">"canviar l\'estat de WiMAX"</string>
     <string name="permlab_handoverStatuswear" msgid="4835786819716499249">"rebre l\'estat de la transferència d\'Android Beam"</string>
-    <string name="permlab_route_media_outputwear" msgid="8737024341474587192">"indicar la ruta de sortida del contingut multimèdia"</string>
+    <string name="permlab_route_media_outputwear" msgid="8737024341474587192">"indicar la sortida del fitxer multimèdia"</string>
     <string name="permlab_readInstallSessionswear" msgid="9059478058685861989">"llegir les sessions d\'instal·lació"</string>
-    <string name="permlab_requestInstallPackageswear" msgid="4982025836783539503">"sol·licitar els paquets d\'instal·lació"</string>
+    <string name="permlab_requestInstallPackageswear" msgid="4982025836783539503">"sol·licitar la instal·lació de paquets"</string>
 </resources>
diff --git a/core/res/res/values-el-watch/strings.xml b/core/res/res/values-el-watch/strings.xml
index 8081013..83d9c3d 100644
--- a/core/res/res/values-el-watch/strings.xml
+++ b/core/res/res/values-el-watch/strings.xml
@@ -42,5 +42,5 @@
     <string name="permlab_handoverStatuswear" msgid="4835786819716499249">"λήψη κατάστασης μεταφοράς Android Beam"</string>
     <string name="permlab_route_media_outputwear" msgid="8737024341474587192">"δρομολόγηση εξόδου μέσων"</string>
     <string name="permlab_readInstallSessionswear" msgid="9059478058685861989">"ανάγνωση περιόδων σύνδεσης εγκατάστασης"</string>
-    <string name="permlab_requestInstallPackageswear" msgid="4982025836783539503">"αίτημα εγκατάστασης πακέτων."</string>
+    <string name="permlab_requestInstallPackageswear" msgid="4982025836783539503">"αίτημα εγκατάστασης πακέτων"</string>
 </resources>
diff --git a/core/res/res/values-eu-rES-watch/strings.xml b/core/res/res/values-eu-rES-watch/strings.xml
index 011105e..0fca702 100644
--- a/core/res/res/values-eu-rES-watch/strings.xml
+++ b/core/res/res/values-eu-rES-watch/strings.xml
@@ -26,7 +26,7 @@
     <string name="permgrouplab_locationwear" msgid="6275317222482780209">"Atzitu erlojuaren kokapena"</string>
     <string name="permgrouplab_calendarwear" msgid="441900844045065081">"Atzitu egutegia"</string>
     <string name="permgrouplab_smswear" msgid="6849506550342974220">"Bidali eta ikusi SMS mezuak"</string>
-    <string name="permgrouplab_storagewear" msgid="1003807594193602313">"Atzitu erlojuko argazkiak, multimedia-elementuak eta fitxategiak"</string>
+    <string name="permgrouplab_storagewear" msgid="1003807594193602313">"Atzitu erlojuko argazkiak, multimedia-edukia eta fitxategiak"</string>
     <string name="permgrouplab_microphonewear" msgid="1047561180980891136">"Grabatu audioa"</string>
     <string name="permgrouplab_camerawear" msgid="4543951283103407017">"Atera argazkiak eta grabatu bideoak"</string>
     <string name="permgrouplab_phonewear" msgid="134365036753766126">"Egin eta kudeatu telefono-deiak"</string>
diff --git a/core/res/res/values-ml-rIN/strings.xml b/core/res/res/values-ml-rIN/strings.xml
index 43264a7..2bdc9c8 100644
--- a/core/res/res/values-ml-rIN/strings.xml
+++ b/core/res/res/values-ml-rIN/strings.xml
@@ -1149,7 +1149,7 @@
     <string name="sync_really_delete" msgid="2572600103122596243">"ഇനങ്ങൾ ഇല്ലാതാക്കുക"</string>
     <string name="sync_undo_deletes" msgid="2941317360600338602">"ഇല്ലാതാക്കിയവ പഴയപടിയാക്കുക"</string>
     <string name="sync_do_nothing" msgid="3743764740430821845">"ഇപ്പോൾ ഒന്നും ചെയ്യേണ്ടതില്ല"</string>
-    <string name="choose_account_label" msgid="5655203089746423927">"ഒരു അക്കൗണ്ട് തിരഞ്ഞെടുക്കുക"</string>
+    <string name="choose_account_label" msgid="5655203089746423927">"അക്കൗണ്ട് തിരഞ്ഞെടുക്കൂ"</string>
     <string name="add_account_label" msgid="2935267344849993553">"ഒരു അക്കൗണ്ട് ചേർക്കുക"</string>
     <string name="add_account_button_label" msgid="3611982894853435874">"അക്കൗണ്ട് ചേർക്കുക"</string>
     <string name="number_picker_increment_button" msgid="2412072272832284313">"വർദ്ധിപ്പിക്കുക"</string>
diff --git a/core/res/res/values-ne-rNP-watch/strings.xml b/core/res/res/values-ne-rNP-watch/strings.xml
index a38de99..1b4ffc9 100644
--- a/core/res/res/values-ne-rNP-watch/strings.xml
+++ b/core/res/res/values-ne-rNP-watch/strings.xml
@@ -26,7 +26,7 @@
     <string name="permgrouplab_locationwear" msgid="6275317222482780209">"यो घडीको स्थान पहुँच गर्नुहोस्"</string>
     <string name="permgrouplab_calendarwear" msgid="441900844045065081">"आफ्नो पात्रोमा पहुँच गर्नुहोस्"</string>
     <string name="permgrouplab_smswear" msgid="6849506550342974220">"SMS सन्देशहरू पठाउनुहोस् र हेर्नुहोस्"</string>
-    <string name="permgrouplab_storagewear" msgid="1003807594193602313">"आफ्नो समयमा फोटो, मिडिया, र फाइलहरू हेर्नुहोस्"</string>
+    <string name="permgrouplab_storagewear" msgid="1003807594193602313">"आफ्नो समयमा तस्बिर, मिडिया, र फाइलहरू हेर्नुहोस्"</string>
     <string name="permgrouplab_microphonewear" msgid="1047561180980891136">"अडियो रेकर्ड गर्नुहोस्"</string>
     <string name="permgrouplab_camerawear" msgid="4543951283103407017">"तस्बिरहरू खिच्नुहोस् र भिडियो रेकर्ड गर्नुहोस्"</string>
     <string name="permgrouplab_phonewear" msgid="134365036753766126">"फोन कलहरू गर्नुहोस् र व्यवस्थापन गर्नुहोस्"</string>
diff --git a/core/res/res/values-ta-rIN-watch/strings.xml b/core/res/res/values-ta-rIN-watch/strings.xml
index 63e072f..629ca27 100644
--- a/core/res/res/values-ta-rIN-watch/strings.xml
+++ b/core/res/res/values-ta-rIN-watch/strings.xml
@@ -29,7 +29,7 @@
     <string name="permgrouplab_storagewear" msgid="1003807594193602313">"உங்கள் வாட்சில் உள்ள படங்கள், மீடியா மற்றும் கோப்புகளை அணுகும்"</string>
     <string name="permgrouplab_microphonewear" msgid="1047561180980891136">"ஆடியோவைப் பதிவுசெய்யும்"</string>
     <string name="permgrouplab_camerawear" msgid="4543951283103407017">"படங்களை எடுக்கும், வீடியோவைப் பதிவுசெய்யும்"</string>
-    <string name="permgrouplab_phonewear" msgid="134365036753766126">"மொபைல் அழைப்புகளைச் செய்யும், பெறும்"</string>
+    <string name="permgrouplab_phonewear" msgid="134365036753766126">"மொபைல் அழைப்புகளைச் செய்யும், நிர்வகிக்கும்"</string>
     <string name="permgrouplab_sensorswear" msgid="1429324744329327663">"உங்கள் உடலியக்கக் குறிகள் பற்றிய உணர்வித் தரவை அணுகும்"</string>
     <string name="permlab_statusBarServicewear" msgid="2469402818964691034">"நிலைப் பட்டியில் இருக்கும்"</string>
     <string name="permlab_bodySensorswear" msgid="7857941041202791873">"உடல் உணர்விகளை (இதயத் துடிப்பு மானிட்டர்கள் போன்றவை) அணுகும்"</string>
diff --git a/core/res/res/values-ur-rPK/strings.xml b/core/res/res/values-ur-rPK/strings.xml
index aa46949..e6e20f1 100644
--- a/core/res/res/values-ur-rPK/strings.xml
+++ b/core/res/res/values-ur-rPK/strings.xml
@@ -429,7 +429,7 @@
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"فنگر پرنٹ اسٹور نہیں کیا جا سکتا ہے۔ براہ کرم ایک موجودہ فنگر پرنٹ ہٹائیں۔"</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"فنگر پرنٹ کی میعاد ختم ہوگئی۔ دوبارہ کوشش کریں۔"</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"فنگر پرنٹ کی کارروائی منسوخ ہوگئی۔"</string>
-    <string name="fingerprint_error_lockout" msgid="5536934748136933450">"کافی زیادہ کوششیں کی گئیں۔ بعد میں دوباہ کوشش کریں۔"</string>
+    <string name="fingerprint_error_lockout" msgid="5536934748136933450">"کافی زیادہ کوششیں کی گئیں۔ بعد میں دوبارہ کوشش کریں۔"</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"دوبارہ کوشش کریں۔"</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"انگلی <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 61af6c5..59d1a7c 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -639,6 +639,8 @@
         <attr name="imageButtonStyle" format="reference" />
         <!-- The style resource to use for an ImageButton that is an image well. -->
         <attr name="imageWellStyle" format="reference" />
+        <!-- Default menu-style ListView style. -->
+        <attr name="listMenuViewStyle" format="reference" />
         <!-- Default ListView style. -->
         <attr name="listViewStyle" format="reference" />
         <!-- ListView with white background. -->
@@ -3784,6 +3786,8 @@
         <attr name="itemIconDisabledAlpha" format="float" />
         <!-- Whether space should be reserved in layout when an icon is missing. -->
         <attr name="preserveIconSpacing" format="boolean" />
+        <!-- Drawable for the arrow icon indicating a particular item is a submenu. -->
+        <attr name="subMenuArrow" format="reference" />
     </declare-styleable>
     <declare-styleable name="IconMenuView">
         <!-- Defines the height of each row. -->
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index d2089cd..c89b31b 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2660,6 +2660,9 @@
        =============================================================== -->
     <eat-comment />
 
+    <public type="attr" name="listMenuViewStyle" />
+    <public type="attr" name="subMenuArrow" />
+
     <public type="style" name="Theme.Material.DayNight" />
     <public type="style" name="Theme.Material.DayNight.DarkActionBar" />
     <public type="style" name="Theme.Material.DayNight.Dialog" />
diff --git a/core/res/res/values/styles_material.xml b/core/res/res/values/styles_material.xml
index 2369c9b..5dc14e3 100644
--- a/core/res/res/values/styles_material.xml
+++ b/core/res/res/values/styles_material.xml
@@ -685,6 +685,10 @@
 
     <style name="Widget.Material.ListView.White"/>
 
+    <style name="Widget.Material.ListMenuView">
+        <item name="subMenuArrow">@drawable/ic_arrow_drop_right_black_24dp</item>
+    </style>
+
     <style name="Widget.Material.PopupWindow" parent="Widget.PopupWindow"/>
 
     <style name="Widget.Material.PopupWindow.ActionMode">
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index e04c743..98c9f77 100755
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -158,6 +158,7 @@
   <java-symbol type="id" name="shortcut" />
   <java-symbol type="id" name="skip_button" />
   <java-symbol type="id" name="split_action_bar" />
+  <java-symbol type="id" name="submenuarrow" />
   <java-symbol type="id" name="submit_area" />
   <java-symbol type="id" name="switch_new" />
   <java-symbol type="id" name="switch_old" />
diff --git a/core/res/res/values/themes_material.xml b/core/res/res/values/themes_material.xml
index e406ae0..3010190 100644
--- a/core/res/res/values/themes_material.xml
+++ b/core/res/res/values/themes_material.xml
@@ -238,6 +238,7 @@
         <item name="gridViewStyle">@style/Widget.Material.GridView</item>
         <item name="imageButtonStyle">@style/Widget.Material.ImageButton</item>
         <item name="imageWellStyle">@style/Widget.Material.ImageWell</item>
+        <item name="listMenuViewStyle">@style/Widget.Material.ListMenuView</item>
         <item name="listViewStyle">@style/Widget.Material.ListView</item>
         <item name="listViewWhiteStyle">@style/Widget.Material.ListView.White</item>
         <item name="popupWindowStyle">@style/Widget.Material.PopupWindow</item>
@@ -594,6 +595,7 @@
         <item name="gridViewStyle">@style/Widget.Material.Light.GridView</item>
         <item name="imageButtonStyle">@style/Widget.Material.Light.ImageButton</item>
         <item name="imageWellStyle">@style/Widget.Material.Light.ImageWell</item>
+        <item name="listMenuViewStyle">@style/Widget.Material.ListMenuView</item>
         <item name="listViewStyle">@style/Widget.Material.Light.ListView</item>
         <item name="listViewWhiteStyle">@style/Widget.Material.Light.ListView.White</item>
         <item name="popupWindowStyle">@style/Widget.Material.Light.PopupWindow</item>
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index c5d68bd..ce35b87 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -17,10 +17,13 @@
 package android.graphics;
 
 import android.annotation.ColorInt;
+import android.annotation.NonNull;
+import android.annotation.Size;
 import android.text.GraphicsOperations;
 import android.text.SpannableString;
 import android.text.SpannedString;
 import android.text.TextUtils;
+import android.util.LocaleList;
 
 import java.util.Locale;
 
@@ -50,7 +53,7 @@
     private float       mCompatScaling;
     private float       mInvCompatScaling;
 
-    private Locale      mLocale;
+    private LocaleList  mLocales;
     private String      mFontFeatureSettings;
 
     /**
@@ -434,7 +437,7 @@
         // setHinting(DisplayMetrics.DENSITY_DEVICE >= DisplayMetrics.DENSITY_TV
         //        ? HINTING_OFF : HINTING_ON);
         mCompatScaling = mInvCompatScaling = 1;
-        setTextLocale(Locale.getDefault());
+        setTextLocales(LocaleList.getDefault());
     }
 
     /**
@@ -474,7 +477,7 @@
         mInvCompatScaling = 1;
 
         mBidiFlags = BIDI_DEFAULT_LTR;
-        setTextLocale(Locale.getDefault());
+        setTextLocales(LocaleList.getDefault());
         setElegantTextHeight(false);
         mFontFeatureSettings = null;
     }
@@ -512,7 +515,7 @@
         mInvCompatScaling = paint.mInvCompatScaling;
 
         mBidiFlags = paint.mBidiFlags;
-        mLocale = paint.mLocale;
+        mLocales = paint.mLocales;
         mFontFeatureSettings = paint.mFontFeatureSettings;
     }
 
@@ -1174,47 +1177,80 @@
     }
 
     /**
-     * Get the text Locale.
+     * Get the text's primary Locale. Note that this is not all of the locale-related information
+     * Paint has. Use {@link #getTextLocales()} to get the complete list.
      *
-     * @return the paint's Locale used for drawing text, never null.
+     * @return the paint's primary Locale used for drawing text, never null.
      */
+    @NonNull
     public Locale getTextLocale() {
-        return mLocale;
+        return mLocales.getPrimary();
     }
 
     /**
-     * Set the text locale.
+     * Get the text locale list.
      *
-     * The text locale affects how the text is drawn for some languages.
+     * @return the paint's LocaleList used for drawing text, never null or empty.
+     */
+    @NonNull @Size(min=1)
+    public LocaleList getTextLocales() {
+        return mLocales;
+    }
+
+    /**
+     * Set the text locale list to a one-member list consisting of just the locale.
      *
-     * For example, if the locale is {@link Locale#CHINESE} or {@link Locale#CHINA},
+     * See {@link #setTextLocales(LocaleList)} for how the locale list affects
+     * the way the text is drawn for some languages.
+     *
+     * @param locale the paint's locale value for drawing text, must not be null.
+     */
+    public void setTextLocale(@NonNull Locale locale) {
+        if (locale == null) {
+            throw new IllegalArgumentException("locale cannot be null");
+        }
+        if (mLocales != null && mLocales.size() == 1 && locale.equals(mLocales.getPrimary())) {
+            return;
+        }
+        mLocales = new LocaleList(locale);
+        native_setTextLocale(mNativePaint, locale.toString());
+    }
+
+    /**
+     * Set the text locale list.
+     *
+     * The text locale list affects how the text is drawn for some languages.
+     *
+     * For example, if the locale list contains {@link Locale#CHINESE} or {@link Locale#CHINA},
      * then the text renderer will prefer to draw text using a Chinese font. Likewise,
-     * if the locale is {@link Locale#JAPANESE} or {@link Locale#JAPAN}, then the text
-     * renderer will prefer to draw text using a Japanese font.
+     * if the locale list contains {@link Locale#JAPANESE} or {@link Locale#JAPAN}, then the text
+     * renderer will prefer to draw text using a Japanese font. If the locale list contains both,
+     * the order those locales appear in the list is considered for deciding the font.
      *
      * This distinction is important because Chinese and Japanese text both use many
      * of the same Unicode code points but their appearance is subtly different for
      * each language.
      *
-     * By default, the text locale is initialized to the system locale (as returned
-     * by {@link Locale#getDefault}). This assumes that the text to be rendered will
-     * most likely be in the user's preferred language.
+     * By default, the text locale list is initialized to a one-member list just containing the
+     * system locale (as returned by {@link LocaleList#getDefault()}). This assumes that the text to
+     * be rendered will most likely be in the user's preferred language.
      *
-     * If the actual language of the text is known, then it can be provided to the
-     * text renderer using this method. The text renderer may attempt to guess the
+     * If the actual language or languages of the text is/are known, then they can be provided to
+     * the text renderer using this method. The text renderer may attempt to guess the
      * language script based on the contents of the text to be drawn independent of
-     * the text locale here. Specifying the text locale just helps it do a better
-     * job in certain ambiguous cases
+     * the text locale here. Specifying the text locales just helps it do a better
+     * job in certain ambiguous cases.
      *
-     * @param locale the paint's locale value for drawing text, must not be null.
+     * @param locales the paint's locale list for drawing text, must not be null or empty.
      */
-    public void setTextLocale(Locale locale) {
-        if (locale == null) {
-            throw new IllegalArgumentException("locale cannot be null");
+    public void setTextLocales(@NonNull @Size(min=1) LocaleList locales) {
+        if (locales == null || locales.isEmpty()) {
+            throw new IllegalArgumentException("locales cannot be null or empty");
         }
-        if (locale.equals(mLocale)) return;
-        mLocale = locale;
-        native_setTextLocale(mNativePaint, locale.toString());
+        if (locales.equals(mLocales)) return;
+        mLocales = locales;
+        // TODO: Pass the whole LocaleList to native code
+        native_setTextLocale(mNativePaint, locales.getPrimary().toString());
     }
 
     /**
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/CursorHelper.java b/packages/MtpDocumentsProvider/src/com/android/mtp/CursorHelper.java
index 48d5dcf..b5694b7 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/CursorHelper.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/CursorHelper.java
@@ -17,6 +17,7 @@
 package com.android.mtp;
 
 import android.database.MatrixCursor;
+import android.mtp.MtpConstants;
 import android.mtp.MtpObjectInfo;
 import android.provider.DocumentsContract;
 import android.provider.DocumentsContract.Document;
@@ -72,11 +73,11 @@
     static String formatTypeToMimeType(int format) {
         // TODO: Add complete list of mime types.
         switch (format) {
-            case 0x3001:
+            case MtpConstants.FORMAT_ASSOCIATION:
                 return DocumentsContract.Document.MIME_TYPE_DIR;
-            case 0x3009:
+            case MtpConstants.FORMAT_MP3:
                 return "audio/mp3";
-            case 0x3801:
+            case MtpConstants.FORMAT_EXIF_JPEG:
                 return "image/jpeg";
             default:
                 return "application/octet-stream";
@@ -87,13 +88,13 @@
         // TODO: Add complete list of mime types.
         switch (mimeType.toLowerCase()) {
             case Document.MIME_TYPE_DIR:
-                return 0x3001;
+                return MtpConstants.FORMAT_ASSOCIATION;
             case "audio/mp3":
-                return 0x3009;
+                return MtpConstants.FORMAT_MP3;
             case "image/jpeg":
-                return 0x3801;
+                return MtpConstants.FORMAT_EXIF_JPEG;
             default:
-                return 0x3000;  // Undefined object.
+                return MtpConstants.FORMAT_UNDEFINED;
         }
     }
 }
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java
index cbb72d1..9b316be 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java
@@ -209,7 +209,7 @@
     public void testQueryDocument() throws IOException {
         mMtpManager.setObjectInfo(0, new MtpObjectInfo.Builder()
                 .setObjectHandle(2)
-                .setFormat(0x3801)
+                .setFormat(MtpConstants.FORMAT_EXIF_JPEG)
                 .setName("image.jpg")
                 .setDateModified(1422716400000L)
                 .setCompressedSize(1024 * 1024 * 5)
@@ -234,7 +234,7 @@
     public void testQueryDocument_directory() throws IOException {
         mMtpManager.setObjectInfo(0, new MtpObjectInfo.Builder()
                 .setObjectHandle(2)
-                .setFormat(0x3001 /* directory format */)
+                .setFormat(MtpConstants.FORMAT_ASSOCIATION)
                 .setName("directory")
                 .setDateModified(1422716400000L)
                 .build());
@@ -281,7 +281,7 @@
 
         mMtpManager.setObjectInfo(0, new MtpObjectInfo.Builder()
                 .setObjectHandle(1)
-                .setFormat(0x3801 /* JPEG */)
+                .setFormat(MtpConstants.FORMAT_EXIF_JPEG)
                 .setName("image.jpg")
                 .setCompressedSize(1024 * 1024 * 5)
                 .setThumbCompressedSize(5 * 1024)
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 9294a16..1473f24 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -435,4 +435,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"Program is nie op jou toestel geïnstalleer nie"</string>
     <string name="clock_seconds" msgid="7689554147579179507">"Wys horlosiesekondes"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Wys horlosiesekondes op die statusbalk. Sal batterylewe dalk beïnvloed."</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"Herrangskik Kitsinstellings"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"Wys helderheid in Kitsinstellings"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"Gebruik verdeling in Kitsinstellings"</string>
+    <string name="experimental" msgid="6198182315536726162">"Eksperimenteel"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 13f768d..7ab6af9 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -435,4 +435,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"መተግበሪያ በእርስዎ መሣሪያ ላይ አልተጫነም"</string>
     <string name="clock_seconds" msgid="7689554147579179507">"የሰዓት ሰከንዶችን አሳይ"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"የሰዓት ሰከንዶችን በሁኔታ አሞሌ ውስጥ አሳይ። በባትሪ ዕድሜ ላይ ተጽዕኖ ሊኖርው ይችል ይሆናል።"</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"ፈጣን ቅንብሮችን ዳግም ያደራጁ"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"በፈጣን ቅንብሮች ውስጥ ብሩህነትን አሳይ"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"በፈጣን ቅንብሮች ውስጥ ምልክት መጥሪያን ይጠቀሙ"</string>
+    <string name="experimental" msgid="6198182315536726162">"የሙከራ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 6889a43..bd02650 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -439,4 +439,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"التطبيق غير مثبّت على جهازك"</string>
     <string name="clock_seconds" msgid="7689554147579179507">"عرض ثواني الساعة"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"عرض ثواني الساعة في شريط الحالة. قد يؤثر ذلك في عمر البطارية."</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"إعادة ترتيب الإعدادات السريعة"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"عرض السطوع في الإعدادات السريعة"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"استخدام ترقيم الصفحات في الإعدادات السريعة"</string>
+    <string name="experimental" msgid="6198182315536726162">"إعدادات تجريبية"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-az-rAZ/strings.xml b/packages/SystemUI/res/values-az-rAZ/strings.xml
index 51513bd..a0d7d2b 100644
--- a/packages/SystemUI/res/values-az-rAZ/strings.xml
+++ b/packages/SystemUI/res/values-az-rAZ/strings.xml
@@ -435,4 +435,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"Tətbiq cihazınızda quraşdırılmayıb"</string>
     <string name="clock_seconds" msgid="7689554147579179507">"Saatın saniyəsini göstərin"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Saatın saniyəsini status panelində göstərin. Batareyaya təsir edə bilər."</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"Sürətli Ayarları yenidən tənzimləyin"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"Sürətli ayarlarda parlaqlılığı göstərin"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"Sürətli Ayarlarda səhifə nömrələməsindən istifadə edin"</string>
+    <string name="experimental" msgid="6198182315536726162">"Eksperimental"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 014d802..a14d0fc 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -435,4 +435,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"Приложението не е инсталирано на устройството ви"</string>
     <string name="clock_seconds" msgid="7689554147579179507">"Показване на секундите на часовника"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Показване на секундите на часовника в лентата на състоянието. Може да се отрази на живота на батерията."</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"Пренареждане на бързите настройки"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"Показване на яркостта от бързите настройки"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"Използване на разделянето на страници от бързите настройки"</string>
+    <string name="experimental" msgid="6198182315536726162">"Експериментални"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-bn-rBD/strings.xml b/packages/SystemUI/res/values-bn-rBD/strings.xml
index 0860019..e819d54 100644
--- a/packages/SystemUI/res/values-bn-rBD/strings.xml
+++ b/packages/SystemUI/res/values-bn-rBD/strings.xml
@@ -435,4 +435,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"আপনার ডিভাইসে অ্যাপ্লিকেশান ইনস্টল করা নেই"</string>
     <string name="clock_seconds" msgid="7689554147579179507">"ঘড়ির সেকেন্ড দেখায়"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"স্থিতি দন্ডে ঘড়ির সেকেন্ড দেখায়৷ ব্যাটারি লাইফকে প্রভাবিত করতে পারে৷"</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"দ্রুত সেটিংসে পুনরায় সাজান"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"দ্রুত সেটিংসে উজ্জ্বলতা দেখান"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"দ্রুত সেটিংসে পেজিং ব্যবহার করুন"</string>
+    <string name="experimental" msgid="6198182315536726162">"পরীক্ষামূলক"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 9c32052..7def415f 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -437,4 +437,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"L\'aplicació no està instal·lada al dispositiu"</string>
     <string name="clock_seconds" msgid="7689554147579179507">"Mostra els segons del rellotge"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Mostra els segons del rellotge a la barra d\'estat. Això pot afectar la durada de la bateria."</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"Torna a ordenar la Configuració ràpida"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"Mostra la brillantor a la Configuració ràpida"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"Utilitza la paginació a la Configuració ràpida"</string>
+    <string name="experimental" msgid="6198182315536726162">"Experimental"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 4d96a01..a73947f 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -439,4 +439,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"Aplikace není v zařízení nainstalována."</string>
     <string name="clock_seconds" msgid="7689554147579179507">"Zobrazit sekundovou ručičku"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Na stavovém řádku se bude zobrazovat sekundová ručička. Může být ovlivněna výdrž baterie."</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"Změnit uspořádání Rychlého nastavení"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"Zobrazit jas v Rychlém nastavení"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"Použít v Rychlém nastavení stránkování"</string>
+    <string name="experimental" msgid="6198182315536726162">"Experimentální"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 7f005a3..6f49187 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -435,4 +435,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"Applikationen er ikke installeret på din enhed."</string>
     <string name="clock_seconds" msgid="7689554147579179507">"Vis sekunder"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Vis sekunder i statuslinjen. Dette kan påvirke batteriets levetid."</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"Omarranger Hurtige indstillinger"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"Vis lysstyrke i Hurtige indstillinger"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"Brug sidelayout i Hurtige indstillinger"</string>
+    <string name="experimental" msgid="6198182315536726162">"Eksperimentel"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 36f3c98..a659077 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -437,4 +437,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"Die App ist nicht auf Ihrem Gerät installiert."</string>
     <string name="clock_seconds" msgid="7689554147579179507">"Uhrsekunden anzeigen"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Uhrsekunden in der Statusleiste anzeigen. Kann sich auf die Akkulaufzeit auswirken."</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"Schnelleinstellungen neu anordnen"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"Helligkeit in den Schnelleinstellungen anzeigen"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"Seitenlayout in den Schnelleinstellungen verwenden"</string>
+    <string name="experimental" msgid="6198182315536726162">"Experimentell"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 8e73b21..bcfc458 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -437,4 +437,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"Η εφαρμογή δεν έχει εγκατασταθεί στη συσκευή σας"</string>
     <string name="clock_seconds" msgid="7689554147579179507">"Εμφάνιση δευτερολέπτων ρολογιού"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Εμφάνιση δευτερολέπτων ρολογιού στη γραμμή κατάστασης. Ενδέχεται να επηρεάσει τη διάρκεια ζωής της μπαταρίας."</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"Αναδιάταξη Γρήγορων ρυθμίσεων"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"Εμφάνιση φωτεινότητας στις Γρήγορες ρυθμίσεις"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"Χρήση τηλεειδοποίησης στις Γρήγορες ρυθμίσεις"</string>
+    <string name="experimental" msgid="6198182315536726162">"Σε πειραματικό στάδιο"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index 0b49955..fb781d4 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -435,4 +435,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"Application is not installed on your device"</string>
     <string name="clock_seconds" msgid="7689554147579179507">"Show clock seconds"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Show clock seconds in the status bar. May impact battery life."</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"Rearrange Quick Settings"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"Show brightness in Quick Settings"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"Use paging in Quick Settings"</string>
+    <string name="experimental" msgid="6198182315536726162">"Experimental"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 0b49955..fb781d4 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -435,4 +435,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"Application is not installed on your device"</string>
     <string name="clock_seconds" msgid="7689554147579179507">"Show clock seconds"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Show clock seconds in the status bar. May impact battery life."</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"Rearrange Quick Settings"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"Show brightness in Quick Settings"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"Use paging in Quick Settings"</string>
+    <string name="experimental" msgid="6198182315536726162">"Experimental"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 0b49955..fb781d4 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -435,4 +435,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"Application is not installed on your device"</string>
     <string name="clock_seconds" msgid="7689554147579179507">"Show clock seconds"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Show clock seconds in the status bar. May impact battery life."</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"Rearrange Quick Settings"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"Show brightness in Quick Settings"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"Use paging in Quick Settings"</string>
+    <string name="experimental" msgid="6198182315536726162">"Experimental"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index c4dca9c..10834a2 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -437,4 +437,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"La aplicación no está instalada en el dispositivo"</string>
     <string name="clock_seconds" msgid="7689554147579179507">"Mostrar los segundos del reloj"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Muestra los segundos del reloj en la barra de estado. Puede afectar la duración de la batería."</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"Reorganizar la Configuración rápida"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"Mostrar el brillo en la Configuración rápida"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"Usar la paginación en la Configuración rápida"</string>
+    <string name="experimental" msgid="6198182315536726162">"Experimental"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index e316a94..37c81f4 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -435,4 +435,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"La aplicación no está instalada en tu dispositivo"</string>
     <string name="clock_seconds" msgid="7689554147579179507">"Mostrar los segundos del reloj"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Muestra los segundos del reloj en la barra de estado. Puede afectar a la duración de la batería."</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"Reorganizar Ajustes rápidos"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"Mostrar brillo en Ajustes rápidos"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"Utilizar paginación en Ajustes rápidos"</string>
+    <string name="experimental" msgid="6198182315536726162">"Experimental"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-et-rEE/strings.xml b/packages/SystemUI/res/values-et-rEE/strings.xml
index a151bce..f4218a3 100644
--- a/packages/SystemUI/res/values-et-rEE/strings.xml
+++ b/packages/SystemUI/res/values-et-rEE/strings.xml
@@ -435,4 +435,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"Rakendust pole teie seadmesse installitud"</string>
     <string name="clock_seconds" msgid="7689554147579179507">"Kella sekundite kuvamine"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Olekuribal kella sekundite kuvamine. See võib mõjutada aku kasutusaega."</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"Korralda kiirseaded ümber"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"Kuva kiirseadetes heledus"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"Kasuta kiirseadetes lehe paigutust"</string>
+    <string name="experimental" msgid="6198182315536726162">"Eksperimentaalne"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-eu-rES/strings.xml b/packages/SystemUI/res/values-eu-rES/strings.xml
index 37cdee7..fbf0eb42 100644
--- a/packages/SystemUI/res/values-eu-rES/strings.xml
+++ b/packages/SystemUI/res/values-eu-rES/strings.xml
@@ -435,4 +435,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"Aplikazioa ez dago gailuan instalatuta"</string>
     <string name="clock_seconds" msgid="7689554147579179507">"Erakutsi erlojuko segundoak"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Erakutsi erlojuko segundoak egoera-barran. Baliteke bateria gehiago erabiltzea."</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"Berrantolatu ezarpen bizkorrak"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"Erakutsi ezarpen bizkorren distira"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"Erabili ezarpen bizkorretako orriak pasatzeko diseinu berria"</string>
+    <string name="experimental" msgid="6198182315536726162">"Esperimentala"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 80d0918..fa01c47 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -435,4 +435,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"برنامه در دستگاه شما نصب نیست"</string>
     <string name="clock_seconds" msgid="7689554147579179507">"نمایش ثانیه‌های ساعت"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"ثانیه‌های ساعت را در نوار وضعیت نشان می‌دهد. ممکن است بر ماندگاری باتری تأثیر بگذارد."</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"ترتیب مجدد در تنظیمات سریع"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"نمایش روشنایی در تنظیمات سریع"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"استفاده از صفحه‌بندی در تنظیمات سریع"</string>
+    <string name="experimental" msgid="6198182315536726162">"آزمایشی"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index b86247a..6c4a029 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -435,4 +435,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"Sovellusta ei ole asennettu laitteellesi."</string>
     <string name="clock_seconds" msgid="7689554147579179507">"Näytä sekunnit kellossa"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Näytä sekunnit tilapalkin kellossa. Tämä voi vaikuttaa akun kestoon."</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"Järjestä pika-asetukset uudelleen"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"Näytä kirkkaus pika-asetuksissa"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"Käytä sivutusta pika-asetuksissa"</string>
+    <string name="experimental" msgid="6198182315536726162">"Kokeellinen"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index f99447c..07a2fc3 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -437,4 +437,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"L\'application n\'est pas installée sur votre appareil"</string>
     <string name="clock_seconds" msgid="7689554147579179507">"Afficher les secondes sur l\'horloge"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Afficher les secondes sur l\'horloge dans la barre d\'état. Cela peut réduire l\'autonomie de la pile."</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"Réorganiser les paramètres rapides"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"Afficher la luminosité dans les paramètres rapides"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"Utiliser la pagination dans les paramètres rapides"</string>
+    <string name="experimental" msgid="6198182315536726162">"Fonctions expérimentales"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index aada1eb..0aa45ae 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -437,4 +437,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"L\'application n\'est pas installée sur votre appareil."</string>
     <string name="clock_seconds" msgid="7689554147579179507">"Afficher les secondes sur l\'horloge"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Afficher les secondes dans la barre d\'état. Cela risque de réduire l\'autonomie de la batterie."</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"Réorganiser la fenêtre de configuration rapide"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"Afficher la luminosité dans fenêtre de configuration rapide"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"Utiliser mise en page dans fenêtre de configuration rapide"</string>
+    <string name="experimental" msgid="6198182315536726162">"Paramètres expérimentaux"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-gl-rES/strings.xml b/packages/SystemUI/res/values-gl-rES/strings.xml
index 951809f..ec64f22 100644
--- a/packages/SystemUI/res/values-gl-rES/strings.xml
+++ b/packages/SystemUI/res/values-gl-rES/strings.xml
@@ -437,4 +437,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"A aplicación non está instalada no teu dispositivo"</string>
     <string name="clock_seconds" msgid="7689554147579179507">"Mostrar segundos do reloxo"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Mostra os segundos do reloxo na barra de estado. Pode influír na duración da batería."</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"Reorganizar Configuración rápida"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"Mostrar brillo en Configuración rápida"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"Utilizar paxinación en Configuración rápida"</string>
+    <string name="experimental" msgid="6198182315536726162">"Experimental"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-gu-rIN/strings.xml b/packages/SystemUI/res/values-gu-rIN/strings.xml
index 02e4e52..e873c95 100644
--- a/packages/SystemUI/res/values-gu-rIN/strings.xml
+++ b/packages/SystemUI/res/values-gu-rIN/strings.xml
@@ -435,4 +435,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"તમારા ઉપકરણ પર એપ્લિકેશન ઇન્સ્ટોલ થયેલ નથી"</string>
     <string name="clock_seconds" msgid="7689554147579179507">"ઘડિયાળ સેકન્ડ બતાવો"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"ઘડિયાળ સેકન્ડ સ્થિતિ બારમાં બતાવો. બૅટરીની આવરદા પર અસર કરી શકે છે."</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"ઝડપી સેટિંગ્સને ફરીથી ગોઠવો"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"ઝડપી સેટિંગ્સમાં તેજ બતાવો"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"ઝડપી સેટિંગ્સમાં પૃષ્ઠાંકનનો ઉપયોગ કરો"</string>
+    <string name="experimental" msgid="6198182315536726162">"પ્રાયોગિક"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 3ed090c..83ac46e 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -435,4 +435,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"ऐप्लिकेशन आपके डिवाइस पर इंस्टॉल नहीं है"</string>
     <string name="clock_seconds" msgid="7689554147579179507">"घड़ी के सेकंड दिखाएं"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"स्थिति बार में घड़ी के सेकंड दिखाएं. इससे बैटरी के जीवनकाल पर प्रभाव पड़ सकता है."</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"त्वरित सेटिंग को पुन: व्यवस्थित करें"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"त्वरित सेटिंग में स्क्रीन की रोशनी दिखाएं"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"त्वरित सेटिंग में पेजिंग का उपयोग करें"</string>
+    <string name="experimental" msgid="6198182315536726162">"प्रयोगात्मक"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 9698aba..b5d9931 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -436,4 +436,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"Aplikacija nije instalirana na vašem uređaju"</string>
     <string name="clock_seconds" msgid="7689554147579179507">"Prikaži sekunde na satu"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Prikazuju se sekunde na satu na traci statusa. Može utjecati na trajanje baterije."</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"Promijeni raspored Brzih postavki"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"Prikaži svjetlinu u Brzim postavkama"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"Upotrijebi redni broj stranice u Brzim postavkama"</string>
+    <string name="experimental" msgid="6198182315536726162">"Eksperimentalno"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 37cb0a8..79390a6 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -435,4 +435,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"Az alkalmazás nincs telepítve eszközén."</string>
     <string name="clock_seconds" msgid="7689554147579179507">"Másodpercek megjelenítése az órán"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Másodpercek megjelenítése az állapotsor óráján. Ez hatással lehet az akkumulátor üzemidejére."</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"Gyorsbeállítások átrendezése"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"Fényerő megjelenítése a gyorsbeállításokban"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"Oldalelrendezés használata a gyorsbeállításokban"</string>
+    <string name="experimental" msgid="6198182315536726162">"Kísérleti"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hy-rAM/strings.xml b/packages/SystemUI/res/values-hy-rAM/strings.xml
index e31cf49..9f48b26 100644
--- a/packages/SystemUI/res/values-hy-rAM/strings.xml
+++ b/packages/SystemUI/res/values-hy-rAM/strings.xml
@@ -435,4 +435,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"Հավելվածը տեղադրված չէ սարքի վրա"</string>
     <string name="clock_seconds" msgid="7689554147579179507">"Ցույց տալ ժամացույցի վայրկյանները"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Ցույց տալ ժամացույցի վայրկյանները կարգավիճակի տողում: Կարող է ազդել մարտկոցի աշխատանքի ժամանակի վրա:"</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"Վերադասավորել Արագ կարգավորումները"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"Ցույց տալ պայծառությունն Արագ կարգավորումներում"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"Օգտագործել էջերի դասավորությունը Արագ կարգավորումներում"</string>
+    <string name="experimental" msgid="6198182315536726162">"Փորձնական"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index ad8141b..60024115 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -435,4 +435,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"Aplikasi tidak dipasang di perangkat"</string>
     <string name="clock_seconds" msgid="7689554147579179507">"Tampilkan detik jam"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Tampilkan detik jam di bilah status. Dapat memengaruhi masa pakai baterai."</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"Atur Ulang Setelan Cepat"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"Tampilkan kecerahan di Setelan Cepat"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"Gunakan pembagian laman di Setelan Cepat"</string>
+    <string name="experimental" msgid="6198182315536726162">"Eksperimental"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-is-rIS/strings.xml b/packages/SystemUI/res/values-is-rIS/strings.xml
index 02caf17..e8e0530 100644
--- a/packages/SystemUI/res/values-is-rIS/strings.xml
+++ b/packages/SystemUI/res/values-is-rIS/strings.xml
@@ -435,4 +435,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"Forritið er ekki uppsett í tækinu."</string>
     <string name="clock_seconds" msgid="7689554147579179507">"Sýna sekúndur á klukku"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Sýna sekúndur á klukku í stöðustikunni. Getur haft áhrif á endingu rafhlöðu."</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"Endurraða flýtistillingum"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"Sýna birtustig í flýtistillingum"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"Nota síðuskoðun í flýtistillingum"</string>
+    <string name="experimental" msgid="6198182315536726162">"Tilraunastillingar"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index ab5d8beab..8ee5f07 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -437,4 +437,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"Applicazione non installata sul dispositivo"</string>
     <string name="clock_seconds" msgid="7689554147579179507">"Mostra i secondi nell\'orologio"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Mostra i secondi nell\'orologio nella barra di stato. Ciò potrebbe ridurre la durata della carica della batteria."</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"Riorganizza Impostazioni rapide"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"Mostra luminosità in Impostazioni rapide"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"Utilizza nuovo layout in Impostazioni rapide"</string>
+    <string name="experimental" msgid="6198182315536726162">"Sperimentali"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 9dad8aa..e38501d 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -437,4 +437,12 @@
     <string name="activity_not_found" msgid="348423244327799974">"האפליקציה אינה מותקנת במכשיר"</string>
     <string name="clock_seconds" msgid="7689554147579179507">"הצג שניות בשעון"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"הצג שניות בשעון בשורת הסטטוס. פעולה זו עשויה להשפיע על אורך חיי הסוללה."</string>
+    <!-- no translation found for qs_rearrange (8060918697551068765) -->
+    <skip />
+    <!-- no translation found for show_brightness (6613930842805942519) -->
+    <skip />
+    <!-- no translation found for qs_paging (7020133150248666132) -->
+    <skip />
+    <!-- no translation found for experimental (6198182315536726162) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 9cb2fc8..a73f4c1 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -437,4 +437,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"アプリが端末にインストールされていません"</string>
     <string name="clock_seconds" msgid="7689554147579179507">"時計の秒を表示"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"ステータスバーに時計の秒を表示します。電池使用量に影響する可能性があります。"</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"クイック設定を並べ替え"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"クイック設定に明るさ調整バーを表示する"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"クイック設定でページ設定を使用する"</string>
+    <string name="experimental" msgid="6198182315536726162">"試験運用版"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ka-rGE/strings.xml b/packages/SystemUI/res/values-ka-rGE/strings.xml
index a9728b2..f1035a8 100644
--- a/packages/SystemUI/res/values-ka-rGE/strings.xml
+++ b/packages/SystemUI/res/values-ka-rGE/strings.xml
@@ -435,4 +435,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"აპლიკაცია თქვენს მოწყობილობაზე დაყენებული არ არის"</string>
     <string name="clock_seconds" msgid="7689554147579179507">"საათის წამების ჩვენება"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"საათის წამების ჩვენება სტატუსის ზოლში. შეიძლება გავლენა იქონიოს ბატარეაზე."</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"სწრაფი პარამეტრების გადაწყობა"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"სიკაშკაშის ჩვენება სწრაფ პარამეტრებში"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"გამოიყენეთ გვერდების დანომვრა სწრაფ პარამეტრებში"</string>
+    <string name="experimental" msgid="6198182315536726162">"ექსპერიმენტული"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-kk-rKZ/strings.xml b/packages/SystemUI/res/values-kk-rKZ/strings.xml
index 1d61372..8b82e5f 100644
--- a/packages/SystemUI/res/values-kk-rKZ/strings.xml
+++ b/packages/SystemUI/res/values-kk-rKZ/strings.xml
@@ -435,4 +435,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"Қолданба құрылғыда орнатылмаған"</string>
     <string name="clock_seconds" msgid="7689554147579179507">"Сағат секундтарын көрсету"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Күйін көрсету жолағында сағат секундтарын көрсету. Батареяның қызмет көрсету мерзіміне әсер етуі мүмкін."</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"Жылдам параметрлерді қайта реттеу"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"Жылдам параметрлерде жарықтықты көрсету"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"Жылдам параметрлерде беттерді нөмірлеуді пайдалану"</string>
+    <string name="experimental" msgid="6198182315536726162">"Эксперименттік"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-km-rKH/strings.xml b/packages/SystemUI/res/values-km-rKH/strings.xml
index c233f83..b8db00f 100644
--- a/packages/SystemUI/res/values-km-rKH/strings.xml
+++ b/packages/SystemUI/res/values-km-rKH/strings.xml
@@ -435,4 +435,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"កម្មវិធីមិនបានដំឡើងនៅលើឧបករណ៍របស់អ្នកទេ"</string>
     <string name="clock_seconds" msgid="7689554147579179507">"បង្ហាញវិនាទី"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"បង្ហាញវិនាទីនៅលើរបារស្ថានភាពអាចនឹងប៉ះពាល់ដល់ថាមពលថ្ម។"</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"រៀបចំការកំណត់រហ័សឡើងវិញ"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"បង្ហាញកម្រិតពន្លឺនៅក្នុងការកំណត់រហ័ស"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"ប្រើការចុះទំព័រនៅក្នុងការកំណត់រហ័ស"</string>
+    <string name="experimental" msgid="6198182315536726162">"ពិសោធន៍"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-kn-rIN/strings.xml b/packages/SystemUI/res/values-kn-rIN/strings.xml
index d486e56..316c04f 100644
--- a/packages/SystemUI/res/values-kn-rIN/strings.xml
+++ b/packages/SystemUI/res/values-kn-rIN/strings.xml
@@ -435,4 +435,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"ನಿಮ್ಮ ಸಾಧನದಲ್ಲಿ ಅಪ್ಲಿಕೇಶನ್ ಅನ್ನು ಸ್ಥಾಪಿಸಲಾಗಿಲ್ಲ"</string>
     <string name="clock_seconds" msgid="7689554147579179507">"ಗಡಿಯಾರದ ಸೆಕೆಂಡುಗಳನ್ನು ತೋರಿಸು"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"ಸ್ಥಿತಿ ಪಟ್ಟಿಯಲ್ಲಿ ಗಡಿಯಾರ ಸೆಕೆಂಡುಗಳನ್ನು ತೋರಿಸು. ಇದಕ್ಕೆ ಬ್ಯಾಟರಿ ಬಾಳಿಕೆಯು ಪರಿಣಾಮಬೀರಬಹುದು."</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"ತ್ವರಿತ ಸೆಟ್ಟಿಂಗ್‌‌ಗಳನ್ನು ಮರುಹೊಂದಿಸಿ"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"ತ್ವರಿತ ಸೆಟ್ಟಿಂಗ್‌‌ಗಳಲ್ಲಿ ಪ್ರಖರತೆಯನ್ನು ತೋರಿಸಿ"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"ತ್ವರಿತ ಸೆಟ್ಟಿಂಗ್‌‌ಗಳಲ್ಲಿ ಪುಟಗಳನ್ನು ಬಳಸಿ"</string>
+    <string name="experimental" msgid="6198182315536726162">"ಪ್ರಾಯೋಗಿಕ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 3505754..d7f1543 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -435,4 +435,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"기기에 애플리케이션이 설치되어 있지 않습니다."</string>
     <string name="clock_seconds" msgid="7689554147579179507">"시계 초 단위 표시"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"상태 표시줄에 시계 초 단위를 표시합니다. 배터리 수명에 영향을 줄 수도 있습니다."</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"빠른 설정 재정렬"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"빠른 설정에서 밝기 표시"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"빠른 설정에서 페이지 레이아웃 사용"</string>
+    <string name="experimental" msgid="6198182315536726162">"베타"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ky-rKG/strings.xml b/packages/SystemUI/res/values-ky-rKG/strings.xml
index 968a65a..efe699b 100644
--- a/packages/SystemUI/res/values-ky-rKG/strings.xml
+++ b/packages/SystemUI/res/values-ky-rKG/strings.xml
@@ -435,4 +435,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"Колдонмо сиздин түзмөгүңүздө орнотулган эмес"</string>
     <string name="clock_seconds" msgid="7689554147579179507">"Сааттын секунддары көрсөтүлсүн"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Абал тилкесинен сааттын секунддары көрсөтүлсүн. Батареянын кубаты көбүрөөк сарпталышы мүмкүн."</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"Ыкчам жөндөөлөрдү кайра коюу"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"Ыкчам жөндөөлөрдөн жарыктыгын көрсөтүү"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"Ыкчам жөндөөлөрдөн баракты номерлөөнү колдонуу"</string>
+    <string name="experimental" msgid="6198182315536726162">"Сынамык"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-lo-rLA/strings.xml b/packages/SystemUI/res/values-lo-rLA/strings.xml
index f34c70e..50b4522 100644
--- a/packages/SystemUI/res/values-lo-rLA/strings.xml
+++ b/packages/SystemUI/res/values-lo-rLA/strings.xml
@@ -435,4 +435,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"ແອັບ​ພ​ລິ​ເຄ​ຊັນ​ບໍ່​ຖືກ​ຕິດ​ຕັ້ງ​ຢູ່​ໃນ​ອຸ​ປະ​ກອນ​ຂອງ​ທ່ານ"</string>
     <string name="clock_seconds" msgid="7689554147579179507">"ສະ​ແດງວິ​ນາ​ທີ​ໂມງ"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"ສະ​ແດງວິ​ນາ​ທີ​ໂມງ​ຢູ່​ໃນ​ແຖບ​ສະ​ຖາ​ນະ. ອາດ​ຈະ​ມີ​ຜົນ​ກະ​ທົບ​ຕໍ່​ອາ​ຍຸ​ແບັດ​ເຕີ​ຣີ."</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"ຈັດ​ວາງ​ການ​ຕັ້ງ​ຄ່າ​ດ່ວນ​ຄືນ​ໃໝ່"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"ສະ​ແດງ​ຄວາມ​ແຈ້ງ​ຢູ່​ໃນ​ການ​ຕັ້ງ​ຄ່າ​ດ່ວນ"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"ໃຊ້​ການ​ໃສ່​ໜ້າ​ຢູ່​ໃນ​ການ​ຕັ້ງ​ຄ່າ​ດ່ວນ"</string>
+    <string name="experimental" msgid="6198182315536726162">"ຍັງຢູ່ໃນການທົດລອງ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index cf70d6b..9082778 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -437,4 +437,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"Programa neįdiegta įrenginyje"</string>
     <string name="clock_seconds" msgid="7689554147579179507">"Rodyti laikrodžio sekundes"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Rodyti laikrodžio sekundes būsenos juostoje. Tai gali paveikti akumuliatoriaus naudojimo laiką."</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"Pertvarkyti sparčiuosius nustatymus"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"Rodyti skaistį sparčiuosiuose nustatymuose"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"Naudoti puslapių kaitą sparčiuosiuose nustatymuose"</string>
+    <string name="experimental" msgid="6198182315536726162">"Eksperimentinė versija"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 5e2db80..5fb4bb0 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -436,4 +436,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"Lietojumprogramma nav instalēta jūsu ierīcē."</string>
     <string name="clock_seconds" msgid="7689554147579179507">"Rādīt pulksteņa sekundes"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Statusa joslā rādīt pulksteņa sekundes. Var ietekmēt akumulatora darbības laiku."</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"Pārkārtot ātros iestatījumus"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"Rādīt spilgtumu ātrajos iestatījumos"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"Izmantot lapošanu ātrajos iestatījumos"</string>
+    <string name="experimental" msgid="6198182315536726162">"Eksperimentāli"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-mk-rMK/strings.xml b/packages/SystemUI/res/values-mk-rMK/strings.xml
index fe781b6..8571b3f 100644
--- a/packages/SystemUI/res/values-mk-rMK/strings.xml
+++ b/packages/SystemUI/res/values-mk-rMK/strings.xml
@@ -437,4 +437,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"Апликацијата не е инсталирана на уредот"</string>
     <string name="clock_seconds" msgid="7689554147579179507">"Прикажи ги секундите на часовникот"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Прикажи ги секундите на часовникот на статусната лента. Може да влијае на траењето на батеријата."</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"Преуредете ги Брзи поставки"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"Прикажете ја осветленоста во Брзи поставки"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"Користете прелистување страници во Брзи поставки"</string>
+    <string name="experimental" msgid="6198182315536726162">"Експериментално"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ml-rIN/strings.xml b/packages/SystemUI/res/values-ml-rIN/strings.xml
index 6e6fc55..4b11962 100644
--- a/packages/SystemUI/res/values-ml-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ml-rIN/strings.xml
@@ -435,4 +435,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"നിങ്ങളുടെ ഉപകരണത്തിൽ അപ്ലിക്കേഷൻ ഇൻസ്റ്റാൾ ചെയ്തിട്ടില്ല"</string>
     <string name="clock_seconds" msgid="7689554147579179507">"ക്ലോക്ക് സെക്കൻഡ് കാണിക്കുക"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"സ്റ്റാറ്റസ് ബാറിൽ ക്ലോക്ക് സെക്കൻഡ് കാണിക്കുന്നത് ബാറ്ററിയുടെ ലൈഫിനെ ബാധിക്കാം."</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"ദ്രുത ക്രമീകരണം പുനഃസജ്ജീകരിക്കുക"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"ദ്രുത ക്രമീകരണത്തിൽ തെളിച്ചം കാണിക്കുക"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"ദ്രുത്ര ക്രമീകരണത്തിൽ പേജിംഗ് ഉപയോഗിക്കുക"</string>
+    <string name="experimental" msgid="6198182315536726162">"പരീക്ഷണാത്മകം!"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-mn-rMN/strings.xml b/packages/SystemUI/res/values-mn-rMN/strings.xml
index 65250bb..d1dbd6d 100644
--- a/packages/SystemUI/res/values-mn-rMN/strings.xml
+++ b/packages/SystemUI/res/values-mn-rMN/strings.xml
@@ -433,4 +433,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"Апп-ыг таны төхөөрөмжид суулгаагүй байна"</string>
     <string name="clock_seconds" msgid="7689554147579179507">"Цагийн секундыг харуулах"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Статус талбарт цагийн секундыг харуулах. Энэ нь тэжээлийн цэнэгт нөлөөлж болно."</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"Түргэн тохиргоог дахин засварлах"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"Түргэн тохиргоонд гэрэлтүүлэг харах"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"Хуудаслалтыг түргэн тохиргоонд ашиглаарай"</string>
+    <string name="experimental" msgid="6198182315536726162">"Туршилтын"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-mr-rIN/strings.xml b/packages/SystemUI/res/values-mr-rIN/strings.xml
index 0f71b4b..fe50f90 100644
--- a/packages/SystemUI/res/values-mr-rIN/strings.xml
+++ b/packages/SystemUI/res/values-mr-rIN/strings.xml
@@ -435,4 +435,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"अनुप्रयोग आपल्या डिव्हाइसवर स्थापित केलेला नाही"</string>
     <string name="clock_seconds" msgid="7689554147579179507">"घड्‍याळ सेकंद दर्शवा"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"स्टेटस बारमध्‍ये घड्‍याळ सेकंद दर्शवा. कदाचित बॅटरी आयुष्‍य प्रभावित होऊ शकते."</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"दृत सेटिंग्जची पुनर्रचना करा"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"दृत सेटिंग्जमध्‍ये चमक दर्शवा"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"द्रुत सेटिंग्जमध्ये लिखाण वापरा"</string>
+    <string name="experimental" msgid="6198182315536726162">"प्रायोगिक"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ms-rMY/strings.xml b/packages/SystemUI/res/values-ms-rMY/strings.xml
index 596275c..01f7edf 100644
--- a/packages/SystemUI/res/values-ms-rMY/strings.xml
+++ b/packages/SystemUI/res/values-ms-rMY/strings.xml
@@ -435,4 +435,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"Aplikasi tidak dipasang pada peranti anda"</string>
     <string name="clock_seconds" msgid="7689554147579179507">"Tunjukkan saat jam"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Tunjukkan saat jam dalam bar status. Mungkin menjejaskan hayat bateri."</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"Susun Semula Tetapan Pantas"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"Tunjukkan kecerahan dalam Tetapan Pantas"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"Gunakan penghalaman dalam Tetapan Pantas"</string>
+    <string name="experimental" msgid="6198182315536726162">"Percubaan"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-my-rMM/strings.xml b/packages/SystemUI/res/values-my-rMM/strings.xml
index 3147d0c..d0eaccf 100644
--- a/packages/SystemUI/res/values-my-rMM/strings.xml
+++ b/packages/SystemUI/res/values-my-rMM/strings.xml
@@ -435,4 +435,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"အပလီကေးရှင်းကို သင်၏ ကိရိယာထဲသို့ တပ်ဆင်မပေးရသေးပါ။"</string>
     <string name="clock_seconds" msgid="7689554147579179507">"နာရီ စက္ကန့်များကို ပြရန်"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"အခြေအနေပြနေရာမှာ နာရီ စက္ကန့်များကို ပြပါ။ ဘက်ထရီ သက်တမ်းကို အကျိုးသက်ရောက်နိုင်တယ်။"</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"အမြန် ဆက်တင်များကို ပြန်စီစဉ်ရန်"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"အမြန် ဆက်တင်များထဲက တောက်ပမှုကို ပြရန်"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"အမြန် ဆက်တင်များထဲတွင် စာမျက်နှာ ပုံစံချမှုကို အသုံးပြုပါ"</string>
+    <string name="experimental" msgid="6198182315536726162">"စမ်းသပ်ရေး"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index f1bfbe1..e582039 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -435,4 +435,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"Appen er ikke installert på enheten din"</string>
     <string name="clock_seconds" msgid="7689554147579179507">"Vis sekunder på klokken"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Vis sekunder i statusfeltet på klokken. Det kan påvirke batteritiden."</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"Omorganiser hurtiginnstillingene"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"Vis lysstyrke i hurtiginnstillingene"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"Bruk sidetall i hurtiginnstillingene"</string>
+    <string name="experimental" msgid="6198182315536726162">"På forsøksstadiet"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ne-rNP/strings.xml b/packages/SystemUI/res/values-ne-rNP/strings.xml
index 461a15f..c3dc703 100644
--- a/packages/SystemUI/res/values-ne-rNP/strings.xml
+++ b/packages/SystemUI/res/values-ne-rNP/strings.xml
@@ -435,4 +435,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"तपाईँको यन्त्रमा अनुप्रयोग स्थापना भएको छैन"</string>
     <string name="clock_seconds" msgid="7689554147579179507">"घडीमा सेकेन्ड देखाउनुहोस्"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"वस्तुस्थिति पट्टीको घडीमा सेकेन्ड देखाउनुहोस्। ब्याट्री आयु प्रभावित हुन सक्छ।"</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"द्रुत सेटिङहरू पुनः व्यवस्थित गर्नुहोस्"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"द्रुत सेटिङहरूमा उज्यालो देखाउनुहोस्"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"द्रुत सेटिङहरूमा पेजिंग प्रयोग गर्नुहोस्"</string>
+    <string name="experimental" msgid="6198182315536726162">"प्रयोगात्मक"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index b74f91d..13f02d5 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -435,4 +435,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"Deze app is niet geïnstalleerd op uw apparaat"</string>
     <string name="clock_seconds" msgid="7689554147579179507">"Klokseconden weergeven"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Klokseconden op de statusbalk weergeven. Kan van invloed zijn op de accuduur."</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"Snelle instellingen opnieuw indelen"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"Helderheid weergeven in Snelle instellingen"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"Paginering gebruiken in Snelle instellingen"</string>
+    <string name="experimental" msgid="6198182315536726162">"Experimenteel"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pa-rIN/strings.xml b/packages/SystemUI/res/values-pa-rIN/strings.xml
index 06746cc..ef3d2f3 100644
--- a/packages/SystemUI/res/values-pa-rIN/strings.xml
+++ b/packages/SystemUI/res/values-pa-rIN/strings.xml
@@ -435,4 +435,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"ਐਪਲੀਕੇਸ਼ਨ ਤੁਹਾਡੀ ਡਿਵਾਈਸ ਤੇ ਇੰਸਟੌਲ ਨਹੀਂ ਕੀਤੀ ਗਈ ਹੈ"</string>
     <string name="clock_seconds" msgid="7689554147579179507">"ਘੜੀ ਸਕਿੰਟ ਦਿਖਾਓ"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"ਸਥਿਤੀ ਬਾਰ ਵਿੱਚ ਘੜੀ ਸਕਿੰਟ ਦਿਖਾਓ। ਬੈਟਰੀ ਸਮਰੱਥਾ ਤੇ ਅਸਰ ਪੈ ਸਕਦਾ ਹੈ।"</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"ਤਤਕਾਲ ਸੈਟਿੰਗਾਂ ਨੂੰ ਦੁਬਾਰਾ ਕ੍ਰਮ ਦਿਓ"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"ਤਤਕਾਲ ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਚਮਕ ਦਿਖਾਓ"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"ਤਤਕਾਲ ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਪੇਜਿੰਗ ਵਰਤੋ"</string>
+    <string name="experimental" msgid="6198182315536726162">"ਪ੍ਰਯੋਗਾਤਮਿਕ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 66100c1..8c2c5c4 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -437,4 +437,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"Aplikacja nie jest zainstalowana na urządzeniu"</string>
     <string name="clock_seconds" msgid="7689554147579179507">"Pokaż sekundy na zegarku"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Pokaż sekundy na zegarku na pasku stanu. Może mieć wpływ na czas pracy baterii."</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"Uporządkuj Szybkie ustawienia"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"Pokaż jasność w Szybkich ustawieniach"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"Użyj stronicowania w Szybkich ustawieniach"</string>
+    <string name="experimental" msgid="6198182315536726162">"Eksperymentalne"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 53cea01..3803b81 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -437,4 +437,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"O app não está instalado no seu dispositivo"</string>
     <string name="clock_seconds" msgid="7689554147579179507">"Mostrar segundos do relógio"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Mostrar segundos do relógio na barra de status. Pode afetar a duração da bateria."</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"Reorganizar \"Configurações rápidas\""</string>
+    <string name="show_brightness" msgid="6613930842805942519">"Mostrar brilho nas \"Configurações rápidas\""</string>
+    <string name="qs_paging" msgid="7020133150248666132">"Usar paginação nas \"Configurações rápidas\""</string>
+    <string name="experimental" msgid="6198182315536726162">"Experimentais"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 5006413..be42e8a 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -435,4 +435,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"A aplicação não está instalada no dispositivo"</string>
     <string name="clock_seconds" msgid="7689554147579179507">"Mostrar segundos do relógio"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Mostrar segundos do relógio na barra de estado. Pode afetar a autonomia da bateria."</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"Reorganizar Definições rápidas"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"Mostrar luminosidade nas Definições rápidas"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"Utilizar paginação nas Definições rápidas"</string>
+    <string name="experimental" msgid="6198182315536726162">"Experimental"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 53cea01..3803b81 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -437,4 +437,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"O app não está instalado no seu dispositivo"</string>
     <string name="clock_seconds" msgid="7689554147579179507">"Mostrar segundos do relógio"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Mostrar segundos do relógio na barra de status. Pode afetar a duração da bateria."</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"Reorganizar \"Configurações rápidas\""</string>
+    <string name="show_brightness" msgid="6613930842805942519">"Mostrar brilho nas \"Configurações rápidas\""</string>
+    <string name="qs_paging" msgid="7020133150248666132">"Usar paginação nas \"Configurações rápidas\""</string>
+    <string name="experimental" msgid="6198182315536726162">"Experimentais"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index d97e16b..bb8f2c3 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -436,4 +436,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"Aplicația nu este instalată pe dispozitiv"</string>
     <string name="clock_seconds" msgid="7689554147579179507">"Afișează secundele pe ceas"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Afișează secundele pe ceas în bara de stare. Poate afecta autonomia bateriei."</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"Rearanjați Setările rapide"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"Afișați luminozitatea în Setările rapide"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"Folosiți paginarea în Setările rapide"</string>
+    <string name="experimental" msgid="6198182315536726162">"Experimentale"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index d67ad38..9609f40 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -269,7 +269,7 @@
     <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_detail_empty_text" msgid="269990350383909226">"Не удалось найти доступные сети Wi-Fi"</string>
-    <string name="quick_settings_cast_title" msgid="7709016546426454729">"Wi-Fi-монитор"</string>
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"Трансляция"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"Передача изображения"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"Безымянное устройство"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"Готово к передаче"</string>
@@ -439,4 +439,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"Приложение не установлено на вашем устройстве"</string>
     <string name="clock_seconds" msgid="7689554147579179507">"Показывать секунды"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Показывать в строке состояния время с точностью до секунды (заряд батареи может расходоваться быстрее)."</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"Изменить порядок Быстрых настроек"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"Добавить яркость в Быстрые настройки"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"Разбить Быстрые настройки на страницы"</string>
+    <string name="experimental" msgid="6198182315536726162">"Экспериментальная функция"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-si-rLK/strings.xml b/packages/SystemUI/res/values-si-rLK/strings.xml
index 06cb626..9e78834 100644
--- a/packages/SystemUI/res/values-si-rLK/strings.xml
+++ b/packages/SystemUI/res/values-si-rLK/strings.xml
@@ -435,4 +435,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"යෙදුම ඔබේ උපාංගය මත ස්ථාපනය කර නැත"</string>
     <string name="clock_seconds" msgid="7689554147579179507">"ඔරලෝසු තත්පර පෙන්වන්න"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"තත්ත්ව තීරුවෙහි ඔරලෝසු තත්පර පෙන්වන්න. බැටරි ආයු කාලයට බලපෑමට හැකිය."</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"ඉක්මන් සැකසීම් යළි පිළිවෙළට සකසන්න"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"ඉක්මන් සැකසීම්වල දීප්තිය පෙන්වන්න"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"ඉක්මන් සැකසීම්වල පිටු පිරිසැලසුම් භාවිත කරන්න"</string>
+    <string name="experimental" msgid="6198182315536726162">"පරීක්ෂණාත්මක"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 037074b..e3f0fb3 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -439,4 +439,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"Aplikácia nie je nainštalovaná na zariadení"</string>
     <string name="clock_seconds" msgid="7689554147579179507">"Zobraziť sekundy"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Zobrazí sekundy v stavovom riadku. Môže to ovplyvňovať výdrž batérie."</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"Zmeniť usporiadanie Rýchlych nastavení"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"Zobraziť jas v Rýchlych nastaveniach"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"Použite stránkovanie v Rýchlych nastaveniach"</string>
+    <string name="experimental" msgid="6198182315536726162">"Experimentálne"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 31fe5d8..4dffcfa 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -437,4 +437,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"Aplikacija ni nameščena v napravi"</string>
     <string name="clock_seconds" msgid="7689554147579179507">"Prikaz sekund pri uri"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Prikaže sekunde pri uri v vrstici stanja. To lahko vpliva na čas delovanja pri akumulatorskem napajanju."</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"Preuredi hitre nastavitve"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"Prikaz svetlosti v hitrih nastavitvah"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"Uporaba postavitve strani v hitrih nastavitvah"</string>
+    <string name="experimental" msgid="6198182315536726162">"Poskusno"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sq-rAL/strings.xml b/packages/SystemUI/res/values-sq-rAL/strings.xml
index ffb8bea..20c3426 100644
--- a/packages/SystemUI/res/values-sq-rAL/strings.xml
+++ b/packages/SystemUI/res/values-sq-rAL/strings.xml
@@ -435,4 +435,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"Aplikacioni nuk është instaluar në pajisjen tënde."</string>
     <string name="clock_seconds" msgid="7689554147579179507">"Trego sekondat e orës"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Trego sekondat e orës në shiritin e statusit. Mund të ndikojë te jeta e baterisë."</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"Risistemo Cilësimet e shpejta"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"Shfaq ndriçimin te Cilësimet e shpejta"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"Përdor faqosjen te Cilësimet e shpejta"</string>
+    <string name="experimental" msgid="6198182315536726162">"Eksperimentale"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index bae0284..1dcde3a 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -436,4 +436,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"Апликација није инсталирана на уређају"</string>
     <string name="clock_seconds" msgid="7689554147579179507">"Приказуј секунде на сату"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Секунде на сату се приказују на статусној траци. То може да утиче на трајање батерије."</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"Преуреди Брза подешавања"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"Прикажи осветљеност у Брзим подешавањима"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"Користи листање страница у Брзим подешавањима"</string>
+    <string name="experimental" msgid="6198182315536726162">"Експериментално"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 6588f10..0abeb1e 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -435,4 +435,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"Appen är inte installerad på enheten"</string>
     <string name="clock_seconds" msgid="7689554147579179507">"Visa klocksekunder"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Visa klocksekunder i statusfältet. Detta kan påverka batteritiden."</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"Ordna snabbinställningarna"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"Visa ljusstyrka i snabbinställningarna"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"Använd sidindelning i snabbinställningarna"</string>
+    <string name="experimental" msgid="6198182315536726162">"Experimentella"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 623f12c..d000004 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -435,4 +435,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"Programu haijasakinishwa kwenye kifaa chako"</string>
     <string name="clock_seconds" msgid="7689554147579179507">"Onyesha sekunde za saa"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Onyesha sekunde za saa katika sehemu ya arifa. Inaweza kuathiri muda wa matumizi ya betri."</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"Panga Upya Mipangilio ya Haraka"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"Onyesha unga\'avu katika Mipangilio ya Haraka"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"Tumia nambari za ukurasa katika Mipangilio ya Haraka"</string>
+    <string name="experimental" msgid="6198182315536726162">"Ya majaribio"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ta-rIN/strings.xml b/packages/SystemUI/res/values-ta-rIN/strings.xml
index c6cb337..7b1ded3 100644
--- a/packages/SystemUI/res/values-ta-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ta-rIN/strings.xml
@@ -435,4 +435,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"சாதனத்தில் பயன்பாடு நிறுவப்படவில்லை"</string>
     <string name="clock_seconds" msgid="7689554147579179507">"கடிகார வினாடிகளைக் காட்டு"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"நிலைப் பட்டியில் கடிகார வினாடிகளைக் காட்டும். பேட்டரியின் ஆயுளைக் குறைக்கலாம்."</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"விரைவு அமைப்புகளை மறுவரிசைப்படுத்து"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"விரைவு அமைப்புகளில் ஒளிர்வுப் பட்டியைக் காட்டு"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"விரைவு அமைப்புகளில் புதிய பக்கத் தளவமைப்பைப் பயன்படுத்து"</string>
+    <string name="experimental" msgid="6198182315536726162">"சோதனை முயற்சி"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-te-rIN/strings.xml b/packages/SystemUI/res/values-te-rIN/strings.xml
index c0717c1..06762bd 100644
--- a/packages/SystemUI/res/values-te-rIN/strings.xml
+++ b/packages/SystemUI/res/values-te-rIN/strings.xml
@@ -435,4 +435,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"అనువర్తనం మీ పరికరంలో ఇన్‌స్టాల్ చేయలేదు"</string>
     <string name="clock_seconds" msgid="7689554147579179507">"గడియారం సెకన్లు చూపు"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"స్థితి పట్టీలో గడియారం సెకన్లు చూపుతుంది. బ్యాటరీ శక్తి ప్రభావితం చేయవచ్చు."</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"శీఘ్ర సెట్టింగ్‌ల ఏర్పాటు క్రమం మార్చు"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"శీఘ్ర సెట్టింగ్‌ల్లో ప్రకాశం చూపు"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"శీఘ్ర సెట్టింగ్‌ల్లో పేజింగ్‌ను ఉపయోగించు"</string>
+    <string name="experimental" msgid="6198182315536726162">"ప్రయోగాత్మకం"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index e16fdd2..52c7af7 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -435,4 +435,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"ยังไม่ได้ติดตั้งแอปพลิเคชันบนอุปกรณ์ของคุณ"</string>
     <string name="clock_seconds" msgid="7689554147579179507">"แสดงวินาทีของนาฬิกา"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"แสดงวินาทีของนาฬิกาในแถบสถานะ อาจส่งผลต่ออายุแบตเตอรี"</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"จัดเรียงการตั้งค่าด่วนใหม่"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"แสดงความสว่างในการตั้งค่าด่วน"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"ใช้การแบ่งหน้าในการตั้งค่าด่วน"</string>
+    <string name="experimental" msgid="6198182315536726162">"ทดสอบ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index d970084..66056d1 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -435,4 +435,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"Hindi naka-install ang application sa iyong device"</string>
     <string name="clock_seconds" msgid="7689554147579179507">"Ipakita ang mga segundo ng orasan"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Ipakita ang mga segundo ng orasan sa status bar. Maaaring makaapekto sa tagal ng baterya."</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"Ayusing Muli ang Mga Mabilisang Setting"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"Ipakita ang liwanag sa Mga Mabilisang Setting"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"Gamitin ang paging sa Mga Mabilisang Setting"</string>
+    <string name="experimental" msgid="6198182315536726162">"Pang-eksperimento"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index b22b4fb..fdad0d5 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -435,4 +435,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"Uygulama, cihazınızda yüklü değil"</string>
     <string name="clock_seconds" msgid="7689554147579179507">"Saatin saniyelerini göster"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Durum çubuğunda saatin saniyelerini gösterir. Pil ömrünü etkileyebilir."</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"Hızlı Ayarlar\'ı Yeniden Düzenle"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"Hızlı Ayarlar\'da parlaklığı göster"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"Hızlı Ayarlar\'da sayfa ayırmayı kullan"</string>
+    <string name="experimental" msgid="6198182315536726162">"Deneysel"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 898611d..9dde801 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -437,4 +437,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"Додаток не встановлено на вашому пристрої"</string>
     <string name="clock_seconds" msgid="7689554147579179507">"Показувати секунди на годиннику"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Показувати секунди на годиннику в рядку стану. Акумулятор може розряджатися швидше."</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"Упорядкувати швидкі налаштування"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"Показувати панель яскравості у швидких налаштуваннях"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"Показувати швидкі налаштування у вигляді сторінок"</string>
+    <string name="experimental" msgid="6198182315536726162">"Експериментальні налаштування"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ur-rPK/strings.xml b/packages/SystemUI/res/values-ur-rPK/strings.xml
index d5683e1..a4ef16a 100644
--- a/packages/SystemUI/res/values-ur-rPK/strings.xml
+++ b/packages/SystemUI/res/values-ur-rPK/strings.xml
@@ -435,4 +435,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"ایپلیکیشن آپ کے آلہ پر انسٹال نہیں ہے"</string>
     <string name="clock_seconds" msgid="7689554147579179507">"گھڑی کے سیکنڈز دکھائیں"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"گھڑی کے سیکنڈز اسٹیٹس بار میں دکھائیں۔ اس کا بیٹری کی زندگی پر اثر پڑ سکتا ہے۔"</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"فوری ترتیبات کو دوبارہ ترتیب دیں"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"فوری ترتیبات میں چمکیلا پن دکھائیں"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"فوری ترتیبات میں پیجنگ استعمال کریں"</string>
+    <string name="experimental" msgid="6198182315536726162">"تجرباتی"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-uz-rUZ/strings.xml b/packages/SystemUI/res/values-uz-rUZ/strings.xml
index e31af6b..118c4b8 100644
--- a/packages/SystemUI/res/values-uz-rUZ/strings.xml
+++ b/packages/SystemUI/res/values-uz-rUZ/strings.xml
@@ -435,4 +435,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"Ilova qurilmangizga o‘rnatilmagan"</string>
     <string name="clock_seconds" msgid="7689554147579179507">"Soat soniyalari ko‘rsatilsin"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Holat panelida soat soniyalari ko‘rsatilsin. Bu batareya resursiga ta’sir qilishi mumkin."</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"Tezkor sozlamalarni qayta tartiblash"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"Tezkor sozlamalarda yorqinlikni ko‘rsatish"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"Tezkor sozlamalarda peyjingdan foydalanish"</string>
+    <string name="experimental" msgid="6198182315536726162">"Tajribaviy"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 030bbbe..460d57a 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -435,4 +435,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"Ứng dụng chưa được cài đặt trên thiết bị của bạn"</string>
     <string name="clock_seconds" msgid="7689554147579179507">"Hiển thị giây đồng hồ"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Hiển thị giây đồng hồ trong thanh trạng thái. Có thể ảnh hưởng đến thời lượng pin."</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"Sắp xếp lại Cài đặt nhanh"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"Hiển thị độ sáng trong Cài đặt nhanh"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"Sử dụng đánh số trang trong Cài đặt nhanh"</string>
+    <string name="experimental" msgid="6198182315536726162">"Thử nghiệm"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index b046415..05644e7 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -437,4 +437,12 @@
     <string name="activity_not_found" msgid="348423244327799974">"您的设备中未安装此应用"</string>
     <string name="clock_seconds" msgid="7689554147579179507">"显示时钟的秒数"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"在状态栏中显示时钟的秒数。这可能会影响电池的续航时间。"</string>
+    <!-- no translation found for qs_rearrange (8060918697551068765) -->
+    <skip />
+    <!-- no translation found for show_brightness (6613930842805942519) -->
+    <skip />
+    <!-- no translation found for qs_paging (7020133150248666132) -->
+    <skip />
+    <!-- no translation found for experimental (6198182315536726162) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index d568dba..f7cac90 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -437,4 +437,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"尚未在裝置安裝應用程式"</string>
     <string name="clock_seconds" msgid="7689554147579179507">"顯示時鐘秒數"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"在狀態列中顯示時鐘秒數,但可能會影響電池壽命。"</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"重新排列快速設定"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"在快速設定顯示亮度"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"在快速設定使用分頁"</string>
+    <string name="experimental" msgid="6198182315536726162">"實驗版"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 702ad53..369172f3 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -437,4 +437,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"您的裝置未安裝這個應用程式"</string>
     <string name="clock_seconds" msgid="7689554147579179507">"顯示時鐘秒數"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"在狀態列中顯示時鐘秒數。這可能會影響電池續航力。"</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"重新排列快速設定"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"在快速設定中顯示亮度"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"在快速設定中使用分頁功能"</string>
+    <string name="experimental" msgid="6198182315536726162">"實驗性"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 8774036..2a14a9f 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -435,4 +435,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"Uhlelo lokusebenza alufakiwe kudivayisi yakho"</string>
     <string name="clock_seconds" msgid="7689554147579179507">"Bonisa amasekhondi wewashi"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Bonisa amasekhondi wewashi kubha yesimo. Ingathinta impilo yebhethri."</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"Hlela kabusha izilungiselelo ezisheshayo"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"Bonisa ukukhanya kuzilungiselelo ezisheshayo"</string>
+    <string name="qs_paging" msgid="7020133150248666132">"Sebenzisa i-paging kuzilungiselelo ezisheshayo"</string>
+    <string name="experimental" msgid="6198182315536726162">"Okokulinga"</string>
 </resources>
diff --git a/services/core/java/com/android/server/SystemServiceManager.java b/services/core/java/com/android/server/SystemServiceManager.java
index fda6479..92e6814 100644
--- a/services/core/java/com/android/server/SystemServiceManager.java
+++ b/services/core/java/com/android/server/SystemServiceManager.java
@@ -17,6 +17,7 @@
 package com.android.server;
 
 import android.content.Context;
+import android.os.Trace;
 import android.util.Slog;
 
 import java.lang.reflect.Constructor;
@@ -75,43 +76,48 @@
      */
     @SuppressWarnings("unchecked")
     public <T extends SystemService> T startService(Class<T> serviceClass) {
-        final String name = serviceClass.getName();
-        Slog.i(TAG, "Starting " + name);
-
-        // Create the service.
-        if (!SystemService.class.isAssignableFrom(serviceClass)) {
-            throw new RuntimeException("Failed to create " + name
-                    + ": service must extend " + SystemService.class.getName());
-        }
-        final T service;
         try {
-            Constructor<T> constructor = serviceClass.getConstructor(Context.class);
-            service = constructor.newInstance(mContext);
-        } catch (InstantiationException ex) {
-            throw new RuntimeException("Failed to create service " + name
-                    + ": service could not be instantiated", ex);
-        } catch (IllegalAccessException ex) {
-            throw new RuntimeException("Failed to create service " + name
-                    + ": service must have a public constructor with a Context argument", ex);
-        } catch (NoSuchMethodException ex) {
-            throw new RuntimeException("Failed to create service " + name
-                    + ": service must have a public constructor with a Context argument", ex);
-        } catch (InvocationTargetException ex) {
-            throw new RuntimeException("Failed to create service " + name
-                    + ": service constructor threw an exception", ex);
-        }
+            final String name = serviceClass.getName();
+            Slog.i(TAG, "Starting " + name);
+            Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "StartService " + name);
 
-        // Register it.
-        mServices.add(service);
+            // Create the service.
+            if (!SystemService.class.isAssignableFrom(serviceClass)) {
+                throw new RuntimeException("Failed to create " + name
+                        + ": service must extend " + SystemService.class.getName());
+            }
+            final T service;
+            try {
+                Constructor<T> constructor = serviceClass.getConstructor(Context.class);
+                service = constructor.newInstance(mContext);
+            } catch (InstantiationException ex) {
+                throw new RuntimeException("Failed to create service " + name
+                        + ": service could not be instantiated", ex);
+            } catch (IllegalAccessException ex) {
+                throw new RuntimeException("Failed to create service " + name
+                        + ": service must have a public constructor with a Context argument", ex);
+            } catch (NoSuchMethodException ex) {
+                throw new RuntimeException("Failed to create service " + name
+                        + ": service must have a public constructor with a Context argument", ex);
+            } catch (InvocationTargetException ex) {
+                throw new RuntimeException("Failed to create service " + name
+                        + ": service constructor threw an exception", ex);
+            }
 
-        // Start it.
-        try {
-            service.onStart();
-        } catch (RuntimeException ex) {
-            throw new RuntimeException("Failed to start service " + name
-                    + ": onStart threw an exception", ex);
+            // Register it.
+            mServices.add(service);
+
+            // Start it.
+            try {
+                service.onStart();
+            } catch (RuntimeException ex) {
+                throw new RuntimeException("Failed to start service " + name
+                        + ": onStart threw an exception", ex);
+            }
+            return service;
+        } finally {
+            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
         }
-        return service;
     }
 
     /**
@@ -127,18 +133,22 @@
         mCurrentPhase = phase;
 
         Slog.i(TAG, "Starting phase " + mCurrentPhase);
-
-        final int serviceLen = mServices.size();
-        for (int i = 0; i < serviceLen; i++) {
-            final SystemService service = mServices.get(i);
-            try {
-                service.onBootPhase(mCurrentPhase);
-            } catch (Exception ex) {
-                throw new RuntimeException("Failed to boot service "
-                        + service.getClass().getName()
-                        + ": onBootPhase threw an exception during phase "
-                        + mCurrentPhase, ex);
+        try {
+            Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "OnBootPhase " + phase);
+            final int serviceLen = mServices.size();
+            for (int i = 0; i < serviceLen; i++) {
+                final SystemService service = mServices.get(i);
+                try {
+                    service.onBootPhase(mCurrentPhase);
+                } catch (Exception ex) {
+                    throw new RuntimeException("Failed to boot service "
+                            + service.getClass().getName()
+                            + ": onBootPhase threw an exception during phase "
+                            + mCurrentPhase, ex);
+                }
             }
+        } finally {
+            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
         }
     }
 
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index c0ffb56..09ac7d9 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -215,6 +215,7 @@
 import android.os.StrictMode;
 import android.os.SystemClock;
 import android.os.SystemProperties;
+import android.os.Trace;
 import android.os.UpdateLock;
 import android.os.UserHandle;
 import android.os.UserManager;
@@ -1885,7 +1886,9 @@
             }
             case FINISH_BOOTING_MSG: {
                 if (msg.arg1 != 0) {
+                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "FinishBooting");
                     finishBooting();
+                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                 }
                 if (msg.arg2 != 0) {
                     enableScreenAfterBoot();
@@ -6450,7 +6453,9 @@
             mBootAnimationComplete = true;
         }
         if (callFinishBooting) {
+            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "FinishBooting");
             finishBooting();
+            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
         }
     }
 
@@ -6465,7 +6470,9 @@
         }
 
         if (booting) {
+            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "FinishBooting");
             finishBooting();
+            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
         }
 
         if (enableScreen) {
diff --git a/services/core/java/com/android/server/location/GpsLocationProvider.java b/services/core/java/com/android/server/location/GpsLocationProvider.java
index 5c60a61..239c471 100644
--- a/services/core/java/com/android/server/location/GpsLocationProvider.java
+++ b/services/core/java/com/android/server/location/GpsLocationProvider.java
@@ -434,8 +434,11 @@
     private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
         @Override public void onReceive(Context context, Intent intent) {
             String action = intent.getAction();
-
             if (DEBUG) Log.d(TAG, "receive broadcast intent, action: " + action);
+            if (action == null) {
+                return;
+            }
+
             if (action.equals(ALARM_WAKEUP)) {
                 startNavigating(false);
             } else if (action.equals(ALARM_TIMEOUT)) {
@@ -490,21 +493,27 @@
 
     private void checkSmsSuplInit(Intent intent) {
         SmsMessage[] messages = Intents.getMessagesFromIntent(intent);
-
         if (messages == null) {
             Log.e(TAG, "Message does not exist in the intent.");
             return;
         }
 
-        for (int i=0; i <messages.length; i++) {
-            byte[] supl_init = messages[i].getUserData();
-            native_agps_ni_message(supl_init,supl_init.length);
+        for (SmsMessage message : messages) {
+            if (message != null && message.mWrappedSmsMessage != null) {
+                byte[] suplInit = message.getUserData();
+                if (suplInit != null) {
+                    native_agps_ni_message(suplInit, suplInit.length);
+                }
+            }
         }
     }
 
     private void checkWapSuplInit(Intent intent) {
-        byte[] supl_init = (byte[]) intent.getExtra("data");
-        native_agps_ni_message(supl_init,supl_init.length);
+        byte[] suplInit = intent.getByteArrayExtra("data");
+        if (suplInit == null) {
+            return;
+        }
+        native_agps_ni_message(suplInit,suplInit.length);
     }
 
     private void updateLowPowerMode() {
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 21dd647b..aafaf83 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -38,6 +38,7 @@
 import android.os.StrictMode;
 import android.os.SystemClock;
 import android.os.SystemProperties;
+import android.os.Trace;
 import android.os.UserHandle;
 import android.os.storage.IMountService;
 import android.util.DisplayMetrics;
@@ -175,97 +176,103 @@
     }
 
     private void run() {
-        // If a device's clock is before 1970 (before 0), a lot of
-        // APIs crash dealing with negative numbers, notably
-        // java.io.File#setLastModified, so instead we fake it and
-        // hope that time from cell towers or NTP fixes it shortly.
-        if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {
-            Slog.w(TAG, "System clock is before 1970; setting to 1970.");
-            SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);
-        }
+        try {
+            Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "InitBeforeStartServices");
+            // If a device's clock is before 1970 (before 0), a lot of
+            // APIs crash dealing with negative numbers, notably
+            // java.io.File#setLastModified, so instead we fake it and
+            // hope that time from cell towers or NTP fixes it shortly.
+            if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {
+                Slog.w(TAG, "System clock is before 1970; setting to 1970.");
+                SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);
+            }
 
-        // If the system has "persist.sys.language" and friends set, replace them with
-        // "persist.sys.locale". Note that the default locale at this point is calculated
-        // using the "-Duser.locale" command line flag. That flag is usually populated by
-        // AndroidRuntime using the same set of system properties, but only the system_server
-        // and system apps are allowed to set them.
-        //
-        // NOTE: Most changes made here will need an equivalent change to
-        // core/jni/AndroidRuntime.cpp
-        if (!SystemProperties.get("persist.sys.language").isEmpty()) {
-            final String languageTag = Locale.getDefault().toLanguageTag();
+            // If the system has "persist.sys.language" and friends set, replace them with
+            // "persist.sys.locale". Note that the default locale at this point is calculated
+            // using the "-Duser.locale" command line flag. That flag is usually populated by
+            // AndroidRuntime using the same set of system properties, but only the system_server
+            // and system apps are allowed to set them.
+            //
+            // NOTE: Most changes made here will need an equivalent change to
+            // core/jni/AndroidRuntime.cpp
+            if (!SystemProperties.get("persist.sys.language").isEmpty()) {
+                final String languageTag = Locale.getDefault().toLanguageTag();
 
-            SystemProperties.set("persist.sys.locale", languageTag);
-            SystemProperties.set("persist.sys.language", "");
-            SystemProperties.set("persist.sys.country", "");
-            SystemProperties.set("persist.sys.localevar", "");
-        }
+                SystemProperties.set("persist.sys.locale", languageTag);
+                SystemProperties.set("persist.sys.language", "");
+                SystemProperties.set("persist.sys.country", "");
+                SystemProperties.set("persist.sys.localevar", "");
+            }
 
-        // Here we go!
-        Slog.i(TAG, "Entered the Android system server!");
-        EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN, SystemClock.uptimeMillis());
+            // Here we go!
+            Slog.i(TAG, "Entered the Android system server!");
+            EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN, SystemClock.uptimeMillis());
 
-        // In case the runtime switched since last boot (such as when
-        // the old runtime was removed in an OTA), set the system
-        // property so that it is in sync. We can't do this in
-        // libnativehelper's JniInvocation::Init code where we already
-        // had to fallback to a different runtime because it is
-        // running as root and we need to be the system user to set
-        // the property. http://b/11463182
-        SystemProperties.set("persist.sys.dalvik.vm.lib.2", VMRuntime.getRuntime().vmLibrary());
+            // In case the runtime switched since last boot (such as when
+            // the old runtime was removed in an OTA), set the system
+            // property so that it is in sync. We can't do this in
+            // libnativehelper's JniInvocation::Init code where we already
+            // had to fallback to a different runtime because it is
+            // running as root and we need to be the system user to set
+            // the property. http://b/11463182
+            SystemProperties.set("persist.sys.dalvik.vm.lib.2", VMRuntime.getRuntime().vmLibrary());
 
-        // Enable the sampling profiler.
-        if (SamplingProfilerIntegration.isEnabled()) {
-            SamplingProfilerIntegration.start();
-            mProfilerSnapshotTimer = new Timer();
-            mProfilerSnapshotTimer.schedule(new TimerTask() {
-                @Override
-                public void run() {
-                    SamplingProfilerIntegration.writeSnapshot("system_server", null);
-                }
-            }, SNAPSHOT_INTERVAL, SNAPSHOT_INTERVAL);
-        }
+            // Enable the sampling profiler.
+            if (SamplingProfilerIntegration.isEnabled()) {
+                SamplingProfilerIntegration.start();
+                mProfilerSnapshotTimer = new Timer();
+                mProfilerSnapshotTimer.schedule(new TimerTask() {
+                        @Override
+                        public void run() {
+                            SamplingProfilerIntegration.writeSnapshot("system_server", null);
+                        }
+                    }, SNAPSHOT_INTERVAL, SNAPSHOT_INTERVAL);
+            }
 
-        // Mmmmmm... more memory!
-        VMRuntime.getRuntime().clearGrowthLimit();
+            // Mmmmmm... more memory!
+            VMRuntime.getRuntime().clearGrowthLimit();
 
-        // The system server has to run all of the time, so it needs to be
-        // as efficient as possible with its memory usage.
-        VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);
+            // The system server has to run all of the time, so it needs to be
+            // as efficient as possible with its memory usage.
+            VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);
 
-        // Some devices rely on runtime fingerprint generation, so make sure
-        // we've defined it before booting further.
-        Build.ensureFingerprintProperty();
+            // Some devices rely on runtime fingerprint generation, so make sure
+            // we've defined it before booting further.
+            Build.ensureFingerprintProperty();
 
-        // Within the system server, it is an error to access Environment paths without
-        // explicitly specifying a user.
-        Environment.setUserRequired(true);
+            // Within the system server, it is an error to access Environment paths without
+            // explicitly specifying a user.
+            Environment.setUserRequired(true);
 
-        // Ensure binder calls into the system always run at foreground priority.
-        BinderInternal.disableBackgroundScheduling(true);
+            // Ensure binder calls into the system always run at foreground priority.
+            BinderInternal.disableBackgroundScheduling(true);
 
-        // Prepare the main looper thread (this thread).
-        android.os.Process.setThreadPriority(
+            // Prepare the main looper thread (this thread).
+            android.os.Process.setThreadPriority(
                 android.os.Process.THREAD_PRIORITY_FOREGROUND);
-        android.os.Process.setCanSelfBackground(false);
-        Looper.prepareMainLooper();
+            android.os.Process.setCanSelfBackground(false);
+            Looper.prepareMainLooper();
 
-        // Initialize native services.
-        System.loadLibrary("android_servers");
+            // Initialize native services.
+            System.loadLibrary("android_servers");
 
-        // Check whether we failed to shut down last time we tried.
-        // This call may not return.
-        performPendingShutdown();
+            // Check whether we failed to shut down last time we tried.
+            // This call may not return.
+            performPendingShutdown();
 
-        // Initialize the system context.
-        createSystemContext();
+            // Initialize the system context.
+            createSystemContext();
 
-        // Create the system service manager.
-        mSystemServiceManager = new SystemServiceManager(mSystemContext);
-        LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
+            // Create the system service manager.
+            mSystemServiceManager = new SystemServiceManager(mSystemContext);
+            LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
+        } finally {
+            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
+        }
 
         // Start services.
         try {
+            Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "StartServices");
             startBootstrapServices();
             startCoreServices();
             startOtherServices();
@@ -273,6 +280,8 @@
             Slog.e("System", "******************************************");
             Slog.e("System", "************ Failure starting system services", ex);
             throw ex;
+        } finally {
+            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
         }
 
         // For debug builds, log event loop stalls to dropbox for analysis.
@@ -340,7 +349,9 @@
 
         // Now that the power manager has been started, let the activity manager
         // initialize power management features.
+        Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "InitPowerManagement");
         mActivityManagerService.initPowerManagement();
+        Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
 
         // Manages LEDs and display backlight so we need it to bring up the display.
         mSystemServiceManager.startService(LightsService.class);
@@ -363,14 +374,16 @@
         }
 
         // Start the package manager.
-        Slog.i(TAG, "Package Manager");
+        traceBeginAndSlog("StartPackageManagerService");
         mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
                 mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
         mFirstBoot = mPackageManagerService.isFirstBoot();
         mPackageManager = mSystemContext.getPackageManager();
+        Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
 
-        Slog.i(TAG, "User Service");
+        traceBeginAndSlog("StartUserManagerService");
         ServiceManager.addService(Context.USER_SERVICE, UserManagerService.getInstance());
+        Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
 
         // Initialize attribute cache used to cache resources from packages.
         AttributeCache.init(mSystemContext);
@@ -442,17 +455,20 @@
             Slog.i(TAG, "Reading configuration...");
             SystemConfig.getInstance();
 
-            Slog.i(TAG, "Scheduling Policy");
+            traceBeginAndSlog("StartSchedulingPolicyService");
             ServiceManager.addService("scheduling_policy", new SchedulingPolicyService());
+            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
 
             mSystemServiceManager.startService(TelecomLoaderService.class);
 
-            Slog.i(TAG, "Telephony Registry");
+            traceBeginAndSlog("StartTelephonyRegistry");
             telephonyRegistry = new TelephonyRegistry(context);
             ServiceManager.addService("telephony.registry", telephonyRegistry);
+            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
 
-            Slog.i(TAG, "Entropy Mixer");
+            traceBeginAndSlog("StartEntropyMixer");
             entropyMixer = new EntropyMixer(context);
+            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
 
             mContentResolver = context.getContentResolver();
 
@@ -460,47 +476,55 @@
             mSystemServiceManager.startService(CameraService.class);
 
             // The AccountManager must come before the ContentService
+            traceBeginAndSlog("StartAccountManagerService");
             try {
                 // TODO: seems like this should be disable-able, but req'd by ContentService
-                Slog.i(TAG, "Account Manager");
                 accountManager = new AccountManagerService(context);
                 ServiceManager.addService(Context.ACCOUNT_SERVICE, accountManager);
             } catch (Throwable e) {
                 Slog.e(TAG, "Failure starting Account Manager", e);
             }
+            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
 
-            Slog.i(TAG, "Content Manager");
+            traceBeginAndSlog("StartContentService");
             contentService = ContentService.main(context,
                     mFactoryTestMode == FactoryTest.FACTORY_TEST_LOW_LEVEL);
+            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
 
-            Slog.i(TAG, "System Content Providers");
+            traceBeginAndSlog("InstallSystemProviders");
             mActivityManagerService.installSystemProviders();
+            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
 
-            Slog.i(TAG, "Vibrator Service");
+            traceBeginAndSlog("StartVibratorService");
             vibrator = new VibratorService(context);
             ServiceManager.addService("vibrator", vibrator);
+            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
 
-            Slog.i(TAG, "Consumer IR Service");
+            traceBeginAndSlog("StartConsumerIrService");
             consumerIr = new ConsumerIrService(context);
             ServiceManager.addService(Context.CONSUMER_IR_SERVICE, consumerIr);
+            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
 
             mSystemServiceManager.startService(AlarmManagerService.class);
             alarm = IAlarmManager.Stub.asInterface(
                     ServiceManager.getService(Context.ALARM_SERVICE));
 
-            Slog.i(TAG, "Init Watchdog");
+            traceBeginAndSlog("InitWatchdog");
             final Watchdog watchdog = Watchdog.getInstance();
             watchdog.init(context, mActivityManagerService);
+            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
 
-            Slog.i(TAG, "Input Manager");
+            traceBeginAndSlog("StartInputManagerService");
             inputManager = new InputManagerService(context);
+            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
 
-            Slog.i(TAG, "Window Manager");
+            traceBeginAndSlog("StartWindowManagerService");
             wm = WindowManagerService.main(context, inputManager,
                     mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
                     !mFirstBoot, mOnlyCore);
             ServiceManager.addService(Context.WINDOW_SERVICE, wm);
             ServiceManager.addService(Context.INPUT_SERVICE, inputManager);
+            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
 
             mActivityManagerService.setWindowManager(wm);
 
@@ -523,7 +547,6 @@
             } else if (disableBluetooth) {
                 Slog.i(TAG, "Bluetooth Service disabled by config");
             } else {
-                Slog.i(TAG, "Bluetooth Service");
                 mSystemServiceManager.startService(BluetoothService.class);
             }
         } catch (RuntimeException e) {
@@ -544,21 +567,23 @@
 
         // Bring up services needed for UI.
         if (mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
+            traceBeginAndSlog("StartInputMethodManagerService");
             try {
-                Slog.i(TAG, "Input Method Service");
                 imm = new InputMethodManagerService(context);
                 ServiceManager.addService(Context.INPUT_METHOD_SERVICE, imm);
             } catch (Throwable e) {
                 reportWtf("starting Input Manager Service", e);
             }
+            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
 
+            traceBeginAndSlog("StartAccessibilityManagerService");
             try {
-                Slog.i(TAG, "Accessibility Manager");
                 ServiceManager.addService(Context.ACCESSIBILITY_SERVICE,
                         new AccessibilityManagerService(context));
             } catch (Throwable e) {
                 reportWtf("starting Accessibility Manager", e);
             }
+            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
         }
 
         try {
@@ -588,11 +613,13 @@
         // as appropriate.
         mSystemServiceManager.startService(UiModeManagerService.class);
 
+        Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "PerformBootDexOpt");
         try {
             mPackageManagerService.performBootDexOpt();
         } catch (Throwable e) {
             reportWtf("performing boot dexopt", e);
         }
+        Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
 
         try {
             ActivityManagerNative.getDefault().showBootMessage(
@@ -604,13 +631,14 @@
 
         if (mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
             if (!disableNonCoreServices) {
+                traceBeginAndSlog("StartLockSettingsService");
                 try {
-                    Slog.i(TAG,  "LockSettingsService");
                     lockSettings = new LockSettingsService(context);
                     ServiceManager.addService("lock_settings", lockSettings);
                 } catch (Throwable e) {
                     reportWtf("starting LockSettingsService service", e);
                 }
+                Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
 
                 if (!SystemProperties.get(PERSISTENT_DATA_BLOCK_PROP).equals("")) {
                     mSystemServiceManager.startService(PersistentDataBlockService.class);
@@ -624,64 +652,70 @@
             }
 
             if (!disableSystemUI) {
+                traceBeginAndSlog("StartStatusBarManagerService");
                 try {
-                    Slog.i(TAG, "Status Bar");
                     statusBar = new StatusBarManagerService(context, wm);
                     ServiceManager.addService(Context.STATUS_BAR_SERVICE, statusBar);
                 } catch (Throwable e) {
                     reportWtf("starting StatusBarManagerService", e);
                 }
+                Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
             }
 
             if (!disableNonCoreServices) {
+                traceBeginAndSlog("StartClipboardService");
                 try {
-                    Slog.i(TAG, "Clipboard Service");
                     ServiceManager.addService(Context.CLIPBOARD_SERVICE,
                             new ClipboardService(context));
                 } catch (Throwable e) {
                     reportWtf("starting Clipboard Service", e);
                 }
+                Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
             }
 
             if (!disableNetwork) {
+                traceBeginAndSlog("StartNetworkManagementService");
                 try {
-                    Slog.i(TAG, "NetworkManagement Service");
                     networkManagement = NetworkManagementService.create(context);
                     ServiceManager.addService(Context.NETWORKMANAGEMENT_SERVICE, networkManagement);
                 } catch (Throwable e) {
                     reportWtf("starting NetworkManagement Service", e);
                 }
+                Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
             }
 
             if (!disableNonCoreServices) {
+                traceBeginAndSlog("StartTextServicesManagerService");
                 try {
-                    Slog.i(TAG, "Text Service Manager Service");
                     tsms = new TextServicesManagerService(context);
                     ServiceManager.addService(Context.TEXT_SERVICES_MANAGER_SERVICE, tsms);
                 } catch (Throwable e) {
                     reportWtf("starting Text Service Manager Service", e);
                 }
+                Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
             }
 
             if (!disableNetwork) {
+                traceBeginAndSlog("StartNetworkScoreService");
                 try {
-                    Slog.i(TAG, "Network Score Service");
                     networkScore = new NetworkScoreService(context);
                     ServiceManager.addService(Context.NETWORK_SCORE_SERVICE, networkScore);
                 } catch (Throwable e) {
                     reportWtf("starting Network Score Service", e);
                 }
+                Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
 
+                traceBeginAndSlog("StartNetworkStatsService");
                 try {
-                    Slog.i(TAG, "NetworkStats Service");
                     networkStats = new NetworkStatsService(context, networkManagement, alarm);
                     ServiceManager.addService(Context.NETWORK_STATS_SERVICE, networkStats);
                 } catch (Throwable e) {
                     reportWtf("starting NetworkStats Service", e);
                 }
+                Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
 
+                traceBeginAndSlog("StartNetworkPolicyManagerService");
                 try {
-                    Slog.i(TAG, "NetworkPolicy Service");
                     networkPolicy = new NetworkPolicyManagerService(
                             context, mActivityManagerService,
                             (IPowerManager)ServiceManager.getService(Context.POWER_SERVICE),
@@ -690,6 +724,7 @@
                 } catch (Throwable e) {
                     reportWtf("starting NetworkPolicy Service", e);
                 }
+                Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
 
                 mSystemServiceManager.startService(WIFI_P2P_SERVICE_CLASS);
                 mSystemServiceManager.startService(WIFI_SERVICE_CLASS);
@@ -703,8 +738,8 @@
                     mSystemServiceManager.startService(ETHERNET_SERVICE_CLASS);
                 }
 
+                traceBeginAndSlog("StartConnectivityService");
                 try {
-                    Slog.i(TAG, "Connectivity Service");
                     connectivity = new ConnectivityService(
                             context, networkManagement, networkStats, networkPolicy);
                     ServiceManager.addService(Context.CONNECTIVITY_SERVICE, connectivity);
@@ -713,25 +748,28 @@
                 } catch (Throwable e) {
                     reportWtf("starting Connectivity Service", e);
                 }
+                Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
 
+                traceBeginAndSlog("StartNsdService");
                 try {
-                    Slog.i(TAG, "Network Service Discovery Service");
                     serviceDiscovery = NsdService.create(context);
                     ServiceManager.addService(
                             Context.NSD_SERVICE, serviceDiscovery);
                 } catch (Throwable e) {
                     reportWtf("starting Service Discovery Service", e);
                 }
+                Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
             }
 
             if (!disableNonCoreServices) {
+                traceBeginAndSlog("StartUpdateLockService");
                 try {
-                    Slog.i(TAG, "UpdateLock Service");
                     ServiceManager.addService(Context.UPDATE_LOCK_SERVICE,
                             new UpdateLockService(context));
                 } catch (Throwable e) {
                     reportWtf("starting UpdateLockService", e);
                 }
+                Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
             }
 
             /*
@@ -740,25 +778,31 @@
              * first before continuing.
              */
             if (mountService != null && !mOnlyCore) {
+                Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "WaitForAsecScan");
                 try {
                     mountService.waitForAsecScan();
                 } catch (RemoteException ignored) {
                 }
+                Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
             }
 
+            Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "MakeAccountManagerServiceReady");
             try {
                 if (accountManager != null)
                     accountManager.systemReady();
             } catch (Throwable e) {
                 reportWtf("making Account Manager Service ready", e);
             }
+            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
 
+            Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "MakeContentServiceReady");
             try {
                 if (contentService != null)
                     contentService.systemReady();
             } catch (Throwable e) {
                 reportWtf("making Content Service ready", e);
             }
+            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
 
             mSystemServiceManager.startService(NotificationManagerService.class);
             notification = INotificationManager.Stub.asInterface(
@@ -768,66 +812,72 @@
             mSystemServiceManager.startService(DeviceStorageMonitorService.class);
 
             if (!disableLocation) {
+                traceBeginAndSlog("StartLocationManagerService");
                 try {
-                    Slog.i(TAG, "Location Manager");
                     location = new LocationManagerService(context);
                     ServiceManager.addService(Context.LOCATION_SERVICE, location);
                 } catch (Throwable e) {
                     reportWtf("starting Location Manager", e);
                 }
+                Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
 
+                traceBeginAndSlog("StartCountryDetectorService");
                 try {
-                    Slog.i(TAG, "Country Detector");
                     countryDetector = new CountryDetectorService(context);
                     ServiceManager.addService(Context.COUNTRY_DETECTOR, countryDetector);
                 } catch (Throwable e) {
                     reportWtf("starting Country Detector", e);
                 }
+                Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
             }
 
             if (!disableNonCoreServices) {
+                traceBeginAndSlog("StartSearchManagerService");
                 try {
-                    Slog.i(TAG, "Search Service");
                     ServiceManager.addService(Context.SEARCH_SERVICE,
                             new SearchManagerService(context));
                 } catch (Throwable e) {
                     reportWtf("starting Search Service", e);
                 }
+                Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
             }
 
             mSystemServiceManager.startService(DropBoxManagerService.class);
 
             if (!disableNonCoreServices && context.getResources().getBoolean(
                         R.bool.config_enableWallpaperService)) {
+                traceBeginAndSlog("StartWallpaperManagerService");
                 try {
-                    Slog.i(TAG, "Wallpaper Service");
                     wallpaper = new WallpaperManagerService(context);
                     ServiceManager.addService(Context.WALLPAPER_SERVICE, wallpaper);
                 } catch (Throwable e) {
                     reportWtf("starting Wallpaper Service", e);
                 }
+                Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
             }
 
+            traceBeginAndSlog("StartAudioService");
             try {
-                Slog.i(TAG, "Audio Service");
                 audioService = new AudioService(context);
                 ServiceManager.addService(Context.AUDIO_SERVICE, audioService);
             } catch (Throwable e) {
                 reportWtf("starting Audio Service", e);
             }
+            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
 
             if (!disableNonCoreServices) {
                 mSystemServiceManager.startService(DockObserver.class);
             }
 
+            traceBeginAndSlog("StartWiredAccessoryManager");
             try {
-                Slog.i(TAG, "Wired Accessory Manager");
                 // Listen for wired headset changes
                 inputManager.setWiredAccessoryCallbacks(
                         new WiredAccessoryManager(context, inputManager));
             } catch (Throwable e) {
                 reportWtf("starting WiredAccessoryManager", e);
             }
+            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
 
             if (!disableNonCoreServices) {
                 if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_MIDI)) {
@@ -839,17 +889,20 @@
                         || mPackageManager.hasSystemFeature(
                                 PackageManager.FEATURE_USB_ACCESSORY)) {
                     // Manage USB host and device support
+                    Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "StartUsbService");
                     mSystemServiceManager.startService(USB_SERVICE_CLASS);
+                    Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
                 }
 
+                traceBeginAndSlog("StartSerialService");
                 try {
-                    Slog.i(TAG, "Serial Service");
                     // Serial port support
                     serial = new SerialService(context);
                     ServiceManager.addService(Context.SERIAL_SERVICE, serial);
                 } catch (Throwable e) {
                     Slog.e(TAG, "Failure starting SerialService", e);
                 }
+                Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
             }
 
             mSystemServiceManager.startService(TwilightService.class);
@@ -875,49 +928,54 @@
                 }
             }
 
+            traceBeginAndSlog("StartDiskStatsService");
             try {
-                Slog.i(TAG, "DiskStats Service");
                 ServiceManager.addService("diskstats", new DiskStatsService(context));
             } catch (Throwable e) {
                 reportWtf("starting DiskStats Service", e);
             }
+            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
 
+            traceBeginAndSlog("StartSamplingProfilerService");
             try {
                 // need to add this service even if SamplingProfilerIntegration.isEnabled()
                 // is false, because it is this service that detects system property change and
                 // turns on SamplingProfilerIntegration. Plus, when sampling profiler doesn't work,
                 // there is little overhead for running this service.
-                Slog.i(TAG, "SamplingProfiler Service");
                 ServiceManager.addService("samplingprofiler",
                             new SamplingProfilerService(context));
             } catch (Throwable e) {
                 reportWtf("starting SamplingProfiler Service", e);
             }
+            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
 
             if (!disableNetwork && !disableNetworkTime) {
+                traceBeginAndSlog("StartNetworkTimeUpdateService");
                 try {
-                    Slog.i(TAG, "NetworkTimeUpdateService");
                     networkTimeUpdater = new NetworkTimeUpdateService(context);
                 } catch (Throwable e) {
                     reportWtf("starting NetworkTimeUpdate service", e);
                 }
+                Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
             }
 
+            traceBeginAndSlog("StartCommonTimeManagementService");
             try {
-                Slog.i(TAG, "CommonTimeManagementService");
                 commonTimeMgmtService = new CommonTimeManagementService(context);
                 ServiceManager.addService("commontime_management", commonTimeMgmtService);
             } catch (Throwable e) {
                 reportWtf("starting CommonTimeManagementService service", e);
             }
+            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
 
             if (!disableNetwork) {
+                traceBeginAndSlog("CertBlacklister");
                 try {
-                    Slog.i(TAG, "CertBlacklister");
                     CertBlacklister blacklister = new CertBlacklister(context);
                 } catch (Throwable e) {
                     reportWtf("starting CertBlacklister", e);
                 }
+                Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
             }
 
             if (!disableNonCoreServices) {
@@ -926,13 +984,14 @@
             }
 
             if (!disableNonCoreServices && ZygoteInit.PRELOAD_RESOURCES) {
+                traceBeginAndSlog("StartAssetAtlasService");
                 try {
-                    Slog.i(TAG, "Assets Atlas Service");
                     atlas = new AssetAtlasService(context);
                     ServiceManager.addService(AssetAtlasService.ASSET_ATLAS_SERVICE, atlas);
                 } catch (Throwable e) {
                     reportWtf("starting AssetAtlasService", e);
                 }
+                Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
             }
 
             if (!disableNonCoreServices) {
@@ -957,24 +1016,26 @@
             }
 
             if (!disableNonCoreServices) {
+                traceBeginAndSlog("StartMediaRouterService");
                 try {
-                    Slog.i(TAG, "Media Router Service");
                     mediaRouter = new MediaRouterService(context);
                     ServiceManager.addService(Context.MEDIA_ROUTER_SERVICE, mediaRouter);
                 } catch (Throwable e) {
                     reportWtf("starting MediaRouterService", e);
                 }
+                Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
 
                 mSystemServiceManager.startService(TrustManagerService.class);
 
                 mSystemServiceManager.startService(FingerprintService.class);
 
+                traceBeginAndSlog("StartBackgroundDexOptService");
                 try {
-                    Slog.i(TAG, "BackgroundDexOptService");
                     BackgroundDexOptService.schedule(context, 0);
                 } catch (Throwable e) {
                     reportWtf("starting BackgroundDexOptService", e);
                 }
+                Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
 
             }
 
@@ -1002,12 +1063,15 @@
 
         // It is now time to start up the app processes...
 
+        Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "MakeVibratorServiceReady");
         try {
             vibrator.systemReady();
         } catch (Throwable e) {
             reportWtf("making Vibrator Service ready", e);
         }
+        Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
 
+        Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "MakeLockSettingsServiceReady");
         if (lockSettings != null) {
             try {
                 lockSettings.systemReady();
@@ -1015,17 +1079,20 @@
                 reportWtf("making Lock Settings Service ready", e);
             }
         }
+        Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
 
         // Needed by DevicePolicyManager for initialization
         mSystemServiceManager.startBootPhase(SystemService.PHASE_LOCK_SETTINGS_READY);
 
         mSystemServiceManager.startBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY);
 
+        Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "MakeWindowManagerServiceReady");
         try {
             wm.systemReady();
         } catch (Throwable e) {
             reportWtf("making Window Manager Service ready", e);
         }
+        Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
 
         if (safeMode) {
             mActivityManagerService.showSafeModeOverlay();
@@ -1046,25 +1113,32 @@
             systemTheme.rebase();
         }
 
+        Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "MakePowerManagerServiceReady");
         try {
             // TODO: use boot phase
             mPowerManagerService.systemReady(mActivityManagerService.getAppOpsService());
+            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
         } catch (Throwable e) {
             reportWtf("making Power Manager Service ready", e);
         }
+        Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
 
+        Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "MakePackageManagerServiceReady");
         try {
             mPackageManagerService.systemReady();
         } catch (Throwable e) {
             reportWtf("making Package Manager Service ready", e);
         }
+        Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
 
+        Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "MakeDisplayManagerServiceReady");
         try {
             // TODO: use boot phase and communicate these flags some other way
             mDisplayManagerService.systemReady(safeMode, mOnlyCore);
         } catch (Throwable e) {
             reportWtf("making Display Manager Service ready", e);
         }
+        Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
 
         // These are needed to propagate to the runnable below.
         final NetworkManagementService networkManagementF = networkManagement;
@@ -1098,55 +1172,76 @@
                 Slog.i(TAG, "Making services ready");
                 mSystemServiceManager.startBootPhase(
                         SystemService.PHASE_ACTIVITY_MANAGER_READY);
+                Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "PhaseActivityManagerReady");
 
+                Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "StartObservingNativeCrashes");
                 try {
                     mActivityManagerService.startObservingNativeCrashes();
                 } catch (Throwable e) {
                     reportWtf("observing native crashes", e);
                 }
+                Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
 
                 Slog.i(TAG, "WebViewFactory preparation");
+                Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "WebViewFactoryPreparation");
                 WebViewFactory.prepareWebViewInSystemServer();
+                Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
 
+                Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "StartSystemUI");
                 try {
                     startSystemUi(context);
                 } catch (Throwable e) {
                     reportWtf("starting System UI", e);
                 }
+                Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
+                Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "MakeMountServiceReady");
                 try {
                     if (networkScoreF != null) networkScoreF.systemReady();
                 } catch (Throwable e) {
                     reportWtf("making Network Score Service ready", e);
                 }
+                Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
+                Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "MakeNetworkManagementServiceReady");
                 try {
                     if (networkManagementF != null) networkManagementF.systemReady();
                 } catch (Throwable e) {
                     reportWtf("making Network Managment Service ready", e);
                 }
+                Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
+                Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "MakeNetworkStatsServiceReady");
                 try {
                     if (networkStatsF != null) networkStatsF.systemReady();
                 } catch (Throwable e) {
                     reportWtf("making Network Stats Service ready", e);
                 }
+                Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
+                Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "MakeNetworkPolicyServiceReady");
                 try {
                     if (networkPolicyF != null) networkPolicyF.systemReady();
                 } catch (Throwable e) {
                     reportWtf("making Network Policy Service ready", e);
                 }
+                Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
+                Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "MakeConnectivityServiceReady");
                 try {
                     if (connectivityF != null) connectivityF.systemReady();
                 } catch (Throwable e) {
                     reportWtf("making Connectivity Service ready", e);
                 }
+                Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
+                Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "MakeAudioServiceReady");
                 try {
                     if (audioServiceF != null) audioServiceF.systemReady();
                 } catch (Throwable e) {
                     reportWtf("Notifying AudioService running", e);
                 }
+                Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
                 Watchdog.getInstance().start();
 
                 // It is now okay to let the various system services start their
                 // third party code...
+                Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
+                Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "PhaseThirdPartyAppsCanStart");
                 mSystemServiceManager.startBootPhase(
                         SystemService.PHASE_THIRD_PARTY_APPS_CAN_START);
 
@@ -1215,6 +1310,7 @@
                 } catch (Throwable e) {
                     reportWtf("Notifying MmsService running", e);
                 }
+                Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
             }
         });
     }
@@ -1226,4 +1322,9 @@
         //Slog.d(TAG, "Starting service: " + intent);
         context.startServiceAsUser(intent, UserHandle.SYSTEM);
     }
+
+    private static void traceBeginAndSlog(String name) {
+        Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, name);
+        Slog.i(TAG, name);
+    }
 }
diff --git a/tests/SurfaceComposition/Android.mk b/tests/SurfaceComposition/Android.mk
new file mode 100644
index 0000000..95f69f1
--- /dev/null
+++ b/tests/SurfaceComposition/Android.mk
@@ -0,0 +1,34 @@
+# Copyright (C) 2015 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.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+# Don't include this package in any target
+LOCAL_MODULE_TAGS := tests
+# When built, explicitly put it in the data partition.
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_DEX_PREOPT := false
+
+LOCAL_PROGUARD_ENABLED := disabled
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := SurfaceComposition
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_PACKAGE)
diff --git a/tests/SurfaceComposition/AndroidManifest.xml b/tests/SurfaceComposition/AndroidManifest.xml
new file mode 100644
index 0000000..4c0a9b6
--- /dev/null
+++ b/tests/SurfaceComposition/AndroidManifest.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="android.surfacecomposition">
+    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+    <application android:theme="@style/noeffects">
+        <uses-library android:name="android.test.runner" />
+        <activity android:name="android.surfacecomposition.SurfaceCompositionMeasuringActivity" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <!--  self-instrumenting test package. -->
+    <instrumentation android:name="android.test.InstrumentationTestRunner"
+                     android:targetPackage="android.surfacecomposition">
+    </instrumentation>
+</manifest>
diff --git a/tests/SurfaceComposition/res/values/themes.xml b/tests/SurfaceComposition/res/values/themes.xml
new file mode 100644
index 0000000..254d707
--- /dev/null
+++ b/tests/SurfaceComposition/res/values/themes.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+<resources>
+    <style name="noeffects" parent="@android:style/Theme.Holo.NoActionBar.Fullscreen">
+        <item name="android:windowNoTitle">true</item>
+        <item name="android:windowFullscreen">true</item>
+        <item name="android:fadingEdge">none</item>
+        <item name="android:windowContentTransitions">false</item>
+        <item name="android:windowAnimationStyle">@null</item>
+    </style>
+</resources>
diff --git a/tests/SurfaceComposition/src/android/surfacecomposition/CustomLayout.java b/tests/SurfaceComposition/src/android/surfacecomposition/CustomLayout.java
new file mode 100644
index 0000000..d626f10
--- /dev/null
+++ b/tests/SurfaceComposition/src/android/surfacecomposition/CustomLayout.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2015 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.surfacecomposition;
+
+import android.content.Context;
+import android.view.View;
+import android.view.ViewGroup;
+
+public class CustomLayout extends ViewGroup {
+    public CustomLayout(Context context) {
+        super(context);
+    }
+
+    public static class LayoutParams extends ViewGroup.LayoutParams {
+        private int mLeft, mTop, mRight, mBottom;
+
+        public LayoutParams(int left, int top, int right, int bottom) {
+            super(0, 0);
+            mLeft = left;
+            mTop = top;
+            mRight = right;
+            mBottom = bottom;
+        }
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int l, int t, int r, int b) {
+        final int count = getChildCount();
+        for (int i = 0; i < count; i++) {
+            View child = getChildAt(i);
+            CustomLayout.LayoutParams lp = (CustomLayout.LayoutParams) child.getLayoutParams();
+            child.layout(lp.mLeft, lp.mTop, lp.mRight, lp.mBottom);
+        }
+    }
+}
diff --git a/tests/SurfaceComposition/src/android/surfacecomposition/CustomSurfaceView.java b/tests/SurfaceComposition/src/android/surfacecomposition/CustomSurfaceView.java
new file mode 100644
index 0000000..0430662
--- /dev/null
+++ b/tests/SurfaceComposition/src/android/surfacecomposition/CustomSurfaceView.java
@@ -0,0 +1,243 @@
+/*
+ * Copyright (C) 2015 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.surfacecomposition;
+
+import java.util.Random;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.view.Surface;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+
+/**
+ * This provides functionality to measure Surface update frame rate. The idea is to
+ * constantly invalidates Surface in a separate thread. Lowest possible way is to
+ * use SurfaceView which works with Surface. This gives a very small overhead
+ * and very close to Android internals. Note, that lockCanvas is blocking
+ * methods and it returns once SurfaceFlinger consumes previous buffer. This
+ * gives the change to measure real performance of Surface compositor.
+ */
+public class CustomSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
+    private final static long DURATION_TO_WARMUP_MS = 50;
+    private final static long DURATION_TO_MEASURE_ROUGH_MS = 500;
+    private final static long DURATION_TO_MEASURE_PRECISE_MS = 3000;
+    private final static Random mRandom = new Random();
+
+    private final Object mSurfaceLock = new Object();
+    private Surface mSurface;
+    private boolean mDrawNameOnReady = true;
+    private boolean mSurfaceWasChanged = false;
+    private String mName;
+    private Canvas mCanvas;
+
+    class ValidateThread extends Thread {
+        private double mFPS = 0.0f;
+        // Used to support early exit and prevent long computation.
+        private double mBadFPS;
+        private double mPerfectFPS;
+
+        ValidateThread(double badFPS, double perfectFPS) {
+            mBadFPS = badFPS;
+            mPerfectFPS = perfectFPS;
+        }
+
+        public void run() {
+            long startTime = System.currentTimeMillis();
+            while (System.currentTimeMillis() - startTime < DURATION_TO_WARMUP_MS) {
+                invalidateSurface(false);
+            }
+
+            startTime = System.currentTimeMillis();
+            long endTime;
+            int frameCnt = 0;
+            while (true) {
+                invalidateSurface(false);
+                endTime = System.currentTimeMillis();
+                ++frameCnt;
+                mFPS = (double)frameCnt * 1000.0 / (endTime - startTime);
+                if ((endTime - startTime) >= DURATION_TO_MEASURE_ROUGH_MS) {
+                    // Test if result looks too bad or perfect and stop early.
+                    if (mFPS <= mBadFPS || mFPS >= mPerfectFPS) {
+                        break;
+                    }
+                }
+                if ((endTime - startTime) >= DURATION_TO_MEASURE_PRECISE_MS) {
+                    break;
+                }
+            }
+        }
+
+        public double getFPS() {
+            return mFPS;
+        }
+    }
+
+    public CustomSurfaceView(Context context, String name) {
+        super(context);
+        mName = name;
+        getHolder().addCallback(this);
+    }
+
+    public void setMode(int pixelFormat, boolean drawNameOnReady) {
+        mDrawNameOnReady = drawNameOnReady;
+        getHolder().setFormat(pixelFormat);
+    }
+
+    public void acquireCanvas() {
+        synchronized (mSurfaceLock) {
+            if (mCanvas != null) {
+                throw new RuntimeException("Surface canvas was already acquired.");
+            }
+            if (mSurface != null) {
+                mCanvas = mSurface.lockCanvas(null);
+            }
+        }
+    }
+
+    public void releaseCanvas() {
+        synchronized (mSurfaceLock) {
+            if (mCanvas != null) {
+                if (mSurface == null) {
+                    throw new RuntimeException(
+                            "Surface was destroyed but canvas was not released.");
+                }
+                mSurface.unlockCanvasAndPost(mCanvas);
+                mCanvas = null;
+            }
+        }
+    }
+
+    /**
+     * Invalidate surface.
+     */
+    private void invalidateSurface(boolean drawSurfaceId) {
+        synchronized (mSurfaceLock) {
+            if (mSurface != null) {
+                Canvas canvas = mSurface.lockCanvas(null);
+                // Draw surface name for debug purpose only. This does not affect the test
+                // because it is drawn only during allocation.
+                if (drawSurfaceId) {
+                    int textSize = canvas.getHeight() / 24;
+                    Paint paint = new Paint();
+                    paint.setTextSize(textSize);
+                    int textWidth = (int)(paint.measureText(mName) + 0.5f);
+                    int x = mRandom.nextInt(canvas.getWidth() - textWidth);
+                    int y = textSize + mRandom.nextInt(canvas.getHeight() - textSize);
+                    // Create effect of fog to visually control correctness of composition.
+                    paint.setColor(0xFFFF8040);
+                    canvas.drawARGB(32, 255, 255, 255);
+                    canvas.drawText(mName, x, y, paint);
+                }
+                mSurface.unlockCanvasAndPost(canvas);
+            }
+        }
+    }
+
+    /**
+     * Wait until surface is created and ready to use or return immediately if surface
+     * already exists.
+     */
+    public void waitForSurfaceReady() {
+        synchronized (mSurfaceLock) {
+            if (mSurface == null) {
+                try {
+                    mSurfaceLock.wait(5000);
+                } catch(InterruptedException e) {
+                    e.printStackTrace();
+                }
+            }
+            if (mSurface == null)
+                throw new RuntimeException("Surface is not ready.");
+            mSurfaceWasChanged = false;
+        }
+    }
+
+    /**
+     * Wait until surface is destroyed or return immediately if surface does not exist.
+     */
+    public void waitForSurfaceDestroyed() {
+        synchronized (mSurfaceLock) {
+            if (mSurface != null) {
+                try {
+                    mSurfaceLock.wait(5000);
+                } catch(InterruptedException e) {
+                    e.printStackTrace();
+                }
+            }
+            if (mSurface != null)
+                throw new RuntimeException("Surface still exists.");
+            mSurfaceWasChanged = false;
+        }
+    }
+
+    /**
+     * Validate that surface has not been changed since waitForSurfaceReady or
+     * waitForSurfaceDestroyed.
+     */
+    public void validateSurfaceNotChanged() {
+        synchronized (mSurfaceLock) {
+            if (mSurfaceWasChanged) {
+                throw new RuntimeException("Surface was changed during the test execution.");
+            }
+        }
+    }
+
+    public double measureFPS(double badFPS, double perfectFPS) {
+        try {
+            ValidateThread validateThread = new ValidateThread(badFPS, perfectFPS);
+            validateThread.start();
+            validateThread.join();
+            return validateThread.getFPS();
+        } catch (InterruptedException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Override
+    public void surfaceCreated(SurfaceHolder holder) {
+        synchronized (mSurfaceLock) {
+            mSurfaceWasChanged = true;
+        }
+    }
+
+    @Override
+    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
+        // This method is always called at least once, after surfaceCreated.
+        synchronized (mSurfaceLock) {
+            mSurface = holder.getSurface();
+            // We only need to invalidate the surface for the compositor performance test so that
+            // it gets included in the composition process. For allocation performance we
+            // don't need to invalidate surface and this allows us to remove non-necessary
+            // surface invalidation from the test.
+            if (mDrawNameOnReady) {
+                invalidateSurface(true);
+            }
+            mSurfaceWasChanged = true;
+            mSurfaceLock.notify();
+        }
+    }
+
+    @Override
+    public void surfaceDestroyed(SurfaceHolder holder) {
+        synchronized (mSurfaceLock) {
+            mSurface = null;
+            mSurfaceWasChanged = true;
+            mSurfaceLock.notify();
+        }
+    }
+}
diff --git a/tests/SurfaceComposition/src/android/surfacecomposition/MemoryAccessTask.java b/tests/SurfaceComposition/src/android/surfacecomposition/MemoryAccessTask.java
new file mode 100644
index 0000000..c716dae
--- /dev/null
+++ b/tests/SurfaceComposition/src/android/surfacecomposition/MemoryAccessTask.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2015 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.surfacecomposition;
+
+import android.util.Log;
+
+/**
+ * This task will simulate CPU activity by consuming memory bandwidth from the system.
+ * Note: On most system the CPU and GPU will share the same memory.
+ */
+public class MemoryAccessTask {
+    private final static String TAG = "MemoryAccessTask";
+    private final static int BUFFER_SIZE = 32 * 1024 * 1024;
+    private final static int BUFFER_STEP = 256;
+    private boolean mStopRequested;
+    private WorkThread mThread;
+    private final Object mLock = new Object();
+
+    public class WorkThread extends Thread {
+        public void run() {
+            byte[] memory = new byte[BUFFER_SIZE];
+            while (true) {
+                synchronized (mLock) {
+                    if (mStopRequested) {
+                        break;
+                    }
+                }
+                long result = 0;
+                for (int index = 0; index < BUFFER_SIZE; index += BUFFER_STEP) {
+                    result += ++memory[index];
+                }
+                Log.v(TAG, "Processing...:" + result);
+            }
+        }
+    }
+
+    public void start() {
+        if (mThread != null) {
+            throw new RuntimeException("Work thread is already started");
+        }
+        mStopRequested = false;
+        mThread = new WorkThread();
+        mThread.start();
+    }
+
+    public void stop() {
+        if (mThread != null) {
+            synchronized (mLock) {
+                mStopRequested = true;
+            }
+            try {
+                mThread.join();
+            } catch (InterruptedException e) {
+                e.printStackTrace();
+            }
+        }
+    }
+}
diff --git a/tests/SurfaceComposition/src/android/surfacecomposition/SurfaceCompositionMeasuringActivity.java b/tests/SurfaceComposition/src/android/surfacecomposition/SurfaceCompositionMeasuringActivity.java
new file mode 100644
index 0000000..e3e1d34
--- /dev/null
+++ b/tests/SurfaceComposition/src/android/surfacecomposition/SurfaceCompositionMeasuringActivity.java
@@ -0,0 +1,602 @@
+/*
+ * Copyright (C) 2015 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.surfacecomposition;
+
+import java.text.DecimalFormat;
+import java.util.ArrayList;
+import java.util.List;
+
+import android.app.ActionBar;
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.app.ActivityManager.MemoryInfo;
+import android.content.Context;
+import android.graphics.Color;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.graphics.drawable.ColorDrawable;
+import android.os.Bundle;
+import android.view.Display;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.view.Window;
+import android.view.WindowManager;
+import android.widget.ArrayAdapter;
+import android.widget.Button;
+import android.widget.LinearLayout;
+import android.widget.RelativeLayout;
+import android.widget.Spinner;
+import android.widget.TextView;
+
+/**
+ * This activity is designed to measure peformance scores of Android surfaces.
+ * It can work in two modes. In first mode functionality of this activity is
+ * invoked from Cts test (SurfaceCompositionTest). This activity can also be
+ * used in manual mode as a normal app. Different pixel formats are supported.
+ *
+ * measureCompositionScore(pixelFormat)
+ *   This test measures surface compositor performance which shows how many
+ *   surfaces of specific format surface compositor can combine without dropping
+ *   frames. We allow one dropped frame per half second.
+ *
+ * measureAllocationScore(pixelFormat)
+ *   This test measures surface allocation/deallocation performance. It shows
+ *   how many surface lifecycles (creation, destruction) can be done per second.
+ *
+ * In manual mode, which activated by pressing button 'Compositor speed' or
+ * 'Allocator speed', all possible pixel format are tested and combined result
+ * is displayed in text view. Additional system information such as memory
+ * status, display size and surface format is also displayed and regulary
+ * updated.
+ */
+public class SurfaceCompositionMeasuringActivity extends Activity implements OnClickListener {
+    private final static int MIN_NUMBER_OF_SURFACES = 15;
+    private final static int MAX_NUMBER_OF_SURFACES = 40;
+    private final static int WARM_UP_ALLOCATION_CYCLES = 2;
+    private final static int MEASURE_ALLOCATION_CYCLES = 5;
+    private final static int TEST_COMPOSITOR = 1;
+    private final static int TEST_ALLOCATION = 2;
+    private final static float MIN_REFRESH_RATE_SUPPORTED = 50.0f;
+
+    private final static DecimalFormat DOUBLE_FORMAT = new DecimalFormat("#.00");
+    // Possible selection in pixel format selector.
+    private final static int[] PIXEL_FORMATS = new int[] {
+            PixelFormat.TRANSLUCENT,
+            PixelFormat.TRANSPARENT,
+            PixelFormat.OPAQUE,
+            PixelFormat.RGBA_8888,
+            PixelFormat.RGBX_8888,
+            PixelFormat.RGB_888,
+            PixelFormat.RGB_565,
+    };
+
+
+    private List<CustomSurfaceView> mViews = new ArrayList<CustomSurfaceView>();
+    private Button mMeasureCompositionButton;
+    private Button mMeasureAllocationButton;
+    private Spinner mPixelFormatSelector;
+    private TextView mResultView;
+    private TextView mSystemInfoView;
+    private final Object mLockResumed = new Object();
+    private boolean mResumed;
+
+    // Drop one frame per half second.
+    // TODO(khmel)
+    // Add a feature flag and set the target FPS dependent on the target system as e.g.:
+    // 59FPS for MULTI_WINDOW and 54 otherwise (to satisfy the default lax Android requirements).
+    private double mRefreshRate;
+    private double mTargetFPS;
+
+    private int mWidth;
+    private int mHeight;
+
+    class CompositorScore {
+        double mSurfaces;
+        double mBitrate;
+
+        @Override
+        public String toString() {
+            return DOUBLE_FORMAT.format(mSurfaces) + " surfaces. " +
+                    "Bitrate: " + getReadableMemory((long)mBitrate) + "/s";
+        }
+    }
+
+    /**
+     * Measure performance score.
+     *
+     * @return biggest possible number of visible surfaces which surface
+     *         compositor can handle.
+     */
+    public CompositorScore measureCompositionScore(int pixelFormat) {
+        waitForActivityResumed();
+        //MemoryAccessTask memAccessTask = new MemoryAccessTask();
+        //memAccessTask.start();
+        // Destroy any active surface.
+        configureSurfacesAndWait(0, pixelFormat, false);
+        CompositorScore score = new CompositorScore();
+        score.mSurfaces = measureCompositionScore(new Measurement(0, 60.0),
+                new Measurement(mViews.size() + 1, 0.0f), pixelFormat);
+        // Assume 32 bits per pixel.
+        score.mBitrate = score.mSurfaces * mTargetFPS * mWidth * mHeight * 4.0;
+        //memAccessTask.stop();
+        return score;
+    }
+
+    static class AllocationScore {
+        double mMedian;
+        double mMin;
+        double mMax;
+
+        @Override
+        public String toString() {
+            return DOUBLE_FORMAT.format(mMedian) + " (min:" + DOUBLE_FORMAT.format(mMin) +
+                    ", max:" + DOUBLE_FORMAT.format(mMax) + ") surface allocations per second";
+        }
+    }
+
+    public AllocationScore measureAllocationScore(int pixelFormat) {
+        waitForActivityResumed();
+        AllocationScore score = new AllocationScore();
+        for (int i = 0; i < MEASURE_ALLOCATION_CYCLES + WARM_UP_ALLOCATION_CYCLES; ++i) {
+            long time1 = System.currentTimeMillis();
+            configureSurfacesAndWait(MIN_NUMBER_OF_SURFACES, pixelFormat, false);
+            acquireSurfacesCanvas();
+            long time2 = System.currentTimeMillis();
+            releaseSurfacesCanvas();
+            configureSurfacesAndWait(0, pixelFormat, false);
+            // Give SurfaceFlinger some time to rebuild the layer stack and release the buffers.
+            try {
+                Thread.sleep(500);
+            } catch(InterruptedException e) {
+                e.printStackTrace();
+            }
+            if (i < WARM_UP_ALLOCATION_CYCLES) {
+                // This is warm-up cycles, ignore result so far.
+                continue;
+            }
+            double speed = MIN_NUMBER_OF_SURFACES * 1000.0 / (time2 - time1);
+            score.mMedian += speed / MEASURE_ALLOCATION_CYCLES;
+            if (i == WARM_UP_ALLOCATION_CYCLES) {
+                score.mMin = speed;
+                score.mMax = speed;
+            } else {
+                score.mMin = Math.min(score.mMin, speed);
+                score.mMax = Math.max(score.mMax, speed);
+            }
+        }
+
+        return score;
+    }
+
+    @Override
+    public void onClick(View view) {
+        if (view == mMeasureCompositionButton) {
+            doTest(TEST_COMPOSITOR);
+        } else if (view == mMeasureAllocationButton) {
+            doTest(TEST_ALLOCATION);
+        }
+    }
+
+    private void doTest(final int test) {
+        enableControls(false);
+        final int pixelFormat = PIXEL_FORMATS[mPixelFormatSelector.getSelectedItemPosition()];
+        new Thread() {
+            public void run() {
+                final StringBuffer sb = new StringBuffer();
+                switch (test) {
+                    case TEST_COMPOSITOR: {
+                            sb.append("Compositor score:");
+                            CompositorScore score = measureCompositionScore(pixelFormat);
+                            sb.append("\n    " + getPixelFormatInfo(pixelFormat) + ":" +
+                                    score + ".");
+                        }
+                        break;
+                    case TEST_ALLOCATION: {
+                            sb.append("Allocation score:");
+                            AllocationScore score = measureAllocationScore(pixelFormat);
+                            sb.append("\n    " + getPixelFormatInfo(pixelFormat) + ":" +
+                                    score + ".");
+                        }
+                        break;
+                }
+                runOnUiThreadAndWait(new Runnable() {
+                    public void run() {
+                        mResultView.setText(sb.toString());
+                        enableControls(true);
+                        updateSystemInfo(pixelFormat);
+                    }
+                });
+            }
+        }.start();
+    }
+
+    /**
+     * Wait until activity is resumed.
+     */
+    public void waitForActivityResumed() {
+        synchronized (mLockResumed) {
+            if (!mResumed) {
+                try {
+                    mLockResumed.wait(10000);
+                } catch (InterruptedException e) {
+                }
+            }
+            if (!mResumed) {
+                throw new RuntimeException("Activity was not resumed");
+            }
+        }
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+
+        detectRefreshRate();
+
+        // To layouts in parent. First contains list of Surfaces and second
+        // controls. Controls stay on top.
+        RelativeLayout rootLayout = new RelativeLayout(this);
+        rootLayout.setLayoutParams(new ViewGroup.LayoutParams(
+                ViewGroup.LayoutParams.MATCH_PARENT,
+                ViewGroup.LayoutParams.MATCH_PARENT));
+
+        CustomLayout layout = new CustomLayout(this);
+        layout.setLayoutParams(new ViewGroup.LayoutParams(
+                ViewGroup.LayoutParams.MATCH_PARENT,
+                ViewGroup.LayoutParams.MATCH_PARENT));
+
+        Rect rect = new Rect();
+        getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);
+        mWidth = rect.right;
+        mHeight = rect.bottom;
+        long maxMemoryPerSurface = roundToNextPowerOf2(mWidth) * roundToNextPowerOf2(mHeight) * 4;
+        // Use 75% of available memory.
+        int surfaceCnt = (int)((getMemoryInfo().availMem * 3) / (4 * maxMemoryPerSurface));
+        if (surfaceCnt < MIN_NUMBER_OF_SURFACES) {
+            throw new RuntimeException("Not enough memory to allocate " +
+                    MIN_NUMBER_OF_SURFACES + " surfaces.");
+        }
+        if (surfaceCnt > MAX_NUMBER_OF_SURFACES) {
+            surfaceCnt = MAX_NUMBER_OF_SURFACES;
+        }
+
+        LinearLayout controlLayout = new LinearLayout(this);
+        controlLayout.setOrientation(LinearLayout.VERTICAL);
+        controlLayout.setLayoutParams(new ViewGroup.LayoutParams(
+                ViewGroup.LayoutParams.MATCH_PARENT,
+                ViewGroup.LayoutParams.MATCH_PARENT));
+
+        mMeasureCompositionButton = createButton("Compositor speed.", controlLayout);
+        mMeasureAllocationButton = createButton("Allocation speed", controlLayout);
+
+        String[] pixelFomats = new String[PIXEL_FORMATS.length];
+        for (int i = 0; i < pixelFomats.length; ++i) {
+            pixelFomats[i] = getPixelFormatInfo(PIXEL_FORMATS[i]);
+        }
+        mPixelFormatSelector = new Spinner(this);
+        ArrayAdapter<String> pixelFormatSelectorAdapter =
+                new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, pixelFomats);
+        pixelFormatSelectorAdapter.setDropDownViewResource(
+                android.R.layout.simple_spinner_dropdown_item);
+        mPixelFormatSelector.setAdapter(pixelFormatSelectorAdapter);
+        mPixelFormatSelector.setLayoutParams(new LinearLayout.LayoutParams(
+                ViewGroup.LayoutParams.WRAP_CONTENT,
+                ViewGroup.LayoutParams.WRAP_CONTENT));
+        controlLayout.addView(mPixelFormatSelector);
+
+        mResultView = new TextView(this);
+        mResultView.setBackgroundColor(0);
+        mResultView.setText("Press button to start test.");
+        mResultView.setLayoutParams(new LinearLayout.LayoutParams(
+                ViewGroup.LayoutParams.WRAP_CONTENT,
+                ViewGroup.LayoutParams.WRAP_CONTENT));
+        controlLayout.addView(mResultView);
+
+        mSystemInfoView = new TextView(this);
+        mSystemInfoView.setBackgroundColor(0);
+        mSystemInfoView.setLayoutParams(new LinearLayout.LayoutParams(
+                ViewGroup.LayoutParams.WRAP_CONTENT,
+                ViewGroup.LayoutParams.WRAP_CONTENT));
+        controlLayout.addView(mSystemInfoView);
+
+        for (int i = 0; i < surfaceCnt; ++i) {
+            CustomSurfaceView view = new CustomSurfaceView(this, "Surface:" + i);
+            // Create all surfaces overlapped in order to prevent SurfaceFlinger
+            // to filter out surfaces by optimization in case surface is opaque.
+            // In case surface is transparent it will be drawn anyway. Note that first
+            // surface covers whole screen and must stand below other surfaces. Z order of
+            // layers is not predictable and there is only one way to force first
+            // layer to be below others is to mark it as media and all other layers
+            // to mark as media overlay.
+            if (i == 0) {
+                view.setLayoutParams(new CustomLayout.LayoutParams(0, 0, mWidth, mHeight));
+                view.setZOrderMediaOverlay(false);
+            } else {
+                // Z order of other layers is not predefined so make offset on x and reverse
+                // offset on y to make sure that surface is visible in any layout.
+                int x = i;
+                int y = (surfaceCnt - i);
+                view.setLayoutParams(new CustomLayout.LayoutParams(x, y, x + mWidth, y + mHeight));
+                view.setZOrderMediaOverlay(true);
+            }
+            view.setVisibility(View.INVISIBLE);
+            layout.addView(view);
+            mViews.add(view);
+        }
+
+        rootLayout.addView(layout);
+        rootLayout.addView(controlLayout);
+
+        setContentView(rootLayout);
+    }
+
+    private Button createButton(String caption, LinearLayout layout) {
+        Button button = new Button(this);
+        button.setText(caption);
+        button.setLayoutParams(new LinearLayout.LayoutParams(
+                ViewGroup.LayoutParams.WRAP_CONTENT,
+                ViewGroup.LayoutParams.WRAP_CONTENT));
+        button.setOnClickListener(this);
+        layout.addView(button);
+        return button;
+    }
+
+    private void enableControls(boolean enabled) {
+        mMeasureCompositionButton.setEnabled(enabled);
+        mMeasureAllocationButton.setEnabled(enabled);
+        mPixelFormatSelector.setEnabled(enabled);
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+
+        updateSystemInfo(PixelFormat.UNKNOWN);
+
+        synchronized (mLockResumed) {
+            mResumed = true;
+            mLockResumed.notifyAll();
+        }
+    }
+
+    @Override
+    protected void onPause() {
+        super.onPause();
+
+        synchronized (mLockResumed) {
+            mResumed = false;
+        }
+    }
+
+    class Measurement {
+        Measurement(int surfaceCnt, double fps) {
+            mSurfaceCnt = surfaceCnt;
+            mFPS = fps;
+        }
+
+        public final int mSurfaceCnt;
+        public final double mFPS;
+    }
+
+    private double measureCompositionScore(Measurement ok, Measurement fail, int pixelFormat) {
+        if (ok.mSurfaceCnt + 1 == fail.mSurfaceCnt) {
+            // Interpolate result.
+            double fraction = (mTargetFPS - fail.mFPS) / (ok.mFPS - fail.mFPS);
+            return ok.mSurfaceCnt + fraction;
+        }
+
+        int medianSurfaceCnt = (ok.mSurfaceCnt + fail.mSurfaceCnt) / 2;
+        Measurement median = new Measurement(medianSurfaceCnt,
+                measureFPS(medianSurfaceCnt, pixelFormat));
+
+        if (median.mFPS >= mTargetFPS) {
+            return measureCompositionScore(median, fail, pixelFormat);
+        } else {
+            return measureCompositionScore(ok, median, pixelFormat);
+        }
+    }
+
+    private double measureFPS(int surfaceCnt, int pixelFormat) {
+        configureSurfacesAndWait(surfaceCnt, pixelFormat, true);
+        // At least one view is visible and it is enough to update only
+        // one overlapped surface in order to force SurfaceFlinger to send
+        // all surfaces to compositor.
+        double fps = mViews.get(0).measureFPS(mRefreshRate * 0.8, mRefreshRate * 0.999);
+
+        // Make sure that surface configuration was not changed.
+        validateSurfacesNotChanged();
+
+        return fps;
+    }
+
+    private void waitForSurfacesConfigured(final int pixelFormat) {
+        for (int i = 0; i < mViews.size(); ++i) {
+            CustomSurfaceView view = mViews.get(i);
+            if (view.getVisibility() == View.VISIBLE) {
+                view.waitForSurfaceReady();
+            } else {
+                view.waitForSurfaceDestroyed();
+            }
+        }
+        runOnUiThreadAndWait(new Runnable() {
+            @Override
+            public void run() {
+                updateSystemInfo(pixelFormat);
+            }
+        });
+    }
+
+    private void validateSurfacesNotChanged() {
+        for (int i = 0; i < mViews.size(); ++i) {
+            CustomSurfaceView view = mViews.get(i);
+            view.validateSurfaceNotChanged();
+        }
+    }
+
+    private void configureSurfaces(int surfaceCnt, int pixelFormat, boolean invalidate) {
+        for (int i = 0; i < mViews.size(); ++i) {
+            CustomSurfaceView view = mViews.get(i);
+            if (i < surfaceCnt) {
+                view.setMode(pixelFormat, invalidate);
+                view.setVisibility(View.VISIBLE);
+            } else {
+                view.setVisibility(View.INVISIBLE);
+            }
+        }
+    }
+
+    private void configureSurfacesAndWait(final int surfaceCnt, final int pixelFormat,
+            final boolean invalidate) {
+        runOnUiThreadAndWait(new Runnable() {
+            @Override
+            public void run() {
+                configureSurfaces(surfaceCnt, pixelFormat, invalidate);
+            }
+        });
+        waitForSurfacesConfigured(pixelFormat);
+    }
+
+    private void acquireSurfacesCanvas() {
+        for (int i = 0; i < mViews.size(); ++i) {
+            CustomSurfaceView view = mViews.get(i);
+            view.acquireCanvas();
+        }
+    }
+
+    private void releaseSurfacesCanvas() {
+        for (int i = 0; i < mViews.size(); ++i) {
+            CustomSurfaceView view = mViews.get(i);
+            view.releaseCanvas();
+        }
+    }
+
+    private static String getReadableMemory(long bytes) {
+        long unit = 1024;
+        if (bytes < unit) {
+            return bytes + " B";
+        }
+        int exp = (int) (Math.log(bytes) / Math.log(unit));
+        return String.format("%.1f %sB", bytes / Math.pow(unit, exp),
+                "KMGTPE".charAt(exp-1));
+    }
+
+    private MemoryInfo getMemoryInfo() {
+        ActivityManager activityManager = (ActivityManager)
+                getSystemService(ACTIVITY_SERVICE);
+        MemoryInfo memInfo = new MemoryInfo();
+        activityManager.getMemoryInfo(memInfo);
+        return memInfo;
+    }
+
+    private void updateSystemInfo(int pixelFormat) {
+        int visibleCnt = 0;
+        for (int i = 0; i < mViews.size(); ++i) {
+            if (mViews.get(i).getVisibility() == View.VISIBLE) {
+                ++visibleCnt;
+            }
+        }
+
+        MemoryInfo memInfo = getMemoryInfo();
+        String info = "Available " +
+                getReadableMemory(memInfo.availMem) + " from " +
+                getReadableMemory(memInfo.totalMem) + ".\nVisible " +
+                visibleCnt + " from " + mViews.size() + " " +
+                getPixelFormatInfo(pixelFormat) + " surfaces.\n" +
+                "View size: " + mWidth + "x" + mHeight +
+                ". Refresh rate: " + DOUBLE_FORMAT.format(mRefreshRate) + ".";
+        mSystemInfoView.setText(info);
+    }
+
+    private void detectRefreshRate() {
+        WindowManager wm = (WindowManager)getSystemService(Context.WINDOW_SERVICE);
+        mRefreshRate = wm.getDefaultDisplay().getRefreshRate();
+        if (mRefreshRate < MIN_REFRESH_RATE_SUPPORTED)
+            throw new RuntimeException("Unsupported display refresh rate: " + mRefreshRate);
+        mTargetFPS = mRefreshRate - 2.0f;
+    }
+
+    private int roundToNextPowerOf2(int value) {
+        --value;
+        value |= value >> 1;
+        value |= value >> 2;
+        value |= value >> 4;
+        value |= value >> 8;
+        value |= value >> 16;
+        return value + 1;
+    }
+
+    public static String getPixelFormatInfo(int pixelFormat) {
+        switch (pixelFormat) {
+        case PixelFormat.TRANSLUCENT:
+            return "TRANSLUCENT";
+        case PixelFormat.TRANSPARENT:
+            return "TRANSPARENT";
+        case PixelFormat.OPAQUE:
+            return "OPAQUE";
+        case PixelFormat.RGBA_8888:
+            return "RGBA_8888";
+        case PixelFormat.RGBX_8888:
+            return "RGBX_8888";
+        case PixelFormat.RGB_888:
+            return "RGB_888";
+        case PixelFormat.RGB_565:
+            return "RGB_565";
+        default:
+            return "PIX.FORMAT:" + pixelFormat;
+        }
+    }
+
+    /**
+     * A helper that executes a task in the UI thread and waits for its completion.
+     *
+     * @param task - task to execute.
+     */
+    private void runOnUiThreadAndWait(Runnable task) {
+        new UIExecutor(task);
+    }
+
+    class UIExecutor implements Runnable {
+        private final Object mLock = new Object();
+        private Runnable mTask;
+        private boolean mDone = false;
+
+        UIExecutor(Runnable task) {
+            mTask = task;
+            mDone = false;
+            runOnUiThread(this);
+            synchronized (mLock) {
+                while (!mDone) {
+                    try {
+                        mLock.wait();
+                    } catch (InterruptedException e) {
+                        e.printStackTrace();
+                    }
+                }
+            }
+        }
+
+        public void run() {
+            mTask.run();
+            synchronized (mLock) {
+                mDone = true;
+                mLock.notify();
+            }
+        }
+    }
+}
diff --git a/tests/SurfaceComposition/src/android/surfacecomposition/SurfaceCompositionTest.java b/tests/SurfaceComposition/src/android/surfacecomposition/SurfaceCompositionTest.java
new file mode 100644
index 0000000..6e9e739
--- /dev/null
+++ b/tests/SurfaceComposition/src/android/surfacecomposition/SurfaceCompositionTest.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2015 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.surfacecomposition;
+
+import android.graphics.PixelFormat;
+import android.surfacecomposition.SurfaceCompositionMeasuringActivity.AllocationScore;
+import android.surfacecomposition.SurfaceCompositionMeasuringActivity.CompositorScore;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.util.Log;
+
+public class SurfaceCompositionTest extends
+        ActivityInstrumentationTestCase2<SurfaceCompositionMeasuringActivity> {
+    private final static String TAG = "SurfaceCompositionTest";
+
+    // Pass threshold for major pixel formats.
+    private final static int[] TEST_PIXEL_FORMATS = new int[] {
+        PixelFormat.TRANSLUCENT,
+        PixelFormat.OPAQUE,
+    };
+
+    // Based on Nexus 9 performance which is usually < 9.0.
+    private final static double[] MIN_ACCEPTED_COMPOSITION_SCORE = new double[] {
+        8.0,
+        8.0,
+    };
+
+    // Based on Nexus 6 performance which is usually < 28.0.
+    private final static double[] MIN_ACCEPTED_ALLOCATION_SCORE = new double[] {
+        20.0,
+        20.0,
+    };
+
+    public SurfaceCompositionTest() {
+        super(SurfaceCompositionMeasuringActivity.class);
+    }
+
+    private void testRestoreContexts() {
+    }
+
+    @SmallTest
+    public void testSurfaceCompositionPerformance() {
+        for (int i = 0; i < TEST_PIXEL_FORMATS.length; ++i) {
+            int pixelFormat = TEST_PIXEL_FORMATS[i];
+            String formatName = SurfaceCompositionMeasuringActivity.getPixelFormatInfo(pixelFormat);
+            CompositorScore score = getActivity().measureCompositionScore(pixelFormat);
+            Log.i(TAG, "testSurfaceCompositionPerformance(" + formatName + ") = " + score);
+            assertTrue("Device does not support surface(" + formatName + ") composition " +
+                    "performance score. " + score.mSurfaces + " < " +
+                    MIN_ACCEPTED_COMPOSITION_SCORE[i] + ".",
+                    score.mSurfaces >= MIN_ACCEPTED_COMPOSITION_SCORE[i]);
+        }
+    }
+
+    @SmallTest
+    public void testSurfaceAllocationPerformance() {
+        for (int i = 0; i < TEST_PIXEL_FORMATS.length; ++i) {
+            int pixelFormat = TEST_PIXEL_FORMATS[i];
+            String formatName = SurfaceCompositionMeasuringActivity.getPixelFormatInfo(pixelFormat);
+            AllocationScore score = getActivity().measureAllocationScore(pixelFormat);
+            Log.i(TAG, "testSurfaceAllocationPerformance(" + formatName + ") = " + score);
+            assertTrue("Device does not support surface(" + formatName + ") allocation " +
+                    "performance score. " + score.mMedian + " < " +
+                    MIN_ACCEPTED_ALLOCATION_SCORE[i] + ".",
+                    score.mMedian >= MIN_ACCEPTED_ALLOCATION_SCORE[i]);
+        }
+    }
+}
diff --git a/tools/aidl/Android.mk b/tools/aidl/Android.mk
index 354563a..542f272 100644
--- a/tools/aidl/Android.mk
+++ b/tools/aidl/Android.mk
@@ -64,7 +64,8 @@
     libgmock_host \
     libgtest_host \
 
-LOCAL_LDLIBS := -lrt
+LOCAL_LDLIBS_linux := -lrt
+
 include $(BUILD_HOST_NATIVE_TEST)
 
 endif # No TARGET_BUILD_APPS or TARGET_BUILD_PDK