Merge "fix array index out of bounds"
diff --git a/api/current.txt b/api/current.txt
index 415ce7c..0ca9875 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -4687,6 +4687,7 @@
     method public abstract android.app.FragmentManager.BackStackEntry getBackStackEntryAt(int);
     method public abstract int getBackStackEntryCount();
     method public abstract android.app.Fragment getFragment(android.os.Bundle, java.lang.String);
+    method public abstract android.app.Fragment getPrimaryNavigationFragment();
     method public void invalidateOptionsMenu();
     method public abstract boolean isDestroyed();
     method public abstract void popBackStack();
@@ -4763,6 +4764,7 @@
     method public abstract android.app.FragmentTransaction setBreadCrumbTitle(java.lang.CharSequence);
     method public abstract android.app.FragmentTransaction setCustomAnimations(int, int);
     method public abstract android.app.FragmentTransaction setCustomAnimations(int, int, int, int);
+    method public abstract android.app.FragmentTransaction setPrimaryNavigationFragment(android.app.Fragment);
     method public abstract android.app.FragmentTransaction setTransition(int);
     method public abstract android.app.FragmentTransaction setTransitionStyle(int);
     method public abstract android.app.FragmentTransaction show(android.app.Fragment);
@@ -9054,6 +9056,7 @@
     field public static final java.lang.String CATEGORY_TYPED_OPENABLE = "android.intent.category.TYPED_OPENABLE";
     field public static final java.lang.String CATEGORY_UNIT_TEST = "android.intent.category.UNIT_TEST";
     field public static final java.lang.String CATEGORY_VOICE = "android.intent.category.VOICE";
+    field public static final java.lang.String CATEGORY_VR_HOME = "android.intent.category.VR_HOME";
     field public static final android.os.Parcelable.Creator<android.content.Intent> CREATOR;
     field public static final java.lang.String EXTRA_ALARM_COUNT = "android.intent.extra.ALARM_COUNT";
     field public static final java.lang.String EXTRA_ALLOW_MULTIPLE = "android.intent.extra.ALLOW_MULTIPLE";
@@ -25571,6 +25574,7 @@
     field public java.util.BitSet allowedProtocols;
     field public android.net.wifi.WifiEnterpriseConfig enterpriseConfig;
     field public boolean hiddenSSID;
+    field public boolean isHomeProviderNetwork;
     field public int networkId;
     field public java.lang.String preSharedKey;
     field public int priority;
@@ -36124,7 +36128,7 @@
     method public void deleteNotificationChannel(java.lang.String, java.lang.String);
     method public java.util.List<android.app.NotificationChannel> getNotificationChannels(java.lang.String);
     method public final android.os.IBinder onBind(android.content.Intent);
-    method public abstract android.service.notification.Adjustment onNotificationEnqueued(android.service.notification.StatusBarNotification, int, boolean);
+    method public abstract android.service.notification.Adjustment onNotificationEnqueued(android.service.notification.StatusBarNotification);
     method public abstract void onNotificationSnoozedUntilContext(android.service.notification.StatusBarNotification, java.lang.String);
     method public final void unsnoozeNotification(java.lang.String);
     method public void updateNotificationChannel(java.lang.String, android.app.NotificationChannel);
@@ -44077,8 +44081,8 @@
     method public void drawableHotspotChanged(float, float);
     method protected void drawableStateChanged();
     method public android.view.View findFocus();
-    method public final android.view.View findViewById(int);
-    method public final android.view.View findViewWithTag(java.lang.Object);
+    method public final <T extends android.view.View> T findViewById(int);
+    method public final <T extends android.view.View> T findViewWithTag(java.lang.Object);
     method public void findViewsWithText(java.util.ArrayList<android.view.View>, java.lang.CharSequence, int);
     method protected deprecated boolean fitSystemWindows(android.graphics.Rect);
     method public android.view.View focusSearch(int);
@@ -44944,8 +44948,8 @@
     method public int getPersistentDrawingCache();
     method public boolean getTouchscreenBlocksFocus();
     method public int indexOfChild(android.view.View);
-    method public final void invalidateChild(android.view.View, android.graphics.Rect);
-    method public android.view.ViewParent invalidateChildInParent(int[], android.graphics.Rect);
+    method public final deprecated void invalidateChild(android.view.View, android.graphics.Rect);
+    method public deprecated android.view.ViewParent invalidateChildInParent(int[], android.graphics.Rect);
     method public deprecated boolean isAlwaysDrawnWithCacheEnabled();
     method public deprecated boolean isAnimationCacheEnabled();
     method protected boolean isChildrenDrawingOrderEnabled();
@@ -45108,14 +45112,15 @@
     method public abstract android.view.ViewParent getParentForAccessibility();
     method public abstract int getTextAlignment();
     method public abstract int getTextDirection();
-    method public abstract void invalidateChild(android.view.View, android.graphics.Rect);
-    method public abstract android.view.ViewParent invalidateChildInParent(int[], android.graphics.Rect);
+    method public abstract deprecated void invalidateChild(android.view.View, android.graphics.Rect);
+    method public abstract deprecated android.view.ViewParent invalidateChildInParent(int[], android.graphics.Rect);
     method public abstract boolean isLayoutDirectionResolved();
     method public abstract boolean isLayoutRequested();
     method public abstract boolean isTextAlignmentResolved();
     method public abstract boolean isTextDirectionResolved();
     method public abstract android.view.View keyboardNavigationClusterSearch(android.view.View, int);
     method public abstract void notifySubtreeAccessibilityStateChanged(android.view.View, android.view.View, int);
+    method public default void onDescendantInvalidated(android.view.View, android.view.View);
     method public abstract boolean onNestedFling(android.view.View, float, float, boolean);
     method public abstract boolean onNestedPreFling(android.view.View, float, float);
     method public abstract boolean onNestedPrePerformAccessibilityAction(android.view.View, int, android.os.Bundle);
@@ -49021,8 +49026,6 @@
     method public void addHeaderView(android.view.View);
     method public boolean areFooterDividersEnabled();
     method public boolean areHeaderDividersEnabled();
-    method protected android.view.View findViewTraversal(int);
-    method protected android.view.View findViewWithTagTraversal(java.lang.Object);
     method public android.widget.ListAdapter getAdapter();
     method public deprecated long[] getCheckItemIds();
     method public android.graphics.drawable.Drawable getDivider();
diff --git a/api/system-current.txt b/api/system-current.txt
index 4c194d7..1311240 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -4847,6 +4847,7 @@
     method public abstract android.app.FragmentManager.BackStackEntry getBackStackEntryAt(int);
     method public abstract int getBackStackEntryCount();
     method public abstract android.app.Fragment getFragment(android.os.Bundle, java.lang.String);
+    method public abstract android.app.Fragment getPrimaryNavigationFragment();
     method public void invalidateOptionsMenu();
     method public abstract boolean isDestroyed();
     method public abstract void popBackStack();
@@ -4923,6 +4924,7 @@
     method public abstract android.app.FragmentTransaction setBreadCrumbTitle(java.lang.CharSequence);
     method public abstract android.app.FragmentTransaction setCustomAnimations(int, int);
     method public abstract android.app.FragmentTransaction setCustomAnimations(int, int, int, int);
+    method public abstract android.app.FragmentTransaction setPrimaryNavigationFragment(android.app.Fragment);
     method public abstract android.app.FragmentTransaction setTransition(int);
     method public abstract android.app.FragmentTransaction setTransitionStyle(int);
     method public abstract android.app.FragmentTransaction show(android.app.Fragment);
@@ -9466,6 +9468,7 @@
     field public static final java.lang.String CATEGORY_TYPED_OPENABLE = "android.intent.category.TYPED_OPENABLE";
     field public static final java.lang.String CATEGORY_UNIT_TEST = "android.intent.category.UNIT_TEST";
     field public static final java.lang.String CATEGORY_VOICE = "android.intent.category.VOICE";
+    field public static final java.lang.String CATEGORY_VR_HOME = "android.intent.category.VR_HOME";
     field public static final android.os.Parcelable.Creator<android.content.Intent> CREATOR;
     field public static final java.lang.String EXTRA_ALARM_COUNT = "android.intent.extra.ALARM_COUNT";
     field public static final java.lang.String EXTRA_ALLOW_MULTIPLE = "android.intent.extra.ALLOW_MULTIPLE";
@@ -28060,6 +28063,7 @@
     field public int creatorUid;
     field public android.net.wifi.WifiEnterpriseConfig enterpriseConfig;
     field public boolean hiddenSSID;
+    field public boolean isHomeProviderNetwork;
     field public java.lang.String lastUpdateName;
     field public int lastUpdateUid;
     field public boolean meteredHint;
@@ -33721,7 +33725,6 @@
     method public final void attachBaseContext(android.content.Context);
     method public final android.os.IBinder onBind(android.content.Intent);
     method public abstract java.util.List<android.content.pm.permission.RuntimePermissionPresentationInfo> onGetAppPermissions(java.lang.String);
-    method public abstract java.util.List<android.content.pm.ApplicationInfo> onGetAppsUsingPermissions(boolean);
     field public static final java.lang.String SERVICE_INTERFACE = "android.permissionpresenterservice.RuntimePermissionPresenterService";
   }
 
@@ -36829,6 +36832,7 @@
     field public static final java.lang.String USE_GOOGLE_MAIL = "use_google_mail";
     field public static final java.lang.String WAIT_FOR_DEBUGGER = "wait_for_debugger";
     field public static final java.lang.String WEBVIEW_MULTIPROCESS = "webview_multiprocess";
+    field public static final java.lang.String WIFI_BADGING_THRESHOLDS = "wifi_badging_thresholds";
     field public static final java.lang.String WIFI_DEVICE_OWNER_CONFIGS_LOCKDOWN = "wifi_device_owner_configs_lockdown";
     field public static final java.lang.String WIFI_MAX_DHCP_RETRY_COUNT = "wifi_max_dhcp_retry_count";
     field public static final java.lang.String WIFI_MOBILE_DATA_TRANSITION_WAKELOCK_TIMEOUT_MS = "wifi_mobile_data_transition_wakelock_timeout_ms";
@@ -39152,7 +39156,7 @@
     method public void deleteNotificationChannel(java.lang.String, java.lang.String);
     method public java.util.List<android.app.NotificationChannel> getNotificationChannels(java.lang.String);
     method public final android.os.IBinder onBind(android.content.Intent);
-    method public abstract android.service.notification.Adjustment onNotificationEnqueued(android.service.notification.StatusBarNotification, int, boolean);
+    method public abstract android.service.notification.Adjustment onNotificationEnqueued(android.service.notification.StatusBarNotification);
     method public abstract void onNotificationSnoozedUntilContext(android.service.notification.StatusBarNotification, java.lang.String);
     method public final void unsnoozeNotification(java.lang.String);
     method public void updateNotificationChannel(java.lang.String, android.app.NotificationChannel);
@@ -47480,8 +47484,8 @@
     method public void drawableHotspotChanged(float, float);
     method protected void drawableStateChanged();
     method public android.view.View findFocus();
-    method public final android.view.View findViewById(int);
-    method public final android.view.View findViewWithTag(java.lang.Object);
+    method public final <T extends android.view.View> T findViewById(int);
+    method public final <T extends android.view.View> T findViewWithTag(java.lang.Object);
     method public void findViewsWithText(java.util.ArrayList<android.view.View>, java.lang.CharSequence, int);
     method protected deprecated boolean fitSystemWindows(android.graphics.Rect);
     method public android.view.View focusSearch(int);
@@ -48347,8 +48351,8 @@
     method public int getPersistentDrawingCache();
     method public boolean getTouchscreenBlocksFocus();
     method public int indexOfChild(android.view.View);
-    method public final void invalidateChild(android.view.View, android.graphics.Rect);
-    method public android.view.ViewParent invalidateChildInParent(int[], android.graphics.Rect);
+    method public final deprecated void invalidateChild(android.view.View, android.graphics.Rect);
+    method public deprecated android.view.ViewParent invalidateChildInParent(int[], android.graphics.Rect);
     method public deprecated boolean isAlwaysDrawnWithCacheEnabled();
     method public deprecated boolean isAnimationCacheEnabled();
     method protected boolean isChildrenDrawingOrderEnabled();
@@ -48511,14 +48515,15 @@
     method public abstract android.view.ViewParent getParentForAccessibility();
     method public abstract int getTextAlignment();
     method public abstract int getTextDirection();
-    method public abstract void invalidateChild(android.view.View, android.graphics.Rect);
-    method public abstract android.view.ViewParent invalidateChildInParent(int[], android.graphics.Rect);
+    method public abstract deprecated void invalidateChild(android.view.View, android.graphics.Rect);
+    method public abstract deprecated android.view.ViewParent invalidateChildInParent(int[], android.graphics.Rect);
     method public abstract boolean isLayoutDirectionResolved();
     method public abstract boolean isLayoutRequested();
     method public abstract boolean isTextAlignmentResolved();
     method public abstract boolean isTextDirectionResolved();
     method public abstract android.view.View keyboardNavigationClusterSearch(android.view.View, int);
     method public abstract void notifySubtreeAccessibilityStateChanged(android.view.View, android.view.View, int);
+    method public default void onDescendantInvalidated(android.view.View, android.view.View);
     method public abstract boolean onNestedFling(android.view.View, float, float, boolean);
     method public abstract boolean onNestedPreFling(android.view.View, float, float);
     method public abstract boolean onNestedPrePerformAccessibilityAction(android.view.View, int, android.os.Bundle);
@@ -52788,8 +52793,6 @@
     method public void addHeaderView(android.view.View);
     method public boolean areFooterDividersEnabled();
     method public boolean areHeaderDividersEnabled();
-    method protected android.view.View findViewTraversal(int);
-    method protected android.view.View findViewWithTagTraversal(java.lang.Object);
     method public android.widget.ListAdapter getAdapter();
     method public deprecated long[] getCheckItemIds();
     method public android.graphics.drawable.Drawable getDivider();
diff --git a/api/test-current.txt b/api/test-current.txt
index 244bee3..0261629 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -4697,6 +4697,7 @@
     method public abstract android.app.FragmentManager.BackStackEntry getBackStackEntryAt(int);
     method public abstract int getBackStackEntryCount();
     method public abstract android.app.Fragment getFragment(android.os.Bundle, java.lang.String);
+    method public abstract android.app.Fragment getPrimaryNavigationFragment();
     method public void invalidateOptionsMenu();
     method public abstract boolean isDestroyed();
     method public abstract void popBackStack();
@@ -4773,6 +4774,7 @@
     method public abstract android.app.FragmentTransaction setBreadCrumbTitle(java.lang.CharSequence);
     method public abstract android.app.FragmentTransaction setCustomAnimations(int, int);
     method public abstract android.app.FragmentTransaction setCustomAnimations(int, int, int, int);
+    method public abstract android.app.FragmentTransaction setPrimaryNavigationFragment(android.app.Fragment);
     method public abstract android.app.FragmentTransaction setTransition(int);
     method public abstract android.app.FragmentTransaction setTransitionStyle(int);
     method public abstract android.app.FragmentTransaction show(android.app.Fragment);
@@ -9080,6 +9082,7 @@
     field public static final java.lang.String CATEGORY_TYPED_OPENABLE = "android.intent.category.TYPED_OPENABLE";
     field public static final java.lang.String CATEGORY_UNIT_TEST = "android.intent.category.UNIT_TEST";
     field public static final java.lang.String CATEGORY_VOICE = "android.intent.category.VOICE";
+    field public static final java.lang.String CATEGORY_VR_HOME = "android.intent.category.VR_HOME";
     field public static final android.os.Parcelable.Creator<android.content.Intent> CREATOR;
     field public static final java.lang.String EXTRA_ALARM_COUNT = "android.intent.extra.ALARM_COUNT";
     field public static final java.lang.String EXTRA_ALLOW_MULTIPLE = "android.intent.extra.ALLOW_MULTIPLE";
@@ -25663,6 +25666,7 @@
     field public java.util.BitSet allowedProtocols;
     field public android.net.wifi.WifiEnterpriseConfig enterpriseConfig;
     field public boolean hiddenSSID;
+    field public boolean isHomeProviderNetwork;
     field public int networkId;
     field public java.lang.String preSharedKey;
     field public int priority;
@@ -36259,7 +36263,7 @@
     method public void deleteNotificationChannel(java.lang.String, java.lang.String);
     method public java.util.List<android.app.NotificationChannel> getNotificationChannels(java.lang.String);
     method public final android.os.IBinder onBind(android.content.Intent);
-    method public abstract android.service.notification.Adjustment onNotificationEnqueued(android.service.notification.StatusBarNotification, int, boolean);
+    method public abstract android.service.notification.Adjustment onNotificationEnqueued(android.service.notification.StatusBarNotification);
     method public abstract void onNotificationSnoozedUntilContext(android.service.notification.StatusBarNotification, java.lang.String);
     method public final void unsnoozeNotification(java.lang.String);
     method public void updateNotificationChannel(java.lang.String, android.app.NotificationChannel);
@@ -44383,8 +44387,8 @@
     method public void drawableHotspotChanged(float, float);
     method protected void drawableStateChanged();
     method public android.view.View findFocus();
-    method public final android.view.View findViewById(int);
-    method public final android.view.View findViewWithTag(java.lang.Object);
+    method public final <T extends android.view.View> T findViewById(int);
+    method public final <T extends android.view.View> T findViewWithTag(java.lang.Object);
     method public void findViewsWithText(java.util.ArrayList<android.view.View>, java.lang.CharSequence, int);
     method protected deprecated boolean fitSystemWindows(android.graphics.Rect);
     method public android.view.View focusSearch(int);
@@ -45255,8 +45259,8 @@
     method public int getPersistentDrawingCache();
     method public boolean getTouchscreenBlocksFocus();
     method public int indexOfChild(android.view.View);
-    method public final void invalidateChild(android.view.View, android.graphics.Rect);
-    method public android.view.ViewParent invalidateChildInParent(int[], android.graphics.Rect);
+    method public final deprecated void invalidateChild(android.view.View, android.graphics.Rect);
+    method public deprecated android.view.ViewParent invalidateChildInParent(int[], android.graphics.Rect);
     method public deprecated boolean isAlwaysDrawnWithCacheEnabled();
     method public deprecated boolean isAnimationCacheEnabled();
     method protected boolean isChildrenDrawingOrderEnabled();
@@ -45419,14 +45423,15 @@
     method public abstract android.view.ViewParent getParentForAccessibility();
     method public abstract int getTextAlignment();
     method public abstract int getTextDirection();
-    method public abstract void invalidateChild(android.view.View, android.graphics.Rect);
-    method public abstract android.view.ViewParent invalidateChildInParent(int[], android.graphics.Rect);
+    method public abstract deprecated void invalidateChild(android.view.View, android.graphics.Rect);
+    method public abstract deprecated android.view.ViewParent invalidateChildInParent(int[], android.graphics.Rect);
     method public abstract boolean isLayoutDirectionResolved();
     method public abstract boolean isLayoutRequested();
     method public abstract boolean isTextAlignmentResolved();
     method public abstract boolean isTextDirectionResolved();
     method public abstract android.view.View keyboardNavigationClusterSearch(android.view.View, int);
     method public abstract void notifySubtreeAccessibilityStateChanged(android.view.View, android.view.View, int);
+    method public default void onDescendantInvalidated(android.view.View, android.view.View);
     method public abstract boolean onNestedFling(android.view.View, float, float, boolean);
     method public abstract boolean onNestedPreFling(android.view.View, float, float);
     method public abstract boolean onNestedPrePerformAccessibilityAction(android.view.View, int, android.os.Bundle);
@@ -49338,8 +49343,6 @@
     method public void addHeaderView(android.view.View);
     method public boolean areFooterDividersEnabled();
     method public boolean areHeaderDividersEnabled();
-    method protected android.view.View findViewTraversal(int);
-    method protected android.view.View findViewWithTagTraversal(java.lang.Object);
     method public android.widget.ListAdapter getAdapter();
     method public deprecated long[] getCheckItemIds();
     method public android.graphics.drawable.Drawable getDivider();
diff --git a/cmds/screencap/screencap.cpp b/cmds/screencap/screencap.cpp
index 377e29d..000420f 100644
--- a/cmds/screencap/screencap.cpp
+++ b/cmds/screencap/screencap.cpp
@@ -162,7 +162,9 @@
     uint8_t displayOrientation = configs[activeConfig].orientation;
     uint32_t captureOrientation = ORIENTATION_MAP[displayOrientation];
 
-    status_t result = screenshot.update(display, Rect(), 0, 0, 0, -1U,
+    status_t result = screenshot.update(display, Rect(),
+            0 /* reqWidth */, 0 /* reqHeight */,
+            INT32_MIN, INT32_MAX, /* all layers */
             false, captureOrientation);
     if (result == NO_ERROR) {
         base = screenshot.getPixels();
diff --git a/compiled-classes-phone b/compiled-classes-phone
index ed0a4a6..e4ffaa3 100644
--- a/compiled-classes-phone
+++ b/compiled-classes-phone
@@ -633,6 +633,7 @@
 android.bluetooth.BluetoothClass
 android.bluetooth.BluetoothClass$1
 android.bluetooth.BluetoothCodecConfig
+android.bluetooth.BluetoothCodecStatus
 android.bluetooth.BluetoothDevice
 android.bluetooth.BluetoothDevice$1
 android.bluetooth.BluetoothDevice$2
diff --git a/core/java/android/app/BackStackRecord.java b/core/java/android/app/BackStackRecord.java
index 20a9a93..a27775e 100644
--- a/core/java/android/app/BackStackRecord.java
+++ b/core/java/android/app/BackStackRecord.java
@@ -186,6 +186,8 @@
     static final int OP_SHOW = 5;
     static final int OP_DETACH = 6;
     static final int OP_ATTACH = 7;
+    static final int OP_SET_PRIMARY_NAV = 8;
+    static final int OP_UNSET_PRIMARY_NAV = 9;
 
     static final class Op {
         int cmd;
@@ -194,6 +196,14 @@
         int exitAnim;
         int popEnterAnim;
         int popExitAnim;
+
+        Op() {
+        }
+
+        Op(int cmd, Fragment fragment) {
+            this.cmd = cmd;
+            this.fragment = fragment;
+        }
     }
 
     ArrayList<Op> mOps = new ArrayList<>();
@@ -318,6 +328,13 @@
                     case OP_ATTACH:
                         cmdStr = "ATTACH";
                         break;
+                    case OP_SET_PRIMARY_NAV:
+                        cmdStr="SET_PRIMARY_NAV";
+                        break;
+                    case OP_UNSET_PRIMARY_NAV:
+                        cmdStr="UNSET_PRIMARY_NAV";
+                        break;
+
                     default:
                         cmdStr = "cmd=" + op.cmd;
                         break;
@@ -438,10 +455,7 @@
             fragment.mContainerId = fragment.mFragmentId = containerViewId;
         }
 
-        Op op = new Op();
-        op.cmd = opcmd;
-        op.fragment = fragment;
-        addOp(op);
+        addOp(new Op(opcmd, fragment));
     }
 
     public FragmentTransaction replace(int containerViewId, Fragment fragment) {
@@ -458,46 +472,37 @@
     }
 
     public FragmentTransaction remove(Fragment fragment) {
-        Op op = new Op();
-        op.cmd = OP_REMOVE;
-        op.fragment = fragment;
-        addOp(op);
+        addOp(new Op(OP_REMOVE, fragment));
 
         return this;
     }
 
     public FragmentTransaction hide(Fragment fragment) {
-        Op op = new Op();
-        op.cmd = OP_HIDE;
-        op.fragment = fragment;
-        addOp(op);
+        addOp(new Op(OP_HIDE, fragment));
 
         return this;
     }
 
     public FragmentTransaction show(Fragment fragment) {
-        Op op = new Op();
-        op.cmd = OP_SHOW;
-        op.fragment = fragment;
-        addOp(op);
+        addOp(new Op(OP_SHOW, fragment));
 
         return this;
     }
 
     public FragmentTransaction detach(Fragment fragment) {
-        Op op = new Op();
-        op.cmd = OP_DETACH;
-        op.fragment = fragment;
-        addOp(op);
+        addOp(new Op(OP_DETACH, fragment));
 
         return this;
     }
 
     public FragmentTransaction attach(Fragment fragment) {
-        Op op = new Op();
-        op.cmd = OP_ATTACH;
-        op.fragment = fragment;
-        addOp(op);
+        addOp(new Op(OP_ATTACH, fragment));
+
+        return this;
+    }
+
+    public FragmentTransaction setPrimaryNavigationFragment(Fragment fragment) {
+        addOp(new Op(OP_SET_PRIMARY_NAV, fragment));
 
         return this;
     }
@@ -689,7 +694,8 @@
         final int numOps = mOps.size();
         for (int opNum = 0; opNum < numOps; opNum++) {
             final Op op = mOps.get(opNum);
-            if (op.fragment.mContainerId == containerId) {
+            final int fragContainer = op.fragment != null ? op.fragment.mContainerId : 0;
+            if (fragContainer != 0 && fragContainer == containerId) {
                 return true;
             }
         }
@@ -704,7 +710,7 @@
         int lastContainer = -1;
         for (int opNum = 0; opNum < numOps; opNum++) {
             final Op op = mOps.get(opNum);
-            final int container = op.fragment.mContainerId;
+            final int container = op.fragment != null ? op.fragment.mContainerId : 0;
             if (container != 0 && container != lastContainer) {
                 lastContainer = container;
                 for (int i = startIndex; i < endIndex; i++) {
@@ -712,7 +718,9 @@
                     final int numThoseOps = record.mOps.size();
                     for (int thoseOpIndex = 0; thoseOpIndex < numThoseOps; thoseOpIndex++) {
                         final Op thatOp = record.mOps.get(thoseOpIndex);
-                        if (thatOp.fragment.mContainerId == container) {
+                        final int thatContainer = thatOp.fragment != null
+                                ? thatOp.fragment.mContainerId : 0;
+                        if (thatContainer == container) {
                             return true;
                         }
                     }
@@ -731,7 +739,9 @@
         for (int opNum = 0; opNum < numOps; opNum++) {
             final Op op = mOps.get(opNum);
             final Fragment f = op.fragment;
-            f.setNextTransition(mTransition, mTransitionStyle);
+            if (f != null) {
+                f.setNextTransition(mTransition, mTransitionStyle);
+            }
             switch (op.cmd) {
                 case OP_ADD:
                     f.setNextAnim(op.enterAnim);
@@ -757,10 +767,16 @@
                     f.setNextAnim(op.enterAnim);
                     mManager.attachFragment(f);
                     break;
+                case OP_SET_PRIMARY_NAV:
+                    mManager.setPrimaryNavigationFragment(f);
+                    break;
+                case OP_UNSET_PRIMARY_NAV:
+                    mManager.setPrimaryNavigationFragment(null);
+                    break;
                 default:
                     throw new IllegalArgumentException("Unknown cmd: " + op.cmd);
             }
-            if (!mAllowOptimization && op.cmd != OP_ADD) {
+            if (!mAllowOptimization && op.cmd != OP_ADD && f != null) {
                 mManager.moveFragmentToExpectedState(f);
             }
         }
@@ -778,7 +794,10 @@
         for (int opNum = mOps.size() - 1; opNum >= 0; opNum--) {
             final Op op = mOps.get(opNum);
             Fragment f = op.fragment;
-            f.setNextTransition(FragmentManagerImpl.reverseTransit(mTransition), mTransitionStyle);
+            if (f != null) {
+                f.setNextTransition(FragmentManagerImpl.reverseTransit(mTransition),
+                        mTransitionStyle);
+            }
             switch (op.cmd) {
                 case OP_ADD:
                     f.setNextAnim(op.popExitAnim);
@@ -804,10 +823,16 @@
                     f.setNextAnim(op.popExitAnim);
                     mManager.detachFragment(f);
                     break;
+                case OP_SET_PRIMARY_NAV:
+                    mManager.setPrimaryNavigationFragment(null);
+                    break;
+                case OP_UNSET_PRIMARY_NAV:
+                    mManager.setPrimaryNavigationFragment(f);
+                    break;
                 default:
                     throw new IllegalArgumentException("Unknown cmd: " + op.cmd);
             }
-            if (!mAllowOptimization && op.cmd != OP_REMOVE) {
+            if (!mAllowOptimization && op.cmd != OP_REMOVE && f != null) {
                 mManager.moveFragmentToExpectedState(f);
             }
         }
@@ -817,15 +842,28 @@
     }
 
     /**
-     * Removes all OP_REPLACE ops and replaces them with the proper add and remove
-     * operations that are equivalent to the replace. This must be called prior to
-     * {@link #executeOps()} or any other call that operations on mOps.
+     * Expands all meta-ops into their more primitive equivalents. This must be called prior to
+     * {@link #executeOps()} or any other call that operations on mOps for forward navigation.
+     * It should not be called for pop/reverse navigation operations.
+     *
+     * <p>Removes all OP_REPLACE ops and replaces them with the proper add and remove
+     * operations that are equivalent to the replace.</p>
+     *
+     * <p>Adds OP_UNSET_PRIMARY_NAV ops to match OP_SET_PRIMARY_NAV, OP_REMOVE and OP_DETACH
+     * ops so that we can restore the old primary nav fragment later. Since callers call this
+     * method in a loop before running ops from several transactions at once, the caller should
+     * pass the return value from this method as the oldPrimaryNav parameter for the next call.
+     * The first call in such a loop should pass the value of
+     * {@link FragmentManager#getPrimaryNavigationFragment()}.</p>
      *
      * @param added Initialized to the fragments that are in the mManager.mAdded, this
      *              will be modified to contain the fragments that will be in mAdded
      *              after the execution ({@link #executeOps()}.
+     * @param oldPrimaryNav The tracked primary navigation fragment as of the beginning of
+     *                      this set of ops
+     * @return the new oldPrimaryNav fragment after this record's ops would be run
      */
-    void expandReplaceOps(ArrayList<Fragment> added) {
+    Fragment expandOps(ArrayList<Fragment> added, Fragment oldPrimaryNav) {
         for (int opNum = 0; opNum < mOps.size(); opNum++) {
             final Op op = mOps.get(opNum);
             switch (op.cmd) {
@@ -834,22 +872,33 @@
                     added.add(op.fragment);
                     break;
                 case OP_REMOVE:
-                case OP_DETACH:
+                case OP_DETACH: {
                     added.remove(op.fragment);
-                    break;
+                    if (op.fragment == oldPrimaryNav) {
+                        mOps.add(opNum, new Op(OP_UNSET_PRIMARY_NAV, op.fragment));
+                        opNum++;
+                        oldPrimaryNav = null;
+                    }
+                }
+                break;
                 case OP_REPLACE: {
-                    Fragment f = op.fragment;
-                    int containerId = f.mContainerId;
+                    final Fragment f = op.fragment;
+                    final int containerId = f.mContainerId;
                     boolean alreadyAdded = false;
                     for (int i = added.size() - 1; i >= 0; i--) {
-                        Fragment old = added.get(i);
+                        final Fragment old = added.get(i);
                         if (old.mContainerId == containerId) {
                             if (old == f) {
                                 alreadyAdded = true;
                             } else {
-                                Op removeOp = new Op();
-                                removeOp.cmd = OP_REMOVE;
-                                removeOp.fragment = old;
+                                // This is duplicated from above since we only make
+                                // a single pass for expanding ops. Unset any outgoing primary nav.
+                                if (old == oldPrimaryNav) {
+                                    mOps.add(opNum, new Op(OP_UNSET_PRIMARY_NAV, old));
+                                    opNum++;
+                                    oldPrimaryNav = null;
+                                }
+                                final Op removeOp = new Op(OP_REMOVE, old);
                                 removeOp.enterAnim = op.enterAnim;
                                 removeOp.popEnterAnim = op.popEnterAnim;
                                 removeOp.exitAnim = op.exitAnim;
@@ -869,8 +918,18 @@
                     }
                 }
                 break;
+                case OP_SET_PRIMARY_NAV: {
+                    // It's ok if this is null, that means we will restore to no active
+                    // primary navigation fragment on a pop.
+                    mOps.add(opNum, new Op(OP_UNSET_PRIMARY_NAV, oldPrimaryNav));
+                    opNum++;
+                    // Will be set by the OP_SET_PRIMARY_NAV we inserted before when run
+                    oldPrimaryNav = op.fragment;
+                }
+                break;
             }
         }
+        return oldPrimaryNav;
     }
 
     /**
@@ -917,8 +976,8 @@
 
     private static boolean isFragmentPostponed(Op op) {
         final Fragment fragment = op.fragment;
-        return (fragment.mAdded && fragment.mView != null && !fragment.mDetached &&
-                !fragment.mHidden && fragment.isPostponed());
+        return fragment != null && fragment.mAdded && fragment.mView != null && !fragment.mDetached
+                && !fragment.mHidden && fragment.isPostponed();
     }
 
     public String getName() {
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index 32cf1c3..b0150bd 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -360,6 +360,18 @@
     public abstract void unregisterFragmentLifecycleCallbacks(FragmentLifecycleCallbacks cb);
 
     /**
+     * Return the currently active primary navigation fragment for this FragmentManager.
+     *
+     * <p>The primary navigation fragment's
+     * {@link Fragment#getChildFragmentManager() child FragmentManager} will be called first
+     * to process delegated navigation actions such as {@link #popBackStack()} if no ID
+     * or transaction name is provided to pop to.</p>
+     *
+     * @return the fragment designated as the primary navigation fragment
+     */
+    public abstract Fragment getPrimaryNavigationFragment();
+
+    /**
      * Print the FragmentManager's state into the given stream.
      *
      * @param prefix Text to print at the front of each line.
@@ -524,6 +536,7 @@
     FragmentState[] mActive;
     int[] mAdded;
     BackStackState[] mBackStack;
+    int mPrimaryNavActiveIndex = -1;
     
     public FragmentManagerState() {
     }
@@ -532,6 +545,7 @@
         mActive = in.createTypedArray(FragmentState.CREATOR);
         mAdded = in.createIntArray();
         mBackStack = in.createTypedArray(BackStackState.CREATOR);
+        mPrimaryNavActiveIndex = in.readInt();
     }
     
     public int describeContents() {
@@ -542,6 +556,7 @@
         dest.writeTypedArray(mActive, flags);
         dest.writeIntArray(mAdded);
         dest.writeTypedArray(mBackStack, flags);
+        dest.writeInt(mPrimaryNavActiveIndex);
     }
     
     public static final Parcelable.Creator<FragmentManagerState> CREATOR
@@ -626,6 +641,7 @@
     FragmentHostCallback<?> mHost;
     FragmentContainer mContainer;
     Fragment mParent;
+    Fragment mPrimaryNav;
     
     boolean mNeedMenuInvalidate;
     boolean mStateSaved;
@@ -783,6 +799,16 @@
         execPendingActions();
         ensureExecReady(true);
 
+        if (mPrimaryNav != null // We have a primary nav fragment
+                && id < 0 // No valid id (since they're local)
+                && name == null) { // no name to pop to (since they're local)
+            final FragmentManager childManager = mPrimaryNav.mChildFragmentManager;
+            if (childManager != null && childManager.popBackStackImmediate()) {
+                // We did something, just not to this specific FragmentManager. Return true.
+                return true;
+            }
+        }
+
         boolean executePop = popBackStackState(mTmpRecords, mTmpIsPop, name, id, flags);
         if (executePop) {
             mExecutingActions = true;
@@ -2038,11 +2064,12 @@
         if (mAdded != null) {
             mTmpAddedFragments.addAll(mAdded);
         }
+        Fragment oldPrimaryNav = getPrimaryNavigationFragment();
         for (int recordNum = startIndex; recordNum < endIndex; recordNum++) {
             final BackStackRecord record = records.get(recordNum);
             final boolean isPop = isRecordPop.get(recordNum);
             if (!isPop) {
-                record.expandReplaceOps(mTmpAddedFragments);
+                oldPrimaryNav = record.expandOps(mTmpAddedFragments, oldPrimaryNav);
             } else {
                 record.trackAddedFragmentsInPop(mTmpAddedFragments);
             }
@@ -2318,20 +2345,20 @@
      */
     private boolean generateOpsForPendingActions(ArrayList<BackStackRecord> records,
             ArrayList<Boolean> isPop) {
-        int numActions;
+        boolean didSomething = false;
         synchronized (this) {
             if (mPendingActions == null || mPendingActions.size() == 0) {
                 return false;
             }
 
-            numActions = mPendingActions.size();
+            final int numActions = mPendingActions.size();
             for (int i = 0; i < numActions; i++) {
-                mPendingActions.get(i).generateOps(records, isPop);
+                didSomething |= mPendingActions.get(i).generateOps(records, isPop);
             }
             mPendingActions.clear();
             mHost.getHandler().removeCallbacks(mExecCommit);
         }
-        return numActions > 0;
+        return didSomething;
     }
 
     void doPendingDeferredStart() {
@@ -2618,6 +2645,9 @@
         fms.mActive = active;
         fms.mAdded = added;
         fms.mBackStack = backStack;
+        if (mPrimaryNav != null) {
+            fms.mPrimaryNavActiveIndex = mPrimaryNav.mIndex;
+        }
         return fms;
     }
     
@@ -2744,6 +2774,10 @@
         } else {
             mBackStack = null;
         }
+
+        if (fms.mPrimaryNavActiveIndex >= 0) {
+            mPrimaryNav = mActive.get(fms.mPrimaryNavActiveIndex);
+        }
     }
     
     public void attachController(FragmentHostCallback<?> host, FragmentContainer container,
@@ -2942,6 +2976,19 @@
         }
     }
 
+    public void setPrimaryNavigationFragment(Fragment f) {
+        if (f != null && (f.getFragmentManager() != this || f.mIndex >= mActive.size()
+                || mActive.get(f.mIndex) != f)) {
+            throw new IllegalArgumentException("Fragment " + f
+                    + " is not an active fragment of FragmentManager " + this);
+        }
+        mPrimaryNav = f;
+    }
+
+    public Fragment getPrimaryNavigationFragment() {
+        return mPrimaryNav;
+    }
+
     public void registerFragmentLifecycleCallbacks(FragmentLifecycleCallbacks cb,
             boolean recursive) {
         if (mLifecycleCallbacks == null) {
@@ -3386,6 +3433,16 @@
         @Override
         public boolean generateOps(ArrayList<BackStackRecord> records,
                 ArrayList<Boolean> isRecordPop) {
+            if (mPrimaryNav != null // We have a primary nav fragment
+                    && mId < 0 // No valid id (since they're local)
+                    && mName == null) { // no name to pop to (since they're local)
+                final FragmentManager childManager = mPrimaryNav.mChildFragmentManager;
+                if (childManager != null && childManager.popBackStackImmediate()) {
+                    // We didn't add any operations for this FragmentManager even though
+                    // a child did do work.
+                    return false;
+                }
+            }
             return popBackStackState(records, isRecordPop, mName, mId, mFlags);
         }
     }
diff --git a/core/java/android/app/FragmentTransaction.java b/core/java/android/app/FragmentTransaction.java
index 25a7839..07a313c 100644
--- a/core/java/android/app/FragmentTransaction.java
+++ b/core/java/android/app/FragmentTransaction.java
@@ -132,6 +132,24 @@
     public abstract FragmentTransaction attach(Fragment fragment);
 
     /**
+     * Set a currently active fragment in this FragmentManager as the primary navigation fragment.
+     *
+     * <p>The primary navigation fragment's
+     * {@link Fragment#getChildFragmentManager() child FragmentManager} will be called first
+     * to process delegated navigation actions such as {@link FragmentManager#popBackStack()}
+     * if no ID or transaction name is provided to pop to. Navigation operations outside of the
+     * fragment system may choose to delegate those actions to the primary navigation fragment
+     * as returned by {@link FragmentManager#getPrimaryNavigationFragment()}.</p>
+     *
+     * <p>The fragment provided must currently be added to the FragmentManager to be set as
+     * a primary navigation fragment, or previously added as part of this transaction.</p>
+     *
+     * @param fragment the fragment to set as the primary navigation fragment
+     * @return the same FragmentTransaction instance
+     */
+    public abstract FragmentTransaction setPrimaryNavigationFragment(Fragment fragment);
+
+    /**
      * @return <code>true</code> if this transaction contains no operations,
      * <code>false</code> otherwise.
      */
diff --git a/core/java/android/app/FragmentTransition.java b/core/java/android/app/FragmentTransition.java
index 80a5aac..2570d92 100644
--- a/core/java/android/app/FragmentTransition.java
+++ b/core/java/android/app/FragmentTransition.java
@@ -43,14 +43,16 @@
      * REPLACE operations have already been replaced by add/remove operations.
      */
     private static final int[] INVERSE_OPS = {
-            BackStackRecord.OP_NULL,   // inverse of OP_NULL (error)
-            BackStackRecord.OP_REMOVE, // inverse of OP_ADD
-            BackStackRecord.OP_NULL,   // inverse of OP_REPLACE (error)
-            BackStackRecord.OP_ADD,    // inverse of OP_REMOVE
-            BackStackRecord.OP_SHOW,   // inverse of OP_HIDE
-            BackStackRecord.OP_HIDE,   // inverse of OP_SHOW
-            BackStackRecord.OP_ATTACH, // inverse of OP_DETACH
-            BackStackRecord.OP_DETACH, // inverse of OP_ATTACH
+            BackStackRecord.OP_NULL,              // inverse of OP_NULL (error)
+            BackStackRecord.OP_REMOVE,            // inverse of OP_ADD
+            BackStackRecord.OP_NULL,              // inverse of OP_REPLACE (error)
+            BackStackRecord.OP_ADD,               // inverse of OP_REMOVE
+            BackStackRecord.OP_SHOW,              // inverse of OP_HIDE
+            BackStackRecord.OP_HIDE,              // inverse of OP_SHOW
+            BackStackRecord.OP_ATTACH,            // inverse of OP_DETACH
+            BackStackRecord.OP_DETACH,            // inverse of OP_ATTACH
+            BackStackRecord.OP_UNSET_PRIMARY_NAV, // inverse of OP_SET_PRIMARY_NAV
+            BackStackRecord.OP_SET_PRIMARY_NAV,   // inverse of OP_UNSET_PRIMARY_NAV
     };
 
     /**
@@ -1232,6 +1234,9 @@
             SparseArray<FragmentContainerTransition> transitioningFragments, boolean isPop,
             boolean isOptimizedTransaction) {
         final Fragment fragment = op.fragment;
+        if (fragment == null) {
+            return; // no fragment, no transition
+        }
         final int containerId = fragment.mContainerId;
         if (containerId == 0) {
             return; // no container, no transition
diff --git a/core/java/android/bluetooth/BluetoothA2dp.java b/core/java/android/bluetooth/BluetoothA2dp.java
index 1ce8007..6e31d80 100644
--- a/core/java/android/bluetooth/BluetoothA2dp.java
+++ b/core/java/android/bluetooth/BluetoothA2dp.java
@@ -106,10 +106,9 @@
      * Intent used to broadcast the change in the Audio Codec state of the
      * A2DP Source profile.
      *
-     * <p>This intent will have 3 extras:
+     * <p>This intent will have 2 extras:
      * <ul>
-     *   <li> {@link #EXTRA_CODEC_CONFIG} - The current codec configuration. </li>
-     *   <li> {@link #EXTRA_PREVIOUS_CODEC_CONFIG} - The previous codec configuration. </li>
+     *   <li> {@link BluetoothCodecStatus#EXTRA_CODEC_STATUS} - The codec status. </li>
      *   <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device if the device is currently
      *   connected, otherwise it is not included.</li>
      * </ul>
@@ -565,24 +564,24 @@
     }
 
     /**
-     * Gets the current codec configuration.
+     * Gets the current codec status (configuration and capability).
      *
-     * @return the current codec configuration
+     * @return the current codec status
      * @hide
      */
-    public BluetoothCodecConfig getCodecConfig() {
-        if (DBG) Log.d(TAG, "getCodecConfig");
+    public BluetoothCodecStatus getCodecStatus() {
+        if (DBG) Log.d(TAG, "getCodecStatus");
         try {
             mServiceLock.readLock().lock();
             if (mService != null && isEnabled()) {
-                return mService.getCodecConfig();
+                return mService.getCodecStatus();
             }
             if (mService == null) {
                 Log.w(TAG, "Proxy not attached to service");
             }
             return null;
         } catch (RemoteException e) {
-            Log.e(TAG, "Error talking to BT service in getCodecConfig()", e);
+            Log.e(TAG, "Error talking to BT service in getCodecStatus()", e);
             return null;
         } finally {
             mServiceLock.readLock().unlock();
diff --git a/core/java/android/bluetooth/BluetoothCodecConfig.java b/core/java/android/bluetooth/BluetoothCodecConfig.java
index a37a0b3..a482103 100644
--- a/core/java/android/bluetooth/BluetoothCodecConfig.java
+++ b/core/java/android/bluetooth/BluetoothCodecConfig.java
@@ -29,24 +29,6 @@
  * {@hide}
  */
 public final class BluetoothCodecConfig implements Parcelable {
-
-    /**
-     * Extra for the codec configuration intents of the individual profiles.
-     *
-     * This extra represents the current codec configuration of the A2DP
-     * profile.
-     */
-    public static final String EXTRA_CODEC_CONFIG = "android.bluetooth.codec.extra.CODEC_CONFIG";
-
-    /**
-     * Extra for the codec configuration intents of the individual profiles.
-     *
-     * This extra represents the previous codec configuration of the A2DP
-     * profile.
-     */
-    public static final String EXTRA_PREVIOUS_CODEC_CONFIG =
-        "android.bluetooth.codec.extra.PREVIOUS_CODEC_CONFIG";
-
     // Add an entry for each source codec here.
     // NOTE: The values should be same as those listed in the following file:
     //   hardware/libhardware/include/hardware/bt_av.h
@@ -128,13 +110,93 @@
                             mCodecSpecific2, mCodecSpecific3, mCodecSpecific4);
     }
 
+    /**
+     * Checks whether the object contains valid codec configuration.
+     *
+     * @return true if the object contains valid codec configuration,
+     * otherwise false.
+     */
+    public boolean isValid() {
+        return (mSampleRate != SAMPLE_RATE_NONE) &&
+            (mBitsPerSample != BITS_PER_SAMPLE_NONE) &&
+            (mChannelMode != CHANNEL_MODE_NONE);
+    }
+
+    /**
+     * Adds capability string to an existing string.
+     *
+     * @param prevStr the previous string with the capabilities. Can be
+     * a null pointer.
+     * @param capStr the capability string to append to prevStr argument.
+     * @return the result string in the form "prevStr|capStr".
+     */
+    private static String appendCapabilityToString(String prevStr,
+                                                   String capStr) {
+        if (prevStr == null) {
+            return capStr;
+        }
+        return prevStr + "|" + capStr;
+    }
+
     @Override
     public String toString() {
-        return "{mCodecType:" + mCodecType +
+        String sampleRateStr = null;
+        if (mSampleRate == SAMPLE_RATE_NONE) {
+            sampleRateStr = appendCapabilityToString(sampleRateStr, "NONE");
+        }
+        if ((mSampleRate & SAMPLE_RATE_44100) != 0) {
+            sampleRateStr = appendCapabilityToString(sampleRateStr, "44100");
+        }
+        if ((mSampleRate & SAMPLE_RATE_48000) != 0) {
+            sampleRateStr = appendCapabilityToString(sampleRateStr, "48000");
+        }
+        if ((mSampleRate & SAMPLE_RATE_88200) != 0) {
+            sampleRateStr = appendCapabilityToString(sampleRateStr, "88200");
+        }
+        if ((mSampleRate & SAMPLE_RATE_96000) != 0) {
+            sampleRateStr = appendCapabilityToString(sampleRateStr, "96000");
+        }
+        if ((mSampleRate & SAMPLE_RATE_176400) != 0) {
+            sampleRateStr = appendCapabilityToString(sampleRateStr, "176400");
+        }
+        if ((mSampleRate & SAMPLE_RATE_192000) != 0) {
+            sampleRateStr = appendCapabilityToString(sampleRateStr, "192000");
+        }
+
+        String bitsPerSampleStr = null;
+        if (mBitsPerSample == BITS_PER_SAMPLE_NONE) {
+            bitsPerSampleStr = appendCapabilityToString(bitsPerSampleStr, "NONE");
+        }
+        if ((mBitsPerSample & BITS_PER_SAMPLE_16) != 0) {
+            bitsPerSampleStr = appendCapabilityToString(bitsPerSampleStr, "16");
+        }
+        if ((mBitsPerSample & BITS_PER_SAMPLE_24) != 0) {
+            bitsPerSampleStr = appendCapabilityToString(bitsPerSampleStr, "24");
+        }
+        if ((mBitsPerSample & BITS_PER_SAMPLE_32) != 0) {
+            bitsPerSampleStr = appendCapabilityToString(bitsPerSampleStr, "32");
+        }
+
+        String channelModeStr = null;
+        if (mChannelMode == CHANNEL_MODE_NONE) {
+            channelModeStr = appendCapabilityToString(channelModeStr, "NONE");
+        }
+        if ((mChannelMode & CHANNEL_MODE_MONO) != 0) {
+            channelModeStr = appendCapabilityToString(channelModeStr, "MONO");
+        }
+        if ((mChannelMode & CHANNEL_MODE_STEREO) != 0) {
+            channelModeStr = appendCapabilityToString(channelModeStr, "STEREO");
+        }
+
+        return "{codecName:" + getCodecName() +
+            ",mCodecType:" + mCodecType +
             ",mCodecPriority:" + mCodecPriority +
             ",mSampleRate:" + String.format("0x%x", mSampleRate) +
+            "(" + sampleRateStr + ")" +
             ",mBitsPerSample:" + String.format("0x%x", mBitsPerSample) +
+            "(" + bitsPerSampleStr + ")" +
             ",mChannelMode:" + String.format("0x%x", mChannelMode) +
+            "(" + channelModeStr + ")" +
             ",mCodecSpecific1:" + mCodecSpecific1 +
             ",mCodecSpecific2:" + mCodecSpecific2 +
             ",mCodecSpecific3:" + mCodecSpecific3 +
@@ -181,7 +243,32 @@
     }
 
     /**
-     * Returns the codec type.
+     * Gets the codec name.
+     *
+     * @return the codec name
+     */
+    public String getCodecName() {
+        switch (mCodecType) {
+        case SOURCE_CODEC_TYPE_SBC:
+            return "SBC";
+        case SOURCE_CODEC_TYPE_AAC:
+            return "AAC";
+        case SOURCE_CODEC_TYPE_APTX:
+            return "aptX";
+        case SOURCE_CODEC_TYPE_APTX_HD:
+            return "aptX HD";
+        case SOURCE_CODEC_TYPE_LDAC:
+            return "LDAC";
+        case SOURCE_CODEC_TYPE_INVALID:
+            return "INVALID CODEC";
+        default:
+            break;
+        }
+        return "UNKNOWN CODEC(" + mCodecType + ")";
+    }
+
+    /**
+     * Gets the codec type.
      * See {@link android.bluetooth.BluetoothCodecConfig#SOURCE_CODEC_TYPE_SBC}.
      *
      * @return the codec type
@@ -191,7 +278,7 @@
     }
 
     /**
-     * Returns the codec selection priority.
+     * Gets the codec selection priority.
      * The codec selection priority is relative to other codecs: larger value
      * means higher priority. If 0, reset to default.
      *
@@ -202,7 +289,7 @@
     }
 
     /**
-     * Returns the codec sample rate. The value can be a bitmask with all
+     * Gets the codec sample rate. The value can be a bitmask with all
      * supported sample rates:
      * {@link android.bluetooth.BluetoothCodecConfig#SAMPLE_RATE_NONE} or
      * {@link android.bluetooth.BluetoothCodecConfig#SAMPLE_RATE_44100} or
@@ -219,7 +306,7 @@
     }
 
     /**
-     * Returns the codec bits per sample. The value can be a bitmask with all
+     * Gets the codec bits per sample. The value can be a bitmask with all
      * bits per sample supported:
      * {@link android.bluetooth.BluetoothCodecConfig#BITS_PER_SAMPLE_NONE} or
      * {@link android.bluetooth.BluetoothCodecConfig#BITS_PER_SAMPLE_16} or
@@ -233,7 +320,7 @@
     }
 
     /**
-     * Returns the codec channel mode. The value can be a bitmask with all
+     * Gets the codec channel mode. The value can be a bitmask with all
      * supported channel modes:
      * {@link android.bluetooth.BluetoothCodecConfig#CHANNEL_MODE_NONE} or
      * {@link android.bluetooth.BluetoothCodecConfig#CHANNEL_MODE_MONO} or
@@ -246,7 +333,7 @@
     }
 
     /**
-     * Returns a codec specific value1.
+     * Gets a codec specific value1.
      *
      * @return a codec specific value1.
      */
@@ -255,7 +342,7 @@
     }
 
     /**
-     * Returns a codec specific value2.
+     * Gets a codec specific value2.
      *
      * @return a codec specific value2
      */
@@ -264,7 +351,7 @@
     }
 
     /**
-     * Returns a codec specific value3.
+     * Gets a codec specific value3.
      *
      * @return a codec specific value3
      */
@@ -273,7 +360,7 @@
     }
 
     /**
-     * Returns a codec specific value4.
+     * Gets a codec specific value4.
      *
      * @return a codec specific value4
      */
diff --git a/core/java/android/bluetooth/BluetoothCodecStatus.aidl b/core/java/android/bluetooth/BluetoothCodecStatus.aidl
new file mode 100644
index 0000000..f9c3a3d
--- /dev/null
+++ b/core/java/android/bluetooth/BluetoothCodecStatus.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2017 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.bluetooth;
+
+parcelable BluetoothCodecStatus;
diff --git a/core/java/android/bluetooth/BluetoothCodecStatus.java b/core/java/android/bluetooth/BluetoothCodecStatus.java
new file mode 100644
index 0000000..c8cd8d1
--- /dev/null
+++ b/core/java/android/bluetooth/BluetoothCodecStatus.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2017 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.bluetooth;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Arrays;
+import java.util.Objects;
+
+/**
+ * Represents the codec status (configuration and capability) for a Bluetooth
+ * A2DP source device.
+ *
+ * {@see BluetoothA2dp}
+ *
+ * {@hide}
+ */
+public final class BluetoothCodecStatus implements Parcelable {
+    /**
+     * Extra for the codec configuration intents of the individual profiles.
+     *
+     * This extra represents the current codec status of the A2DP
+     * profile.
+     */
+    public static final String EXTRA_CODEC_STATUS =
+        "android.bluetooth.codec.extra.CODEC_STATUS";
+
+    private final BluetoothCodecConfig mCodecConfig;
+    private final BluetoothCodecConfig[] mCodecsLocalCapabilities;
+    private final BluetoothCodecConfig[] mCodecsSelectableCapabilities;
+
+    public BluetoothCodecStatus(BluetoothCodecConfig codecConfig,
+                                BluetoothCodecConfig[] codecsLocalCapabilities,
+                                BluetoothCodecConfig[] codecsSelectableCapabilities) {
+        mCodecConfig = codecConfig;
+        mCodecsLocalCapabilities = codecsLocalCapabilities;
+        mCodecsSelectableCapabilities = codecsSelectableCapabilities;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (o instanceof BluetoothCodecStatus) {
+            BluetoothCodecStatus other = (BluetoothCodecStatus)o;
+            return (Objects.equals(other.mCodecConfig, mCodecConfig) &&
+                    Objects.equals(other.mCodecsLocalCapabilities,
+                                   mCodecsLocalCapabilities) &&
+                    Objects.equals(other.mCodecsSelectableCapabilities,
+                                   mCodecsSelectableCapabilities));
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mCodecConfig, mCodecsLocalCapabilities,
+                            mCodecsLocalCapabilities);
+    }
+
+    @Override
+    public String toString() {
+        return "{mCodecConfig:" + mCodecConfig +
+            ",mCodecsLocalCapabilities:" + Arrays.toString(mCodecsLocalCapabilities) +
+            ",mCodecsSelectableCapabilities:" + Arrays.toString(mCodecsSelectableCapabilities) +
+            "}";
+    }
+
+    public int describeContents() {
+        return 0;
+    }
+
+    public static final Parcelable.Creator<BluetoothCodecStatus> CREATOR =
+            new Parcelable.Creator<BluetoothCodecStatus>() {
+        public BluetoothCodecStatus createFromParcel(Parcel in) {
+            final BluetoothCodecConfig codecConfig = in.readTypedObject(BluetoothCodecConfig.CREATOR);
+            final BluetoothCodecConfig[] codecsLocalCapabilities = in.createTypedArray(BluetoothCodecConfig.CREATOR);
+            final BluetoothCodecConfig[] codecsSelectableCapabilities = in.createTypedArray(BluetoothCodecConfig.CREATOR);
+
+            return new BluetoothCodecStatus(codecConfig,
+                                            codecsLocalCapabilities,
+                                            codecsSelectableCapabilities);
+        }
+        public BluetoothCodecStatus[] newArray(int size) {
+            return new BluetoothCodecStatus[size];
+        }
+    };
+
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeTypedObject(mCodecConfig, 0);
+        out.writeTypedArray(mCodecsLocalCapabilities, 0);
+        out.writeTypedArray(mCodecsSelectableCapabilities, 0);
+    }
+
+    /**
+     * Gets the current codec configuration.
+     *
+     * @return the current codec configuration
+     */
+    public BluetoothCodecConfig getCodecConfig() {
+        return mCodecConfig;
+    }
+
+    /**
+     * Gets the codecs local capabilities.
+     *
+     * @return an array with the codecs local capabilities
+     */
+    public BluetoothCodecConfig[] getCodecsLocalCapabilities() {
+        return mCodecsLocalCapabilities;
+    }
+
+    /**
+     * Gets the codecs selectable capabilities.
+     *
+     * @return an array with the codecs selectable capabilities
+     */
+    public BluetoothCodecConfig[] getCodecsSelectableCapabilities() {
+        return mCodecsSelectableCapabilities;
+    }
+}
diff --git a/core/java/android/bluetooth/IBluetoothA2dp.aidl b/core/java/android/bluetooth/IBluetoothA2dp.aidl
index 5b524eb..dbb5b7d 100644
--- a/core/java/android/bluetooth/IBluetoothA2dp.aidl
+++ b/core/java/android/bluetooth/IBluetoothA2dp.aidl
@@ -17,6 +17,7 @@
 package android.bluetooth;
 
 import android.bluetooth.BluetoothCodecConfig;
+import android.bluetooth.BluetoothCodecStatus;
 import android.bluetooth.BluetoothDevice;
 
 /**
@@ -37,6 +38,6 @@
     oneway void adjustAvrcpAbsoluteVolume(int direction);
     oneway void setAvrcpAbsoluteVolume(int volume);
     boolean isA2dpPlaying(in BluetoothDevice device);
-    BluetoothCodecConfig getCodecConfig();
+    BluetoothCodecStatus getCodecStatus();
     oneway void setCodecConfigPreference(in BluetoothCodecConfig codecConfig);
 }
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 111b4d6..6a0da33 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -569,6 +569,7 @@
  *     <li> {@link #CATEGORY_HE_DESK_DOCK}
  *     <li> {@link #CATEGORY_CAR_MODE}
  *     <li> {@link #CATEGORY_APP_MARKET}
+ *     <li> {@link #CATEGORY_VR_HOME}
  * </ul>
  *
  * <h3>Standard Extra Data</h3>
@@ -3643,6 +3644,13 @@
     @SdkConstant(SdkConstantType.INTENT_CATEGORY)
     public static final String CATEGORY_CAR_MODE = "android.intent.category.CAR_MODE";
 
+    /**
+     * An activity to use for the launcher when the device is placed in a VR Headset viewer.
+     * Used with {@link #ACTION_MAIN} to launch an activity.  For more
+     * information, see {@link android.app.UiModeManager}.
+     */
+    @SdkConstant(SdkConstantType.INTENT_CATEGORY)
+    public static final String CATEGORY_VR_HOME = "android.intent.category.VR_HOME";
     // ---------------------------------------------------------------------
     // ---------------------------------------------------------------------
     // Application launch intent categories (see addCategory()).
diff --git a/core/java/android/content/pm/permission/IRuntimePermissionPresenter.aidl b/core/java/android/content/pm/permission/IRuntimePermissionPresenter.aidl
index 8766508..3c3b84d 100644
--- a/core/java/android/content/pm/permission/IRuntimePermissionPresenter.aidl
+++ b/core/java/android/content/pm/permission/IRuntimePermissionPresenter.aidl
@@ -25,5 +25,4 @@
  */
 oneway interface IRuntimePermissionPresenter {
     void getAppPermissions(String packageName, in RemoteCallback callback);
-    void getAppsUsingPermissions(boolean system, in RemoteCallback callback);
-}
\ No newline at end of file
+}
diff --git a/core/java/android/content/pm/permission/RuntimePermissionPresenter.java b/core/java/android/content/pm/permission/RuntimePermissionPresenter.java
index 2e39926..6d55d2f 100644
--- a/core/java/android/content/pm/permission/RuntimePermissionPresenter.java
+++ b/core/java/android/content/pm/permission/RuntimePermissionPresenter.java
@@ -72,15 +72,6 @@
                 List<RuntimePermissionPresentationInfo> permissions) {
             /* do nothing - stub */
         }
-
-        /**
-         * The result for {@link #getAppsUsingPermissions(boolean, List)}.
-         * @param system Whether to return only the system apps or only the non-system ones.
-         * @param apps The apps using runtime permissions.
-         */
-        public void getAppsUsingPermissions(boolean system, @NonNull List<ApplicationInfo> apps) {
-            /* do nothing - stub */
-        }
     }
 
     private static final Object sLock = new Object();
@@ -127,29 +118,6 @@
         mRemoteService.processMessage(message);
     }
 
-    /**
-     * Gets the system apps that use runtime permissions. System apps are ones
-     * that are considered system for presentation purposes instead of ones
-     * that are preinstalled on the system image. System apps are ones that
-     * are on the system image, haven't been updated (a.k.a factory apps)
-     * that do not have a launcher icon.
-     *
-     * @param system If true only system apps are returned otherwise only
-     *        non-system ones are returned.
-     * @param callback Callback to receive the result.
-     * @param handler Handler on which to invoke the callback.
-     */
-    public void getAppsUsingPermissions(boolean system, @NonNull OnResultCallback callback,
-            @Nullable Handler handler) {
-        SomeArgs args = SomeArgs.obtain();
-        args.arg1 = callback;
-        args.arg2 = handler;
-        args.argi1 = system ? 1 : 0;
-        Message message = mRemoteService.obtainMessage(
-                RemoteService.MSG_GET_APPS_USING_PERMISSIONS, args);
-        mRemoteService.processMessage(message);
-    }
-
     private static final class RemoteService
             extends Handler implements ServiceConnection {
         private static final long UNBIND_TIMEOUT_MILLIS = 10000;
@@ -254,51 +222,6 @@
                     scheduleUnbind();
                 } break;
 
-                case MSG_GET_APPS_USING_PERMISSIONS: {
-                    SomeArgs args = (SomeArgs) msg.obj;
-                    final OnResultCallback callback = (OnResultCallback) args.arg1;
-                    final Handler handler = (Handler) args.arg2;
-                    final boolean system = args.argi1 == 1;
-                    args.recycle();
-                    final IRuntimePermissionPresenter remoteInstance;
-                    synchronized (mLock) {
-                        remoteInstance = mRemoteInstance;
-                    }
-                    if (remoteInstance == null) {
-                        return;
-                    }
-                    try {
-                        remoteInstance.getAppsUsingPermissions(system, new RemoteCallback(
-                                new RemoteCallback.OnResultListener() {
-                            @Override
-                            public void onResult(Bundle result) {
-                                final List<ApplicationInfo> reportedApps;
-                                List<ApplicationInfo> apps = null;
-                                if (result != null) {
-                                    apps = result.getParcelableArrayList(KEY_RESULT);
-                                }
-                                if (apps == null) {
-                                    apps = Collections.emptyList();
-                                }
-                                reportedApps = apps;
-                                if (handler != null) {
-                                    handler.post(new Runnable() {
-                                        @Override
-                                        public void run() {
-                                            callback.getAppsUsingPermissions(system, reportedApps);
-                                        }
-                                    });
-                                } else {
-                                    callback.getAppsUsingPermissions(system, reportedApps);
-                                }
-                            }
-                        }, this));
-                    } catch (RemoteException re) {
-                        Log.e(TAG, "Error getting apps using permissions", re);
-                    }
-                    scheduleUnbind();
-                } break;
-
                 case MSG_UNBIND: {
                     synchronized (mLock) {
                         if (mBound) {
diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java
index a8822c5..ef5bc5c 100644
--- a/core/java/android/os/RecoverySystem.java
+++ b/core/java/android/os/RecoverySystem.java
@@ -623,7 +623,8 @@
         final ConditionVariable condition = new ConditionVariable();
 
         Intent intent = new Intent("android.intent.action.MASTER_CLEAR_NOTIFICATION");
-        intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+        intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND
+                | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
         context.sendOrderedBroadcastAsUser(intent, UserHandle.SYSTEM,
                 android.Manifest.permission.MASTER_CLEAR,
                 new BroadcastReceiver() {
diff --git a/core/java/android/permissionpresenterservice/RuntimePermissionPresenterService.java b/core/java/android/permissionpresenterservice/RuntimePermissionPresenterService.java
index 405be1a..344d947 100644
--- a/core/java/android/permissionpresenterservice/RuntimePermissionPresenterService.java
+++ b/core/java/android/permissionpresenterservice/RuntimePermissionPresenterService.java
@@ -72,14 +72,6 @@
      */
     public abstract List<RuntimePermissionPresentationInfo> onGetAppPermissions(String packageName);
 
-    /**
-     * Gets the apps that use runtime permissions.
-     *
-     * @param system Whether to return only the system apps or only the non-system ones.
-     * @return The app list.
-     */
-    public abstract List<ApplicationInfo> onGetAppsUsingPermissions(boolean system);
-
     @Override
     public final IBinder onBind(Intent intent) {
         return new IRuntimePermissionPresenter.Stub() {
@@ -91,12 +83,6 @@
                 mHandler.obtainMessage(MyHandler.MSG_GET_APP_PERMISSIONS,
                         args).sendToTarget();
             }
-
-            @Override
-            public void getAppsUsingPermissions(boolean system, RemoteCallback callback) {
-                mHandler.obtainMessage(MyHandler.MSG_GET_APPS_USING_PERMISSIONS,
-                        system ? 1 : 0, 0, callback).sendToTarget();
-            }
         };
     }
 
@@ -127,19 +113,6 @@
                         callback.sendResult(null);
                     }
                 } break;
-
-                case MSG_GET_APPS_USING_PERMISSIONS: {
-                    RemoteCallback callback = (RemoteCallback) msg.obj;
-                    final boolean system = msg.arg1 == 1;
-                    List<ApplicationInfo> apps = onGetAppsUsingPermissions(system);
-                    if (apps != null && !apps.isEmpty()) {
-                        Bundle result = new Bundle();
-                        result.putParcelableList(RuntimePermissionPresenter.KEY_RESULT, apps);
-                        callback.sendResult(result);
-                    } else {
-                        callback.sendResult(null);
-                    }
-                } break;
             }
         }
     }
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 9bc7034..d71ce34 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -8082,6 +8082,17 @@
        public static final String NETWORK_AVOID_BAD_WIFI = "network_avoid_bad_wifi";
 
        /**
+        * The thresholds of the wifi throughput badging (SD, HD etc.) as a comma-delimited list of
+        * colon-delimited key-value pairs. The key is the badging enum value defined in
+        * android.net.ScoredNetwork and the value is the minimum sustained network throughput in
+        * kbps required for the badge. For example: "10:3000,20:5000,30:25000"
+        *
+        * @hide
+        */
+       @SystemApi
+       public static final String WIFI_BADGING_THRESHOLDS = "wifi_badging_thresholds";
+
+       /**
         * Whether Wifi display is enabled/disabled
         * 0=disabled. 1=enabled.
         * @hide
diff --git a/core/java/android/service/notification/INotificationListener.aidl b/core/java/android/service/notification/INotificationListener.aidl
index 01d3391..b26e328 100644
--- a/core/java/android/service/notification/INotificationListener.aidl
+++ b/core/java/android/service/notification/INotificationListener.aidl
@@ -34,6 +34,6 @@
     void onInterruptionFilterChanged(int interruptionFilter);
 
     // rankers only
-    void onNotificationEnqueued(in IStatusBarNotificationHolder notificationHolder, int importance, boolean user);
+    void onNotificationEnqueued(in IStatusBarNotificationHolder notificationHolder);
     void onNotificationSnoozedUntilContext(in IStatusBarNotificationHolder notificationHolder, String snoozeCriterionId);
 }
diff --git a/core/java/android/service/notification/NotificationAssistantService.java b/core/java/android/service/notification/NotificationAssistantService.java
index cecdbee..de86b2d 100644
--- a/core/java/android/service/notification/NotificationAssistantService.java
+++ b/core/java/android/service/notification/NotificationAssistantService.java
@@ -77,12 +77,9 @@
      * A notification was posted by an app. Called before alert.
      *
      * @param sbn the new notification
-     * @param importance the initial importance of the notification.
-     * @param user true if the initial importance reflects an explicit user preference.
      * @return an adjustment or null to take no action, within 100ms.
      */
-    abstract public Adjustment onNotificationEnqueued(StatusBarNotification sbn,
-          int importance, boolean user);
+    abstract public Adjustment onNotificationEnqueued(StatusBarNotification sbn);
 
     /**
      * Updates a notification.  N.B. this won’t cause
@@ -202,8 +199,7 @@
 
     private class NotificationAssistantServiceWrapper extends NotificationListenerWrapper {
         @Override
-        public void onNotificationEnqueued(IStatusBarNotificationHolder sbnHolder,
-                int importance, boolean user) {
+        public void onNotificationEnqueued(IStatusBarNotificationHolder sbnHolder) {
             StatusBarNotification sbn;
             try {
                 sbn = sbnHolder.get();
@@ -214,8 +210,6 @@
 
             SomeArgs args = SomeArgs.obtain();
             args.arg1 = sbn;
-            args.argi1 = importance;
-            args.argi2 = user ? 1 : 0;
             mHandler.obtainMessage(MyHandler.MSG_ON_NOTIFICATION_ENQUEUED,
                     args).sendToTarget();
         }
@@ -254,10 +248,8 @@
                 case MSG_ON_NOTIFICATION_ENQUEUED: {
                     SomeArgs args = (SomeArgs) msg.obj;
                     StatusBarNotification sbn = (StatusBarNotification) args.arg1;
-                    final int importance = args.argi1;
-                    final boolean user = args.argi2 == 1;
                     args.recycle();
-                    Adjustment adjustment = onNotificationEnqueued(sbn, importance, user);
+                    Adjustment adjustment = onNotificationEnqueued(sbn);
                     if (adjustment != null) {
                         if (!isBound()) return;
                         try {
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index 22ad83a..e5abdac 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -1100,8 +1100,8 @@
         }
 
         @Override
-        public void onNotificationEnqueued(IStatusBarNotificationHolder notificationHolder,
-                                           int importance, boolean user) throws RemoteException {
+        public void onNotificationEnqueued(IStatusBarNotificationHolder notificationHolder)
+                throws RemoteException {
             // no-op in the listener
         }
 
diff --git a/core/java/android/text/SpannableStringInternal.java b/core/java/android/text/SpannableStringInternal.java
index 4b02df86..60d8a0f 100644
--- a/core/java/android/text/SpannableStringInternal.java
+++ b/core/java/android/text/SpannableStringInternal.java
@@ -53,12 +53,16 @@
      * @param end End index in the source object.
      */
     private final void copySpans(Spanned src, int start, int end) {
-        Object[] spans = src.getSpans(start, end, Object.class);
+        final Object[] spans = src.getSpans(start, end, Object.class);
 
         for (int i = 0; i < spans.length; i++) {
+            if (spans[i] instanceof NoCopySpan) {
+                continue;
+            }
+
             int st = src.getSpanStart(spans[i]);
             int en = src.getSpanEnd(spans[i]);
-            int fl = src.getSpanFlags(spans[i]);
+            final int fl = src.getSpanFlags(spans[i]);
 
             if (st < start)
                 st = start;
@@ -78,33 +82,42 @@
      * @param end End index in the source object.
      */
     private final void copySpans(SpannableStringInternal src, int start, int end) {
-        if (start == 0 && end == src.length()) {
+        int count = 0;
+        boolean includesNoCopySpan = false;
+        final int[] srcData = src.mSpanData;
+        final Object[] srcSpans = src.mSpans;
+        final int limit = src.mSpanCount;
+
+        for (int i = 0; i < limit; i++) {
+            int spanStart = srcData[i * COLUMNS + START];
+            int spanEnd = srcData[i * COLUMNS + END];
+            if (isOutOfCopyRange(start, end, spanStart, spanEnd)) continue;
+            if (srcSpans[i] instanceof NoCopySpan) {
+                includesNoCopySpan = true;
+                continue;
+            }
+            count++;
+        }
+
+        if (count == 0) return;
+
+        if (!includesNoCopySpan && start == 0 && end == src.length()) {
             mSpans = ArrayUtils.newUnpaddedObjectArray(src.mSpans.length);
             mSpanData = new int[src.mSpanData.length];
             mSpanCount = src.mSpanCount;
             System.arraycopy(src.mSpans, 0, mSpans, 0, src.mSpans.length);
             System.arraycopy(src.mSpanData, 0, mSpanData, 0, mSpanData.length);
         } else {
-            int count = 0;
-            int[] srcData = src.mSpanData;
-            int limit = src.mSpanCount;
-            for (int i = 0; i < limit; i++) {
-                int spanStart = srcData[i * COLUMNS + START];
-                int spanEnd = srcData[i * COLUMNS + END];
-                if (isOutOfCopyRange(start, end, spanStart, spanEnd)) continue;
-                count++;
-            }
-
-            if (count == 0) return;
-
-            Object[] srcSpans = src.mSpans;
             mSpanCount = count;
             mSpans = ArrayUtils.newUnpaddedObjectArray(mSpanCount);
             mSpanData = new int[mSpans.length * COLUMNS];
             for (int i = 0, j = 0; i < limit; i++) {
                 int spanStart = srcData[i * COLUMNS + START];
                 int spanEnd = srcData[i * COLUMNS + END];
-                if (isOutOfCopyRange(start, end, spanStart, spanEnd)) continue;
+                if (isOutOfCopyRange(start, end, spanStart, spanEnd)
+                        || srcSpans[i] instanceof NoCopySpan) {
+                    continue;
+                }
                 if (spanStart < start) spanStart = start;
                 if (spanEnd > end) spanEnd = end;
 
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 597c051..1292243 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -14384,16 +14384,8 @@
      * @hide
      */
     protected void damageInParent() {
-        final AttachInfo ai = mAttachInfo;
-        final ViewParent p = mParent;
-        if (p != null && ai != null) {
-            final Rect r = ai.mTmpInvalRect;
-            r.set(0, 0, mRight - mLeft, mBottom - mTop);
-            if (mParent instanceof ViewGroup) {
-                ((ViewGroup) mParent).damageChild(this, r);
-            } else {
-                mParent.invalidateChild(this, r);
-            }
+        if (mParent != null && mAttachInfo != null) {
+            mParent.onDescendantInvalidated(this, this);
         }
     }
 
@@ -19995,38 +19987,39 @@
     }
 
     /**
-     * {@hide}
      * @param id the id of the view to be found
      * @return the view of the specified id, null if cannot be found
+     * @hide
      */
-    protected View findViewTraversal(@IdRes int id) {
+    protected <T extends View> T findViewTraversal(@IdRes int id) {
         if (id == mID) {
-            return this;
+            return (T) this;
         }
         return null;
     }
 
     /**
-     * {@hide}
      * @param tag the tag of the view to be found
      * @return the view of specified tag, null if cannot be found
+     * @hide
      */
-    protected View findViewWithTagTraversal(Object tag) {
+    protected <T extends View> T findViewWithTagTraversal(Object tag) {
         if (tag != null && tag.equals(mTag)) {
-            return this;
+            return (T) this;
         }
         return null;
     }
 
     /**
-     * {@hide}
      * @param predicate The predicate to evaluate.
      * @param childToSkip If not null, ignores this child during the recursive traversal.
      * @return The first view that matches the predicate or null.
+     * @hide
      */
-    protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
+    protected <T extends View> T findViewByPredicateTraversal(Predicate<View> predicate,
+            View childToSkip) {
         if (predicate.apply(this)) {
-            return this;
+            return (T) this;
         }
         return null;
     }
@@ -20039,7 +20032,7 @@
      * @return The view that has the given id in the hierarchy or null
      */
     @Nullable
-    public final View findViewById(@IdRes int id) {
+    public final <T extends View> T findViewById(@IdRes int id) {
         if (id < 0) {
             return null;
         }
@@ -20052,11 +20045,11 @@
      * @param accessibilityId The searched accessibility id.
      * @return The found view.
      */
-    final View findViewByAccessibilityId(int accessibilityId) {
+    final <T extends View> T  findViewByAccessibilityId(int accessibilityId) {
         if (accessibilityId < 0) {
             return null;
         }
-        View view = findViewByAccessibilityIdTraversal(accessibilityId);
+        T view = findViewByAccessibilityIdTraversal(accessibilityId);
         if (view != null) {
             return view.includeForAccessibility() ? view : null;
         }
@@ -20075,12 +20068,11 @@
      *
      * @param accessibilityId The accessibility id.
      * @return The found view.
-     *
      * @hide
      */
-    public View findViewByAccessibilityIdTraversal(int accessibilityId) {
+    public <T extends View> T findViewByAccessibilityIdTraversal(int accessibilityId) {
         if (getAccessibilityViewId() == accessibilityId) {
-            return this;
+            return (T) this;
         }
         return null;
     }
@@ -20092,7 +20084,7 @@
      * @param tag The tag to search for, using "tag.equals(getTag())".
      * @return The View that has the given tag in the hierarchy or null
      */
-    public final View findViewWithTag(Object tag) {
+    public final <T extends View> T findViewWithTag(Object tag) {
         if (tag == null) {
             return null;
         }
@@ -20100,19 +20092,18 @@
     }
 
     /**
-     * {@hide}
      * Look for a child view that matches the specified predicate.
      * If this view matches the predicate, return this view.
      *
      * @param predicate The predicate to evaluate.
      * @return The first view that matches the predicate or null.
+     * @hide
      */
-    public final View findViewByPredicate(Predicate<View> predicate) {
+    public final <T extends View> T findViewByPredicate(Predicate<View> predicate) {
         return findViewByPredicateTraversal(predicate, null);
     }
 
     /**
-     * {@hide}
      * Look for a child view that matches the specified predicate,
      * starting with the specified view and its descendents and then
      * recusively searching the ancestors and siblings of that view
@@ -20126,11 +20117,13 @@
      * @param start The view to start from.
      * @param predicate The predicate to evaluate.
      * @return The first view that matches the predicate or null.
+     * @hide
      */
-    public final View findViewByPredicateInsideOut(View start, Predicate<View> predicate) {
+    public final <T extends View> T findViewByPredicateInsideOut(
+            View start, Predicate<View> predicate) {
         View childToSkip = null;
         for (;;) {
-            View view = start.findViewByPredicateTraversal(predicate, childToSkip);
+            T view = start.findViewByPredicateTraversal(predicate, childToSkip);
             if (view != null || start == this) {
                 return view;
             }
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index b135bef..ab10ac1 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -19,6 +19,7 @@
 import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR1;
 
 import android.animation.LayoutTransition;
+import android.annotation.CallSuper;
 import android.annotation.IdRes;
 import android.annotation.NonNull;
 import android.annotation.UiThread;
@@ -4210,9 +4211,9 @@
      * {@hide}
      */
     @Override
-    protected View findViewTraversal(@IdRes int id) {
+    protected <T extends View> T findViewTraversal(@IdRes int id) {
         if (id == mID) {
-            return this;
+            return (T) this;
         }
 
         final View[] where = mChildren;
@@ -4225,7 +4226,7 @@
                 v = v.findViewById(id);
 
                 if (v != null) {
-                    return v;
+                    return (T) v;
                 }
             }
         }
@@ -4237,9 +4238,9 @@
      * {@hide}
      */
     @Override
-    protected View findViewWithTagTraversal(Object tag) {
+    protected <T extends View> T findViewWithTagTraversal(Object tag) {
         if (tag != null && tag.equals(mTag)) {
-            return this;
+            return (T) this;
         }
 
         final View[] where = mChildren;
@@ -4252,7 +4253,7 @@
                 v = v.findViewWithTag(tag);
 
                 if (v != null) {
-                    return v;
+                    return (T) v;
                 }
             }
         }
@@ -4264,9 +4265,10 @@
      * {@hide}
      */
     @Override
-    protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
+    protected <T extends View> T findViewByPredicateTraversal(Predicate<View> predicate,
+            View childToSkip) {
         if (predicate.apply(this)) {
-            return this;
+            return (T) this;
         }
 
         final View[] where = mChildren;
@@ -4279,7 +4281,7 @@
                 v = v.findViewByPredicate(predicate);
 
                 if (v != null) {
-                    return v;
+                    return (T) v;
                 }
             }
         }
@@ -5412,100 +5414,60 @@
         }
     }
 
-    /**
-     * HW-only, Rect-ignoring invalidation path.
-     *
-     * Returns false if this path was unable to complete successfully. This means
-     * it hit a ViewParent it doesn't recognize and needs to fall back to calculating
-     * damage area.
-     *
-     * Hardware acceleration ignores damage rectangles, since native computes damage for everything
-     * drawn by HWUI (and SW layer / drawing cache doesn't keep track of damage area).
-     *
-     * Ignores opaque dirty optimizations, always using the full PFLAG_DIRTY flag.
-     *
-     * Ignores FLAG_OPTIMIZE_INVALIDATE, since we're not computing a rect,
-     *         so no point in optimizing that.
-     * @hide
-     */
-    public boolean tryInvalidateChildHardware(View child) {
-        final AttachInfo attachInfo = mAttachInfo;
-        if (attachInfo == null || !attachInfo.mHardwareAccelerated) {
-            return false;
+    @Override
+    @CallSuper
+    public void onDescendantInvalidated(@NonNull View child, @NonNull View target) {
+        /*
+         * HW-only, Rect-ignoring damage codepath
+         *
+         * We don't deal with rectangles here, since RenderThread native code computes damage for
+         * everything drawn by HWUI (and SW layer / drawing cache doesn't keep track of damage area)
+         */
+
+        // if set, combine the animation flag into the parent
+        mPrivateFlags |= (target.mPrivateFlags & PFLAG_DRAW_ANIMATION);
+
+        if ((target.mPrivateFlags & ~PFLAG_DIRTY_MASK) != 0) {
+            // We lazily use PFLAG_DIRTY, since computing opaque isn't worth the potential
+            // optimization in provides in a DisplayList world.
+            mPrivateFlags = (mPrivateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DIRTY;
+
+            // simplified invalidateChildInParent behavior: clear cache validity to be safe...
+            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
         }
 
-        // verify it's ViewGroups up to a ViewRootImpl
-        ViewRootImpl viewRoot = null;
-        ViewParent parent = getParent();
-        while (parent != null) {
-            if (parent instanceof ViewGroup) {
-                parent = parent.getParent();
-            } else if (parent instanceof ViewRootImpl) {
-                viewRoot = (ViewRootImpl) parent;
-                break;
-            } else {
-                // unknown parent type, abort
-                return false;
-            }
-        }
-        if (viewRoot == null) {
-            // unable to find ViewRoot
-            return false;
+        // ... and mark inval if in software layer that needs to repaint (hw handled in native)
+        if (mLayerType == LAYER_TYPE_SOFTWARE) {
+            // Layered parents should be invalidated. Escalate to a full invalidate (and note that
+            // we do this after consuming any relevant flags from the originating descendant)
+            mPrivateFlags |= PFLAG_INVALIDATED | PFLAG_DIRTY;
+            target = this;
         }
 
-        final boolean drawAnimation = (child.mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0;
-
-        if (child.mLayerType != LAYER_TYPE_NONE) {
-            mPrivateFlags |= PFLAG_INVALIDATED;
+        if (mParent != null) {
+            mParent.onDescendantInvalidated(this, target);
         }
-
-        parent = this;
-        do {
-            if (parent != viewRoot) {
-                // Note: we cast here without checking isinstance, to avoid cost of isinstance again
-                ViewGroup viewGroup = (ViewGroup) parent;
-                if (drawAnimation) {
-                    viewGroup.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
-                }
-
-                // We lazily use PFLAG_DIRTY, since computing opaque isn't worth the potential
-                // optimization in provides in a DisplayList world.
-                viewGroup.mPrivateFlags =
-                        (viewGroup.mPrivateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DIRTY;
-
-                // simplified invalidateChildInParent behavior: clear cache validity to be safe,
-                // and mark inval if in layer
-                viewGroup.mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
-                if (viewGroup.mLayerType != LAYER_TYPE_NONE) {
-                    viewGroup.mPrivateFlags |= PFLAG_INVALIDATED;
-                }
-            } else {
-                if (drawAnimation) {
-                    viewRoot.mIsAnimating = true;
-                }
-                ((ViewRootImpl) parent).invalidate();
-                return true;
-            }
-
-            parent = parent.getParent();
-        } while (parent != null);
-        return true;
     }
 
 
     /**
      * Don't call or override this method. It is used for the implementation of
      * the view hierarchy.
+     *
+     * @deprecated Use {@link #onDescendantInvalidated(View, View)} instead to observe updates to
+     * draw state in descendants.
      */
+    @Deprecated
     @Override
     public final void invalidateChild(View child, final Rect dirty) {
-        if (tryInvalidateChildHardware(child)) {
+        final AttachInfo attachInfo = mAttachInfo;
+        if (attachInfo != null && attachInfo.mHardwareAccelerated) {
+            // HW accelerated fast path
+            onDescendantInvalidated(child, child);
             return;
         }
 
         ViewParent parent = this;
-
-        final AttachInfo attachInfo = mAttachInfo;
         if (attachInfo != null) {
             // If the child is drawing an animation, we want to copy this flag onto
             // ourselves and the parent to make sure the invalidate request goes
@@ -5608,7 +5570,11 @@
      * This implementation returns null if this ViewGroup does not have a parent,
      * if this ViewGroup is already fully invalidated or if the dirty rectangle
      * does not intersect with this ViewGroup's bounds.
+     *
+     * @deprecated Use {@link #onDescendantInvalidated(View, View)} instead to observe updates to
+     * draw state in descendants.
      */
+    @Deprecated
     @Override
     public ViewParent invalidateChildInParent(final int[] location, final Rect dirty) {
         if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID)) != 0) {
@@ -5657,74 +5623,6 @@
     }
 
     /**
-     * Native-calculated damage path
-     * Returns false if this path was unable to complete successfully. This means
-     * it hit a ViewParent it doesn't recognize and needs to fall back to calculating
-     * damage area
-     * @hide
-     */
-    public boolean damageChildDeferred() {
-        ViewParent parent = getParent();
-        while (parent != null) {
-            if (parent instanceof ViewGroup) {
-                parent = parent.getParent();
-            } else if (parent instanceof ViewRootImpl) {
-                ((ViewRootImpl) parent).invalidate();
-                return true;
-            } else {
-                parent = null;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Quick invalidation method called by View.invalidateViewProperty. This doesn't set the
-     * DRAWN flags and doesn't handle the Animation logic that the default invalidation methods
-     * do; all we want to do here is schedule a traversal with the appropriate dirty rect.
-     *
-     * @hide
-     */
-    public void damageChild(View child, final Rect dirty) {
-        if (damageChildDeferred()) {
-            return;
-        }
-
-        ViewParent parent = this;
-
-        final AttachInfo attachInfo = mAttachInfo;
-        if (attachInfo != null) {
-            int left = child.mLeft;
-            int top = child.mTop;
-            if (!child.getMatrix().isIdentity()) {
-                child.transformRect(dirty);
-            }
-
-            do {
-                if (parent instanceof ViewGroup) {
-                    ViewGroup parentVG = (ViewGroup) parent;
-                    if (parentVG.mLayerType != LAYER_TYPE_NONE) {
-                        // Layered parents should be recreated, not just re-issued
-                        parentVG.invalidate();
-                        parent = null;
-                    } else {
-                        parent = parentVG.damageChildInParent(left, top, dirty);
-                        left = parentVG.mLeft;
-                        top = parentVG.mTop;
-                    }
-                } else {
-                    // Reached the top; this calls into the usual invalidate method in
-                    // ViewRootImpl, which schedules a traversal
-                    final int[] location = attachInfo.mInvalidateChildLocation;
-                    location[0] = left;
-                    location[1] = top;
-                    parent = parent.invalidateChildInParent(location, dirty);
-                }
-            } while (parent != null);
-        }
-    }
-
-    /**
      * Quick invalidation method that simply transforms the dirty rect into the parent's
      * coordinate system, pruning the invalidation if the parent has already been invalidated.
      *
diff --git a/core/java/android/view/ViewOverlay.java b/core/java/android/view/ViewOverlay.java
index 1676a00..f061370 100644
--- a/core/java/android/view/ViewOverlay.java
+++ b/core/java/android/view/ViewOverlay.java
@@ -328,22 +328,10 @@
             }
         }
 
-        /**
-         * @hide
-         */
         @Override
-        public void damageChild(View child, final Rect dirty) {
-            if (mHostView != null) {
-                // Note: This is not a "fast" invalidation. Would be nice to instead invalidate
-                // using DisplayList properties and a dirty rect instead of causing a real
-                // invalidation of the host view
-                int left = child.mLeft;
-                int top = child.mTop;
-                if (!child.getMatrix().isIdentity()) {
-                    child.transformRect(dirty);
-                }
-                dirty.offset(left, top);
-                mHostView.invalidate(dirty);
+        public void onDescendantInvalidated(@NonNull View child, @NonNull View target) {
+            if (mHostView != null && mHostView.getParent() != null) {
+                mHostView.getParent().onDescendantInvalidated(mHostView, target);
             }
         }
 
diff --git a/core/java/android/view/ViewParent.java b/core/java/android/view/ViewParent.java
index 79b05cd..cc11cb8 100644
--- a/core/java/android/view/ViewParent.java
+++ b/core/java/android/view/ViewParent.java
@@ -16,6 +16,7 @@
 
 package android.view;
 
+import android.annotation.NonNull;
 import android.graphics.Rect;
 import android.os.Bundle;
 import android.view.accessibility.AccessibilityEvent;
@@ -53,12 +54,36 @@
      */
     public void requestTransparentRegion(View child);
 
+
+    /**
+     * The target View has been invalidated, or has had a drawing property changed that
+     * requires the hierarchy to re-render.
+     *
+     * This method is called by the View hierarchy to signal ancestors that a View either needs to
+     * re-record its drawing commands, or drawing properties have changed. This is how Views
+     * schedule a drawing traversal.
+     *
+     * This signal is generally only dispatched for attached Views, since only they need to draw.
+     *
+     * @param child Direct child of this ViewParent containing target
+     * @param target The view that needs to redraw
+     */
+    default void onDescendantInvalidated(@NonNull View child, @NonNull View target) {
+        if (getParent() != null) {
+            // Note: should pass 'this' as default, but can't since we may not be a View
+            getParent().onDescendantInvalidated(child, target);
+        }
+    }
+
     /**
      * All or part of a child is dirty and needs to be redrawn.
      * 
      * @param child The child which is dirty
      * @param r The area within the child that is invalid
+     *
+     * @deprecated Use {@link #onDescendantInvalidated(View, View)} instead.
      */
+    @Deprecated
     public void invalidateChild(View child, Rect r);
 
     /**
@@ -80,7 +105,10 @@
      * @param r The area within the child that is invalid
      *
      * @return the parent of this ViewParent or null
+     *
+     * @deprecated Use {@link #onDescendantInvalidated(View, View)} instead.
      */
+    @Deprecated
     public ViewParent invalidateChildInParent(int[] location, Rect r);
 
     /**
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index c9b9d5f..9bfc260 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -16,6 +16,7 @@
 
 package android.view;
 
+import static android.view.View.PFLAG_DRAW_ANIMATION;
 import static android.view.WindowCallbacks.RESIZE_MODE_DOCKED_DIVIDER;
 import static android.view.WindowCallbacks.RESIZE_MODE_FREEFORM;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY;
@@ -1065,6 +1066,14 @@
         return mLayoutRequested;
     }
 
+    @Override
+    public void onDescendantInvalidated(@NonNull View child, @NonNull View descendant) {
+        if ((descendant.mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) {
+            mIsAnimating = true;
+        }
+        invalidate();
+    }
+
     void invalidate() {
         mDirty.set(0, 0, mWidth, mHeight);
         if (!mWillDrawSoon) {
diff --git a/core/java/android/webkit/WebViewClient.java b/core/java/android/webkit/WebViewClient.java
index 8703468..0a73e17d 100644
--- a/core/java/android/webkit/WebViewClient.java
+++ b/core/java/android/webkit/WebViewClient.java
@@ -488,7 +488,8 @@
      * @param view The WebView which needs to be cleaned up.
      * @param detail the reason why it exited.
      * @return true if the host application handled the situation that process has
-     *         exited, otherwise, application will crash.
+     *         exited, otherwise, application will crash if render process crashed,
+     *         or be killed if render process was killed by the system.
      */
     public boolean onRenderProcessGone(WebView view, RenderProcessGoneDetail detail) {
         return false;
diff --git a/core/java/android/widget/ActivityChooserView.java b/core/java/android/widget/ActivityChooserView.java
index 51587a7..9a39a17 100644
--- a/core/java/android/widget/ActivityChooserView.java
+++ b/core/java/android/widget/ActivityChooserView.java
@@ -250,7 +250,7 @@
         mDefaultActivityButton = (FrameLayout) findViewById(R.id.default_activity_button);
         mDefaultActivityButton.setOnClickListener(mCallbacks);
         mDefaultActivityButton.setOnLongClickListener(mCallbacks);
-        mDefaultActivityButtonImage = (ImageView) mDefaultActivityButton.findViewById(R.id.image);
+        mDefaultActivityButtonImage = mDefaultActivityButton.findViewById(R.id.image);
 
         final FrameLayout expandButton = (FrameLayout) findViewById(R.id.expand_activities_button);
         expandButton.setOnClickListener(mCallbacks);
@@ -282,7 +282,7 @@
         mExpandActivityOverflowButton = expandButton;
 
         mExpandActivityOverflowButtonImage =
-            (ImageView) expandButton.findViewById(R.id.image);
+            expandButton.findViewById(R.id.image);
         mExpandActivityOverflowButtonImage.setImageDrawable(expandActivityOverflowButtonDrawable);
 
         mAdapter = new ActivityChooserViewAdapter();
@@ -760,7 +760,7 @@
                         convertView = LayoutInflater.from(getContext()).inflate(
                                 R.layout.activity_chooser_view_list_item, parent, false);
                         convertView.setId(ITEM_VIEW_TYPE_FOOTER);
-                        TextView titleView = (TextView) convertView.findViewById(R.id.title);
+                        TextView titleView = convertView.findViewById(R.id.title);
                         titleView.setText(mContext.getString(
                                 R.string.activity_chooser_view_see_all));
                     }
@@ -772,11 +772,11 @@
                     }
                     PackageManager packageManager = mContext.getPackageManager();
                     // Set the icon
-                    ImageView iconView = (ImageView) convertView.findViewById(R.id.icon);
+                    ImageView iconView = convertView.findViewById(R.id.icon);
                     ResolveInfo activity = (ResolveInfo) getItem(position);
                     iconView.setImageDrawable(activity.loadIcon(packageManager));
                     // Set the title.
-                    TextView titleView = (TextView) convertView.findViewById(R.id.title);
+                    TextView titleView = convertView.findViewById(R.id.title);
                     titleView.setText(activity.loadLabel(packageManager));
                     // Highlight the default.
                     if (mShowDefaultActivity && position == 0 && mHighlightDefaultActivity) {
diff --git a/core/java/android/widget/AppSecurityPermissions.java b/core/java/android/widget/AppSecurityPermissions.java
index 68e6809..06d4868 100644
--- a/core/java/android/widget/AppSecurityPermissions.java
+++ b/core/java/android/widget/AppSecurityPermissions.java
@@ -451,7 +451,7 @@
 
     private View getPermissionsView(int which, boolean showRevokeUI) {
         LinearLayout permsView = (LinearLayout) mInflater.inflate(R.layout.app_perms_summary, null);
-        LinearLayout displayList = (LinearLayout) permsView.findViewById(R.id.perms_list);
+        LinearLayout displayList = permsView.findViewById(R.id.perms_list);
         View noPermsView = permsView.findViewById(R.id.no_permissions);
 
         displayPermissions(mPermGroupsList, displayList, which, showRevokeUI);
@@ -517,8 +517,8 @@
             CharSequence grpName, CharSequence permList, boolean dangerous, Drawable icon) {
         View permView = inflater.inflate(R.layout.app_permission_item_old, null);
 
-        TextView permGrpView = (TextView) permView.findViewById(R.id.permission_group);
-        TextView permDescView = (TextView) permView.findViewById(R.id.permission_list);
+        TextView permGrpView = permView.findViewById(R.id.permission_group);
+        TextView permDescView = permView.findViewById(R.id.permission_list);
 
         ImageView imgView = (ImageView)permView.findViewById(R.id.perm_icon);
         imgView.setImageDrawable(icon);
diff --git a/core/java/android/widget/ArrayAdapter.java b/core/java/android/widget/ArrayAdapter.java
index bbc50da..81f0d3d 100644
--- a/core/java/android/widget/ArrayAdapter.java
+++ b/core/java/android/widget/ArrayAdapter.java
@@ -388,7 +388,7 @@
                 text = (TextView) view;
             } else {
                 //  Otherwise, find the TextView field within the layout
-                text = (TextView) view.findViewById(mFieldId);
+                text = view.findViewById(mFieldId);
 
                 if (text == null) {
                     throw new RuntimeException("Failed to find view with ID "
diff --git a/core/java/android/widget/CalendarViewLegacyDelegate.java b/core/java/android/widget/CalendarViewLegacyDelegate.java
index 557d411..1b899db 100644
--- a/core/java/android/widget/CalendarViewLegacyDelegate.java
+++ b/core/java/android/widget/CalendarViewLegacyDelegate.java
@@ -316,9 +316,9 @@
         View content = layoutInflater.inflate(R.layout.calendar_view, null, false);
         mDelegator.addView(content);
 
-        mListView = (ListView) mDelegator.findViewById(R.id.list);
-        mDayNamesHeader = (ViewGroup) content.findViewById(R.id.day_names);
-        mMonthName = (TextView) content.findViewById(R.id.month_name);
+        mListView = mDelegator.findViewById(R.id.list);
+        mDayNamesHeader = content.findViewById(R.id.day_names);
+        mMonthName = content.findViewById(R.id.month_name);
 
         setUpHeader();
         setUpListView();
diff --git a/core/java/android/widget/DatePickerCalendarDelegate.java b/core/java/android/widget/DatePickerCalendarDelegate.java
index f712685..907250a 100755
--- a/core/java/android/widget/DatePickerCalendarDelegate.java
+++ b/core/java/android/widget/DatePickerCalendarDelegate.java
@@ -115,10 +115,10 @@
         mDelegator.addView(mContainer);
 
         // Set up header views.
-        final ViewGroup header = (ViewGroup) mContainer.findViewById(R.id.date_picker_header);
-        mHeaderYear = (TextView) header.findViewById(R.id.date_picker_header_year);
+        final ViewGroup header = mContainer.findViewById(R.id.date_picker_header);
+        mHeaderYear = header.findViewById(R.id.date_picker_header_year);
         mHeaderYear.setOnClickListener(mOnHeaderClickListener);
-        mHeaderMonthDay = (TextView) header.findViewById(R.id.date_picker_header_date);
+        mHeaderMonthDay = header.findViewById(R.id.date_picker_header_date);
         mHeaderMonthDay.setOnClickListener(mOnHeaderClickListener);
 
         // For the sake of backwards compatibility, attempt to extract the text
@@ -154,10 +154,10 @@
         a.recycle();
 
         // Set up picker container.
-        mAnimator = (ViewAnimator) mContainer.findViewById(R.id.animator);
+        mAnimator = mContainer.findViewById(R.id.animator);
 
         // Set up day picker view.
-        mDayPickerView = (DayPickerView) mAnimator.findViewById(R.id.date_picker_day_picker);
+        mDayPickerView = mAnimator.findViewById(R.id.date_picker_day_picker);
         mDayPickerView.setFirstDayOfWeek(mFirstDayOfWeek);
         mDayPickerView.setMinDate(mMinDate.getTimeInMillis());
         mDayPickerView.setMaxDate(mMaxDate.getTimeInMillis());
@@ -165,7 +165,7 @@
         mDayPickerView.setOnDaySelectedListener(mOnDaySelectedListener);
 
         // Set up year picker view.
-        mYearPickerView = (YearPickerView) mAnimator.findViewById(R.id.date_picker_year_picker);
+        mYearPickerView = mAnimator.findViewById(R.id.date_picker_year_picker);
         mYearPickerView.setRange(mMinDate, mMaxDate);
         mYearPickerView.setYear(mCurrentDate.get(Calendar.YEAR));
         mYearPickerView.setOnYearSelectedListener(mOnYearSelectedListener);
diff --git a/core/java/android/widget/DayPickerPagerAdapter.java b/core/java/android/widget/DayPickerPagerAdapter.java
index 8d5bf8f..63621e1 100644
--- a/core/java/android/widget/DayPickerPagerAdapter.java
+++ b/core/java/android/widget/DayPickerPagerAdapter.java
@@ -225,7 +225,7 @@
     public Object instantiateItem(ViewGroup container, int position) {
         final View itemView = mInflater.inflate(mLayoutResId, container, false);
 
-        final SimpleMonthView v = (SimpleMonthView) itemView.findViewById(mCalendarViewId);
+        final SimpleMonthView v = itemView.findViewById(mCalendarViewId);
         v.setOnDayClickListener(mOnDayClickListener);
         v.setMonthTextAppearance(mMonthTextAppearance);
         v.setDayOfWeekTextAppearance(mDayOfWeekTextAppearance);
diff --git a/core/java/android/widget/DayPickerViewPager.java b/core/java/android/widget/DayPickerViewPager.java
index 94022ae..058baa6 100644
--- a/core/java/android/widget/DayPickerViewPager.java
+++ b/core/java/android/widget/DayPickerViewPager.java
@@ -137,9 +137,10 @@
     }
 
     @Override
-    protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
+    protected <T extends View> T findViewByPredicateTraversal(Predicate<View> predicate,
+            View childToSkip) {
         if (predicate.apply(this)) {
-            return this;
+            return (T) this;
         }
 
         // Always try the selected view first.
@@ -148,7 +149,7 @@
         if (current != childToSkip && current != null) {
             final View v = current.findViewByPredicate(predicate);
             if (v != null) {
-                return v;
+                return (T) v;
             }
         }
 
@@ -160,7 +161,7 @@
                 final View v = child.findViewByPredicate(predicate);
 
                 if (v != null) {
-                    return v;
+                    return (T) v;
                 }
             }
         }
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index e52c13b..b7da04e 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -3735,32 +3735,30 @@
         }
     }
 
-    /* (non-Javadoc)
+    /**
      * @see android.view.View#findViewById(int)
-     * First look in our children, then in any header and footer views that may be scrolled off.
+     * @removed For internal use only. This should have been hidden.
      */
     @Override
-    protected View findViewTraversal(@IdRes int id) {
-        View v;
-        v = super.findViewTraversal(id);
+    protected <T extends View> T findViewTraversal(@IdRes int id) {
+        // First look in our children, then in any header and footer views that
+        // may be scrolled off.
+        View v = super.findViewTraversal(id);
         if (v == null) {
             v = findViewInHeadersOrFooters(mHeaderViewInfos, id);
             if (v != null) {
-                return v;
+                return (T) v;
             }
             v = findViewInHeadersOrFooters(mFooterViewInfos, id);
             if (v != null) {
-                return v;
+                return (T) v;
             }
         }
-        return v;
+        return (T) v;
     }
 
-    /* (non-Javadoc)
-     *
-     * Look in the passed in list of headers or footers for the view.
-     */
     View findViewInHeadersOrFooters(ArrayList<FixedViewInfo> where, int id) {
+        // Look in the passed in list of headers or footers for the view.
         if (where != null) {
             int len = where.size();
             View v;
@@ -3780,33 +3778,32 @@
         return null;
     }
 
-    /* (non-Javadoc)
+    /**
      * @see android.view.View#findViewWithTag(Object)
-     * First look in our children, then in any header and footer views that may be scrolled off.
+     * @removed For internal use only. This should have been hidden.
      */
     @Override
-    protected View findViewWithTagTraversal(Object tag) {
-        View v;
-        v = super.findViewWithTagTraversal(tag);
+    protected <T extends View> T findViewWithTagTraversal(Object tag) {
+        // First look in our children, then in any header and footer views that
+        // may be scrolled off.
+        View v = super.findViewWithTagTraversal(tag);
         if (v == null) {
             v = findViewWithTagInHeadersOrFooters(mHeaderViewInfos, tag);
             if (v != null) {
-                return v;
+                return (T) v;
             }
 
             v = findViewWithTagInHeadersOrFooters(mFooterViewInfos, tag);
             if (v != null) {
-                return v;
+                return (T) v;
             }
         }
-        return v;
+        return (T) v;
     }
 
-    /* (non-Javadoc)
-     *
-     * Look in the passed in list of headers or footers for the view with the tag.
-     */
     View findViewWithTagInHeadersOrFooters(ArrayList<FixedViewInfo> where, Object tag) {
+        // Look in the passed in list of headers or footers for the view with
+        // the tag.
         if (where != null) {
             int len = where.size();
             View v;
@@ -3827,32 +3824,33 @@
     }
 
     /**
-     * @hide
+     * First look in our children, then in any header and footer views that may
+     * be scrolled off.
+     *
      * @see android.view.View#findViewByPredicate(Predicate)
-     * First look in our children, then in any header and footer views that may be scrolled off.
+     * @hide
      */
     @Override
-    protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
-        View v;
-        v = super.findViewByPredicateTraversal(predicate, childToSkip);
+    protected <T extends View> T findViewByPredicateTraversal(
+            Predicate<View> predicate, View childToSkip) {
+        View v = super.findViewByPredicateTraversal(predicate, childToSkip);
         if (v == null) {
             v = findViewByPredicateInHeadersOrFooters(mHeaderViewInfos, predicate, childToSkip);
             if (v != null) {
-                return v;
+                return (T) v;
             }
 
             v = findViewByPredicateInHeadersOrFooters(mFooterViewInfos, predicate, childToSkip);
             if (v != null) {
-                return v;
+                return (T) v;
             }
         }
-        return v;
+        return (T) v;
     }
 
-    /* (non-Javadoc)
-     *
-     * Look in the passed in list of headers or footers for the first view that matches
-     * the predicate.
+    /**
+     * Look in the passed in list of headers or footers for the first view that
+     * matches the predicate.
      */
     View findViewByPredicateInHeadersOrFooters(ArrayList<FixedViewInfo> where,
             Predicate<View> predicate, View childToSkip) {
diff --git a/core/java/android/widget/MediaController.java b/core/java/android/widget/MediaController.java
index 8008637..8e04f1c 100644
--- a/core/java/android/widget/MediaController.java
+++ b/core/java/android/widget/MediaController.java
@@ -257,13 +257,13 @@
                 .getText(com.android.internal.R.string.lockscreen_transport_play_description);
         mPauseDescription = res
                 .getText(com.android.internal.R.string.lockscreen_transport_pause_description);
-        mPauseButton = (ImageButton) v.findViewById(com.android.internal.R.id.pause);
+        mPauseButton = v.findViewById(com.android.internal.R.id.pause);
         if (mPauseButton != null) {
             mPauseButton.requestFocus();
             mPauseButton.setOnClickListener(mPauseListener);
         }
 
-        mFfwdButton = (ImageButton) v.findViewById(com.android.internal.R.id.ffwd);
+        mFfwdButton = v.findViewById(com.android.internal.R.id.ffwd);
         if (mFfwdButton != null) {
             mFfwdButton.setOnClickListener(mFfwdListener);
             if (!mFromXml) {
@@ -271,7 +271,7 @@
             }
         }
 
-        mRewButton = (ImageButton) v.findViewById(com.android.internal.R.id.rew);
+        mRewButton = v.findViewById(com.android.internal.R.id.rew);
         if (mRewButton != null) {
             mRewButton.setOnClickListener(mRewListener);
             if (!mFromXml) {
@@ -280,16 +280,16 @@
         }
 
         // By default these are hidden. They will be enabled when setPrevNextListeners() is called
-        mNextButton = (ImageButton) v.findViewById(com.android.internal.R.id.next);
+        mNextButton = v.findViewById(com.android.internal.R.id.next);
         if (mNextButton != null && !mFromXml && !mListenersSet) {
             mNextButton.setVisibility(View.GONE);
         }
-        mPrevButton = (ImageButton) v.findViewById(com.android.internal.R.id.prev);
+        mPrevButton = v.findViewById(com.android.internal.R.id.prev);
         if (mPrevButton != null && !mFromXml && !mListenersSet) {
             mPrevButton.setVisibility(View.GONE);
         }
 
-        mProgress = (ProgressBar) v.findViewById(com.android.internal.R.id.mediacontroller_progress);
+        mProgress = v.findViewById(com.android.internal.R.id.mediacontroller_progress);
         if (mProgress != null) {
             if (mProgress instanceof SeekBar) {
                 SeekBar seeker = (SeekBar) mProgress;
@@ -298,8 +298,8 @@
             mProgress.setMax(1000);
         }
 
-        mEndTime = (TextView) v.findViewById(com.android.internal.R.id.time);
-        mCurrentTime = (TextView) v.findViewById(com.android.internal.R.id.time_current);
+        mEndTime = v.findViewById(com.android.internal.R.id.time);
+        mCurrentTime = v.findViewById(com.android.internal.R.id.time_current);
         mFormatBuilder = new StringBuilder();
         mFormatter = new Formatter(mFormatBuilder, Locale.getDefault());
 
diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java
index b424101..67bfe5e 100644
--- a/core/java/android/widget/RelativeLayout.java
+++ b/core/java/android/widget/RelativeLayout.java
@@ -1013,7 +1013,8 @@
             while (v.getVisibility() == View.GONE) {
                 rules = ((LayoutParams) v.getLayoutParams()).getRules(v.getLayoutDirection());
                 node = mGraph.mKeyNodes.get((rules[relation]));
-                if (node == null) return null;
+                // ignore self dependency. for more info look in git commit: da3003
+                if (node == null || v == node.view) return null;
                 v = node.view;
             }
 
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 359d04e..5505f2f 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -1578,7 +1578,7 @@
         @Override
         public void apply(View root, ViewGroup rootParent, OnClickHandler handler) {
             final Context context = root.getContext();
-            final ViewGroup target = (ViewGroup) root.findViewById(viewId);
+            final ViewGroup target = root.findViewById(viewId);
             if (target == null) return;
             if (nestedViews != null) {
                 // Inflate nested views and add as children
@@ -1757,7 +1757,7 @@
 
         @Override
         public void apply(View root, ViewGroup rootParent, OnClickHandler handler) {
-            final TextView target = (TextView) root.findViewById(viewId);
+            final TextView target = root.findViewById(viewId);
             if (target == null) return;
             if (drawablesLoaded) {
                 if (isRelative) {
@@ -1857,7 +1857,7 @@
 
         @Override
         public void apply(View root, ViewGroup rootParent, OnClickHandler handler) {
-            final TextView target = (TextView) root.findViewById(viewId);
+            final TextView target = root.findViewById(viewId);
             if (target == null) return;
             target.setTextSize(units, size);
         }
@@ -2045,7 +2045,7 @@
 
         @Override
         public void apply(View root, ViewGroup rootParent, OnClickHandler handler) {
-            final TextView target = (TextView) root.findViewById(viewId);
+            final TextView target = root.findViewById(viewId);
             if (target == null) return;
             Drawable[] drawables = isRelative
                     ? target.getCompoundDrawablesRelative()
diff --git a/core/java/android/widget/SuggestionsAdapter.java b/core/java/android/widget/SuggestionsAdapter.java
index f833d1b..fbb8993 100644
--- a/core/java/android/widget/SuggestionsAdapter.java
+++ b/core/java/android/widget/SuggestionsAdapter.java
@@ -286,7 +286,7 @@
         v.setTag(new ChildViewCache(v));
 
         // Set up icon.
-        final ImageView iconRefine = (ImageView) v.findViewById(R.id.edit_query);
+        final ImageView iconRefine = v.findViewById(R.id.edit_query);
         iconRefine.setImageResource(mCommitIconResId);
 
         return v;
@@ -304,11 +304,11 @@
         public final ImageView mIconRefine;
 
         public ChildViewCache(View v) {
-            mText1 = (TextView) v.findViewById(com.android.internal.R.id.text1);
-            mText2 = (TextView) v.findViewById(com.android.internal.R.id.text2);
-            mIcon1 = (ImageView) v.findViewById(com.android.internal.R.id.icon1);
-            mIcon2 = (ImageView) v.findViewById(com.android.internal.R.id.icon2);
-            mIconRefine = (ImageView) v.findViewById(com.android.internal.R.id.edit_query);
+            mText1 = v.findViewById(com.android.internal.R.id.text1);
+            mText2 = v.findViewById(com.android.internal.R.id.text2);
+            mIcon1 = v.findViewById(com.android.internal.R.id.icon1);
+            mIcon2 = v.findViewById(com.android.internal.R.id.icon2);
+            mIconRefine = v.findViewById(com.android.internal.R.id.edit_query);
         }
     }
 
diff --git a/core/java/android/widget/TabHost.java b/core/java/android/widget/TabHost.java
index 32418cd..7e2cadf 100644
--- a/core/java/android/widget/TabHost.java
+++ b/core/java/android/widget/TabHost.java
@@ -619,7 +619,7 @@
                     mTabWidget, // tab widget is the parent
                     false); // no inflate params
 
-            final TextView tv = (TextView) tabIndicator.findViewById(R.id.title);
+            final TextView tv = tabIndicator.findViewById(R.id.title);
             tv.setText(mLabel);
 
             if (context.getApplicationInfo().targetSdkVersion <= Build.VERSION_CODES.DONUT) {
@@ -653,8 +653,8 @@
                     mTabWidget, // tab widget is the parent
                     false); // no inflate params
 
-            final TextView tv = (TextView) tabIndicator.findViewById(R.id.title);
-            final ImageView iconView = (ImageView) tabIndicator.findViewById(R.id.icon);
+            final TextView tv = tabIndicator.findViewById(R.id.title);
+            final ImageView iconView = tabIndicator.findViewById(R.id.icon);
 
             // when icon is gone by default, we're in exclusive mode
             final boolean exclusive = iconView.getVisibility() == View.GONE;
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 6322615..a7a8fb4 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -1162,12 +1162,12 @@
 
                 case com.android.internal.R.styleable.TextView_fontFamily:
                     try {
-                        fontTypeface = appearance.getFont(attr);
+                        fontTypeface = a.getFont(attr);
                     } catch (UnsupportedOperationException e) {
                         // Expected if it is not a font resource.
                     }
                     if (fontTypeface == null) {
-                        fontFamily = appearance.getString(attr);
+                        fontFamily = a.getString(attr);
                     }
                     fontFamilyExplicit = true;
                     break;
diff --git a/core/java/android/widget/TimePickerSpinnerDelegate.java b/core/java/android/widget/TimePickerSpinnerDelegate.java
index 6a68f60..4634631 100644
--- a/core/java/android/widget/TimePickerSpinnerDelegate.java
+++ b/core/java/android/widget/TimePickerSpinnerDelegate.java
@@ -86,7 +86,7 @@
         inflater.inflate(layoutResourceId, mDelegator, true);
 
         // hour
-        mHourSpinner = (NumberPicker) delegator.findViewById(R.id.hour);
+        mHourSpinner = delegator.findViewById(R.id.hour);
         mHourSpinner.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
             public void onValueChange(NumberPicker spinner, int oldVal, int newVal) {
                 updateInputState();
@@ -100,17 +100,17 @@
                 onTimeChanged();
             }
         });
-        mHourSpinnerInput = (EditText) mHourSpinner.findViewById(R.id.numberpicker_input);
+        mHourSpinnerInput = mHourSpinner.findViewById(R.id.numberpicker_input);
         mHourSpinnerInput.setImeOptions(EditorInfo.IME_ACTION_NEXT);
 
         // divider (only for the new widget style)
-        mDivider = (TextView) mDelegator.findViewById(R.id.divider);
+        mDivider = mDelegator.findViewById(R.id.divider);
         if (mDivider != null) {
             setDividerText();
         }
 
         // minute
-        mMinuteSpinner = (NumberPicker) mDelegator.findViewById(R.id.minute);
+        mMinuteSpinner = mDelegator.findViewById(R.id.minute);
         mMinuteSpinner.setMinValue(0);
         mMinuteSpinner.setMaxValue(59);
         mMinuteSpinner.setOnLongPressUpdateInterval(100);
@@ -138,7 +138,7 @@
                 onTimeChanged();
             }
         });
-        mMinuteSpinnerInput = (EditText) mMinuteSpinner.findViewById(R.id.numberpicker_input);
+        mMinuteSpinnerInput = mMinuteSpinner.findViewById(R.id.numberpicker_input);
         mMinuteSpinnerInput.setImeOptions(EditorInfo.IME_ACTION_NEXT);
 
         // Get the localized am/pm strings and use them in the spinner.
@@ -173,13 +173,13 @@
                     onTimeChanged();
                 }
             });
-            mAmPmSpinnerInput = (EditText) mAmPmSpinner.findViewById(R.id.numberpicker_input);
+            mAmPmSpinnerInput = mAmPmSpinner.findViewById(R.id.numberpicker_input);
             mAmPmSpinnerInput.setImeOptions(EditorInfo.IME_ACTION_DONE);
         }
 
         if (isAmPmAtStart()) {
             // Move the am/pm view to the beginning
-            ViewGroup amPmParent = (ViewGroup) delegator.findViewById(R.id.timePickerLayout);
+            ViewGroup amPmParent = delegator.findViewById(R.id.timePickerLayout);
             amPmParent.removeView(amPmView);
             amPmParent.addView(amPmView, 0);
             // Swap layout margins if needed. They may be not symmetrical (Old Standard Theme
diff --git a/core/java/android/widget/Toast.java b/core/java/android/widget/Toast.java
index 789e60b..bf0601d 100644
--- a/core/java/android/widget/Toast.java
+++ b/core/java/android/widget/Toast.java
@@ -299,7 +299,7 @@
         if (mNextView == null) {
             throw new RuntimeException("This Toast was not created with Toast.makeText()");
         }
-        TextView tv = (TextView) mNextView.findViewById(com.android.internal.R.id.message);
+        TextView tv = mNextView.findViewById(com.android.internal.R.id.message);
         if (tv == null) {
             throw new RuntimeException("This Toast was not created with Toast.makeText()");
         }
diff --git a/core/java/android/widget/ZoomButtonsController.java b/core/java/android/widget/ZoomButtonsController.java
index 69b79971..1a3ca86 100644
--- a/core/java/android/widget/ZoomButtonsController.java
+++ b/core/java/android/widget/ZoomButtonsController.java
@@ -264,7 +264,7 @@
                 .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
         inflater.inflate(com.android.internal.R.layout.zoom_container, container);
 
-        mControls = (ZoomControls) container.findViewById(com.android.internal.R.id.zoomControls);
+        mControls = container.findViewById(com.android.internal.R.id.zoomControls);
         mControls.setOnZoomInClickListener(new OnClickListener() {
             public void onClick(View v) {
                 dismissControlsDelayed(ZOOM_CONTROLS_TIMEOUT);
diff --git a/core/java/com/android/internal/widget/WatchHeaderListView.java b/core/java/com/android/internal/widget/WatchHeaderListView.java
index 4fd19c3..53fa7ab 100644
--- a/core/java/com/android/internal/widget/WatchHeaderListView.java
+++ b/core/java/com/android/internal/widget/WatchHeaderListView.java
@@ -92,13 +92,14 @@
     }
 
     @Override
-    protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
+    protected <T extends View> T findViewByPredicateTraversal(
+            Predicate<View> predicate, View childToSkip) {
         View v = super.findViewByPredicateTraversal(predicate, childToSkip);
         if (v == null && mTopPanel != null && mTopPanel != childToSkip
                 && !mTopPanel.isRootNamespace()) {
-            return mTopPanel.findViewByPredicate(predicate);
+            return (T) mTopPanel.findViewByPredicate(predicate);
         }
-        return v;
+        return (T) v;
     }
 
     @Override
diff --git a/core/res/res/values-mcc704-mnc01/config.xml b/core/res/res/values-mcc704-mnc01/config.xml
new file mode 100644
index 0000000..10b6470
--- /dev/null
+++ b/core/res/res/values-mcc704-mnc01/config.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2016, 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 my 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>
+    <!-- Do not translate. Defines the slots is Two Digit Number for dialing normally not USSD -->
+    <string-array name="config_twoDigitNumberPattern">
+        <item>"*1"</item>
+        <item>"*5"</item>
+        <item>"*9"</item>
+    </string-array>
+</resources>
diff --git a/core/res/res/values-mcc708-mnc001/config.xml b/core/res/res/values-mcc708-mnc001/config.xml
new file mode 100755
index 0000000..7b7c48d
--- /dev/null
+++ b/core/res/res/values-mcc708-mnc001/config.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2016, 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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+     for different hardware and product builds. -->
+<resources>
+    <string-array translatable="false" name="config_twoDigitNumberPattern">
+        <item>"*1"</item>
+        <item>"*5"</item>
+    </string-array>
+</resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index ac8c896..2ab0914 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -4460,4 +4460,6 @@
     <!-- Category title for apps which are primarily productivity apps, such as cloud storage or workplace apps. [CHAR LIMIT=32] -->
     <string name="app_category_productivity">Productivity</string>
 
+    <!-- Channel name for DeviceStorageMonitor notifications -->
+    <string name="device_storage_monitor_notification_channel">Device storage</string>
 </resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 643dd02..15011c8 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1880,6 +1880,7 @@
   <java-symbol type="string" name="data_usage_wifi_limit_snoozed_title" />
   <java-symbol type="string" name="data_usage_wifi_limit_title" />
   <java-symbol type="string" name="default_wallpaper_component" />
+  <java-symbol type="string" name="device_storage_monitor_notification_channel" />
   <java-symbol type="string" name="dlg_ok" />
   <java-symbol type="string" name="dump_heap_notification" />
   <java-symbol type="string" name="dump_heap_notification_detail" />
diff --git a/core/tests/coretests/src/android/view/ViewInvalidateTest.java b/core/tests/coretests/src/android/view/ViewInvalidateTest.java
index 4db70ec..9de7d9c 100644
--- a/core/tests/coretests/src/android/view/ViewInvalidateTest.java
+++ b/core/tests/coretests/src/android/view/ViewInvalidateTest.java
@@ -219,7 +219,27 @@
     public void testInvalidateChild_childHardwareLayer() throws Throwable {
         WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mParent, () -> {
             // do in runnable, so tree won't be dirty
-            mChild.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+            mParent.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+        });
+
+        mActivityRule.runOnUiThread(() -> {
+            validateInvalFlags(mParent,
+                    View.PFLAG_DRAWING_CACHE_VALID,
+                    View.PFLAG_DRAWN);
+
+            mParent.invalidateChild(mChild, new Rect(0, 0, 1, 1));
+
+            validateInvalFlags(mParent,
+                    View.PFLAG_DIRTY,
+                    View.PFLAG_DRAWN); // Note: note invalidated, since HW damage handled in native
+        });
+    }
+
+    @Test
+    public void testInvalidateChild_childSoftwareLayer() throws Throwable {
+        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mParent, () -> {
+            // do in runnable, so tree won't be dirty
+            mParent.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
         });
 
         mActivityRule.runOnUiThread(() -> {
@@ -232,7 +252,7 @@
             validateInvalFlags(mParent,
                     View.PFLAG_DIRTY,
                     View.PFLAG_DRAWN,
-                    View.PFLAG_INVALIDATED);
+                    View.PFLAG_INVALIDATED); // Note: invalidated, since SW damage handled here
         });
     }
 
diff --git a/libs/hwui/tests/common/scenes/SaveLayer2Animation.cpp b/libs/hwui/tests/common/scenes/SaveLayer2Animation.cpp
new file mode 100644
index 0000000..ad0b1f1
--- /dev/null
+++ b/libs/hwui/tests/common/scenes/SaveLayer2Animation.cpp
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "TestSceneBase.h"
+#include <string>
+#include <hwui/Paint.h>
+#include <minikin/Layout.h>
+
+class SaveLayer2Animation;
+
+static TestScene::Registrar _SaveLayer(TestScene::Info{
+    "savelayer2",
+    "Interleaving 20 drawText/drawRect ops with saveLayer"
+    "Tests the clipped saveLayer performance and FBO switching overhead.",
+    TestScene::simpleCreateScene<SaveLayer2Animation>
+});
+
+class SaveLayer2Animation : public TestScene {
+public:
+    Paint mBluePaint;
+    Paint mGreenPaint;
+
+    void createContent(int width, int height, Canvas& canvas) override {
+        canvas.drawColor(SkColorSetARGB(255, 255, 0, 0), SkBlendMode::kSrcOver);
+        SkIRect bounds = SkIRect::MakeWH(width, height);
+        int regions = 20;
+        int smallRectHeight = (bounds.height()/regions);
+        int padding = smallRectHeight / 4;
+        int top = bounds.fTop;
+
+        mBluePaint.setColor(SkColorSetARGB(255, 0, 0, 255));
+        mBluePaint.setTextSize(padding);
+        mGreenPaint.setColor(SkColorSetARGB(255, 0, 255, 0));
+        mGreenPaint.setTextSize(padding);
+
+        //interleave drawText and drawRect with saveLayer ops
+        for (int i = 0; i < regions; i++, top += smallRectHeight) {
+            canvas.saveLayer(bounds.fLeft, top, bounds.fRight, top + padding,
+                    &mBluePaint, SaveFlags::ClipToLayer | SaveFlags::MatrixClip);
+            canvas.drawColor(SkColorSetARGB(255, 255, 255, 0), SkBlendMode::kSrcOver);
+            std::string stri = std::to_string(i);
+            std::string offscreen = "offscreen line " + stri;
+            std::unique_ptr<uint16_t[]> offtext = TestUtils::asciiToUtf16(offscreen.c_str());
+            canvas.drawText(offtext.get(), 0, offscreen.length(), offscreen.length(),
+                    bounds.fLeft, top + padding, minikin::kBidi_Force_LTR, mBluePaint, nullptr);
+            canvas.restore();
+
+            canvas.drawRect(bounds.fLeft, top + padding, bounds.fRight,
+                    top + smallRectHeight - padding, mBluePaint);
+            std::string onscreen = "onscreen line " + stri;
+            std::unique_ptr<uint16_t[]> ontext = TestUtils::asciiToUtf16(onscreen.c_str());
+            canvas.drawText(ontext.get(), 0, onscreen.length(), onscreen.length(), bounds.fLeft,
+                    top + smallRectHeight - padding, minikin::kBidi_Force_LTR, mGreenPaint,
+                    nullptr);
+        }
+    }
+    void doFrame(int frameNr) override {
+    }
+};
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationGutsTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationGutsTest.java
index 166fcb1..3e0d15d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationGutsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationGutsTest.java
@@ -63,6 +63,7 @@
     private static final String TEST_CHANNEL = "test_channel";
     private static final String TEST_CHANNEL_NAME = "TEST CHANNEL NAME";
 
+    private NotificationGuts mNotificationGuts;
     private NotificationInfo mNotificationInfo;
     private final INotificationManager mMockINotificationManager = mock(INotificationManager.class);
     private final PackageManager mMockPackageManager = mock(PackageManager.class);
@@ -78,6 +79,9 @@
                 LayoutInflater.from(InstrumentationRegistry.getTargetContext());
         mNotificationInfo = (NotificationInfo) layoutInflater.inflate(R.layout.notification_info,
                 null);
+        mNotificationGuts = (NotificationGuts) layoutInflater.inflate(R.layout.notification_guts,
+                null);
+        mNotificationInfo.setInteractionListener(mNotificationGuts);
 
         // PackageManager must return a packageInfo and applicationInfo.
         final PackageInfo packageInfo = new PackageInfo();
@@ -198,37 +202,38 @@
 
     @Test
     @UiThreadTest
-    public void testCloseControls_DoesNotUpdateNotificationChannelIfUnchanged() throws Exception {
+    public void testSaveImportance_DoesNotUpdateNotificationChannelIfUnchanged() throws Exception {
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 mMockStatusBarNotification, mNotificationChannel, null, null, null);
 
-        mNotificationInfo.closeControls();
+        mNotificationInfo.saveImportance();
         verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
                 anyString(), anyInt(), any());
     }
 
     @Test
     @UiThreadTest
-    public void testCloseControls_DoesNotUpdateNotificationChannelIfUnspecified() throws Exception {
+    public void testSaveImportance_DoesNotUpdateNotificationChannelIfUnspecified()
+            throws Exception {
         mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_UNSPECIFIED);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 mMockStatusBarNotification, mNotificationChannel, null, null, null);
 
-        mNotificationInfo.closeControls();
+        mNotificationInfo.saveImportance();
         verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
                 anyString(), anyInt(), any());
     }
 
     @Test
     @UiThreadTest
-    public void testCloseControls_CallsUpdateNotificationChannelIfChanged() throws Exception {
+    public void testSaveImportance_CallsUpdateNotificationChannelIfChanged() throws Exception {
         mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 mMockStatusBarNotification, mNotificationChannel, null, null, null);
 
         RadioButton highButton = (RadioButton) mNotificationInfo.findViewById(R.id.high_importance);
         highButton.setChecked(true);
-        mNotificationInfo.closeControls();
+        mNotificationInfo.saveImportance();
         verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
                 eq(TEST_PACKAGE_NAME), anyInt(), eq(mNotificationChannel));
         assertEquals(NotificationManager.IMPORTANCE_HIGH, mNotificationChannel.getImportance());
@@ -236,20 +241,6 @@
 
     @Test
     @UiThreadTest
-    public void testCloseControls_DoesNotUpdateNotificationChannelIfSaveFalse() throws Exception {
-        mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
-        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                mMockStatusBarNotification, mNotificationChannel, null, null, null);
-
-        RadioButton highButton = (RadioButton) mNotificationInfo.findViewById(R.id.high_importance);
-        highButton.setChecked(true);
-        mNotificationInfo.closeControls();
-        verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
-                anyString(), anyInt(), any());
-    }
-
-    @Test
-    @UiThreadTest
     public void testEnabledSwitchOnByDefault() throws Exception {
         mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
@@ -292,7 +283,7 @@
 
         Switch enabledSwitch = (Switch) mNotificationInfo.findViewById(R.id.channel_enabled_switch);
         enabledSwitch.setChecked(false);
-        mNotificationInfo.closeControls();
+        mNotificationInfo.saveImportance();
         verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
                 eq(TEST_PACKAGE_NAME), anyInt(), eq(mNotificationChannel));
     }
@@ -308,7 +299,7 @@
         RadioButton lowButton = (RadioButton) mNotificationInfo.findViewById(R.id.low_importance);
         lowButton.setChecked(true);
         enabledSwitch.setChecked(false);
-        mNotificationInfo.closeControls();
+        mNotificationInfo.saveImportance();
         assertEquals(NotificationManager.IMPORTANCE_NONE, mNotificationChannel.getImportance());
     }
 }
diff --git a/services/core/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java
index 8f99127..6f2f2c4 100644
--- a/services/core/java/com/android/server/UiModeManagerService.java
+++ b/services/core/java/com/android/server/UiModeManagerService.java
@@ -35,10 +35,12 @@
 import android.os.BatteryManager;
 import android.os.Binder;
 import android.os.Handler;
-import android.os.IBinder;
 import android.os.PowerManager;
 import android.os.RemoteException;
+import android.os.ResultReceiver;
 import android.os.ServiceManager;
+import android.os.ShellCallback;
+import android.os.ShellCommand;
 import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.provider.Settings;
@@ -47,8 +49,6 @@
 import android.service.vr.IVrStateCallbacks;
 import android.text.TextUtils;
 import android.util.Slog;
-import android.view.WindowManagerInternal;
-import android.view.WindowManagerPolicy;
 
 import java.io.File;
 import java.io.FileDescriptor;
@@ -62,7 +62,6 @@
 import com.android.server.twilight.TwilightListener;
 import com.android.server.twilight.TwilightManager;
 import com.android.server.twilight.TwilightState;
-import com.android.server.wm.WindowManagerService;
 
 final class UiModeManagerService extends SystemService {
     private static final String TAG = UiModeManager.class.getSimpleName();
@@ -238,7 +237,7 @@
         publishBinderService(Context.UI_MODE_SERVICE, mService);
     }
 
-    private final IBinder mService = new IUiModeManager.Stub() {
+    private final IUiModeManager.Stub mService = new IUiModeManager.Stub() {
         @Override
         public void enableCarMode(int flags) {
             if (isUiModeLocked()) {
@@ -390,6 +389,12 @@
         }
 
         @Override
+        public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
+                String[] args, ShellCallback callback, ResultReceiver resultReceiver) {
+            new Shell(mService).exec(mService, in, out, err, args, callback, resultReceiver);
+        }
+
+        @Override
         protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
             if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
                     != PackageManager.PERMISSION_GRANTED) {
@@ -777,4 +782,101 @@
         }
     }
 
+    /**
+     * Handles "adb shell" commands.
+     */
+    private static class Shell extends ShellCommand {
+        public static final String NIGHT_MODE_STR_YES = "yes";
+        public static final String NIGHT_MODE_STR_NO = "no";
+        public static final String NIGHT_MODE_STR_AUTO = "auto";
+        public static final String NIGHT_MODE_STR_UNKNOWN = "unknown";
+        private final IUiModeManager mInterface;
+
+        Shell(IUiModeManager iface) {
+            mInterface = iface;
+        }
+
+        @Override
+        public void onHelp() {
+            final PrintWriter pw = getOutPrintWriter();
+            pw.println("UiModeManager service (uimode) commands:");
+            pw.println("  help");
+            pw.println("    Print this help text.");
+            pw.println("  night [yes|no|auto]");
+            pw.println("    Set or read night mode.");
+        }
+
+        @Override
+        public int onCommand(String cmd) {
+            if (cmd == null) {
+                return handleDefaultCommands(cmd);
+            }
+
+            try {
+                switch (cmd) {
+                    case "night":
+                        return handleNightMode();
+                    default:
+                        return handleDefaultCommands(cmd);
+                }
+            } catch (RemoteException e) {
+                final PrintWriter err = getErrPrintWriter();
+                err.println("Remote exception: " + e);
+            }
+            return -1;
+        }
+
+        private int handleNightMode() throws RemoteException {
+            final PrintWriter err = getErrPrintWriter();
+            final String modeStr = getNextArg();
+            if (modeStr == null) {
+                printCurrentNightMode();
+                return 0;
+            }
+
+            final int mode = strToNightMode(modeStr);
+            if (mode >= 0) {
+                mInterface.setNightMode(mode);
+                printCurrentNightMode();
+                return 0;
+            } else {
+                err.println("Error: mode must be '" + NIGHT_MODE_STR_YES + "', '"
+                        + NIGHT_MODE_STR_NO + "', or '" + NIGHT_MODE_STR_AUTO + "'");
+                return -1;
+            }
+        }
+
+        private void printCurrentNightMode() throws RemoteException {
+            final PrintWriter pw = getOutPrintWriter();
+            final int currMode = mInterface.getNightMode();
+            final String currModeStr = nightModeToStr(currMode);
+            pw.println("Night mode: " + currModeStr);
+        }
+
+        private static String nightModeToStr(int mode) {
+            switch (mode) {
+                case UiModeManager.MODE_NIGHT_YES:
+                    return NIGHT_MODE_STR_YES;
+                case UiModeManager.MODE_NIGHT_NO:
+                    return NIGHT_MODE_STR_NO;
+                case UiModeManager.MODE_NIGHT_AUTO:
+                    return NIGHT_MODE_STR_AUTO;
+                default:
+                    return NIGHT_MODE_STR_UNKNOWN;
+            }
+        }
+
+        private static int strToNightMode(String modeStr) {
+            switch (modeStr) {
+                case NIGHT_MODE_STR_YES:
+                    return UiModeManager.MODE_NIGHT_YES;
+                case NIGHT_MODE_STR_NO:
+                    return UiModeManager.MODE_NIGHT_NO;
+                case NIGHT_MODE_STR_AUTO:
+                    return UiModeManager.MODE_NIGHT_AUTO;
+                default:
+                    return -1;
+            }
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index b82999e..a835976 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -4559,18 +4559,18 @@
                 mHandler.post(new Runnable() {
                     @Override
                     public void run() {
-                        notifyEnqueued(info, sbnToPost, importance, fromUser);
+                        notifyEnqueued(info, sbnToPost);
                     }
                 });
             }
         }
 
         private void notifyEnqueued(final ManagedServiceInfo info,
-                final StatusBarNotification sbn, int importance, boolean fromUser) {
+                final StatusBarNotification sbn) {
             final INotificationListener assistant = (INotificationListener) info.service;
             StatusBarNotificationHolder sbnHolder = new StatusBarNotificationHolder(sbn);
             try {
-                assistant.onNotificationEnqueued(sbnHolder, importance, fromUser);
+                assistant.onNotificationEnqueued(sbnHolder);
             } catch (RemoteException ex) {
                 Log.e(TAG, "unable to notify assistant (enqueued): " + assistant, ex);
             }
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index add2c66..24ab3c7 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -16484,13 +16484,13 @@
             Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
         }
 
-        // Ephemeral apps must have target SDK >= O.
-        // TODO: Update conditional and error message when O gets locked down
-        if (ephemeral && pkg.applicationInfo.targetSdkVersion <= Build.VERSION_CODES.N_MR1) {
-            res.setError(PackageManager.INSTALL_FAILED_EPHEMERAL_INVALID,
-                    "Ephemeral apps must have target SDK version of at least O");
-            return;
-        }
+//        // Ephemeral apps must have target SDK >= O.
+//        // TODO: Update conditional and error message when O gets locked down
+//        if (ephemeral && pkg.applicationInfo.targetSdkVersion <= Build.VERSION_CODES.N_MR1) {
+//            res.setError(PackageManager.INSTALL_FAILED_EPHEMERAL_INVALID,
+//                    "Ephemeral apps must have target SDK version of at least O");
+//            return;
+//        }
 
         if (pkg.applicationInfo.isStaticSharedLibrary()) {
             // Static shared libraries have synthetic package names
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 4350ed9..d623051 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -261,6 +261,9 @@
     // No longer recommended for desk docks;
     static final boolean ENABLE_DESK_DOCK_HOME_CAPTURE = false;
 
+    // Whether to allow devices placed in vr headset viewers to have an alternative Home intent.
+    static final boolean ENABLE_VR_HEADSET_HOME_CAPTURE = true;
+
     static final boolean ALTERNATE_CAR_MODE_NAV_SIZE = false;
 
     static final int SHORT_PRESS_POWER_NOTHING = 0;
@@ -684,6 +687,7 @@
     Intent mHomeIntent;
     Intent mCarDockIntent;
     Intent mDeskDockIntent;
+    Intent mVrHeadsetHomeIntent;
     boolean mSearchKeyShortcutPending;
     boolean mConsumeSearchKeyUp;
     boolean mAssistKeyLongPressed;
@@ -1791,6 +1795,10 @@
         mDeskDockIntent.addCategory(Intent.CATEGORY_DESK_DOCK);
         mDeskDockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+        mVrHeadsetHomeIntent =  new Intent(Intent.ACTION_MAIN, null);
+        mVrHeadsetHomeIntent.addCategory(Intent.CATEGORY_VR_HOME);
+        mVrHeadsetHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+                | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
 
         mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
         mBroadcastWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
@@ -7392,6 +7400,10 @@
                         || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK)) {
             // Always launch dock home from home when watch is docked, if it exists.
             intent = mDeskDockIntent;
+        } else if (mUiMode == Configuration.UI_MODE_TYPE_VR_HEADSET) {
+            if (ENABLE_VR_HEADSET_HOME_CAPTURE) {
+                intent = mVrHeadsetHomeIntent;
+            }
         }
 
         if (intent == null) {
diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java
index b215998..c31369e 100644
--- a/services/core/java/com/android/server/power/Notifier.java
+++ b/services/core/java/com/android/server/power/Notifier.java
@@ -22,6 +22,8 @@
 
 import com.android.internal.app.IAppOpsService;
 import com.android.internal.app.IBatteryStats;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.server.EventLogTags;
 import com.android.server.LocalServices;
 
@@ -32,6 +34,7 @@
 import android.media.AudioManager;
 import android.media.Ringtone;
 import android.media.RingtoneManager;
+import android.metrics.LogMaker;
 import android.net.Uri;
 import android.os.BatteryStats;
 import android.os.Handler;
@@ -401,6 +404,10 @@
                 mHandler.post(new Runnable() {
                     @Override
                     public void run() {
+                        LogMaker log = new LogMaker(MetricsEvent.SCREEN);
+                        log.setType(MetricsEvent.TYPE_OPEN);
+                        log.setSubtype(0); // not user initiated
+                        MetricsLogger.action(log);
                         EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 1, 0, 0, 0);
                         mPolicy.startedWakingUp();
                     }
@@ -457,6 +464,10 @@
                 mHandler.post(new Runnable() {
                     @Override
                     public void run() {
+                        LogMaker log = new LogMaker(MetricsEvent.SCREEN);
+                        log.setType(MetricsEvent.TYPE_CLOSE);
+                        log.setSubtype(why);
+                        MetricsLogger.action(log);
                         EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 0, why, 0, 0);
                         mPolicy.finishedGoingToSleep(why);
                     }
diff --git a/services/core/java/com/android/server/storage/DeviceStorageMonitorService.java b/services/core/java/com/android/server/storage/DeviceStorageMonitorService.java
index a3837b2..afdec9f 100644
--- a/services/core/java/com/android/server/storage/DeviceStorageMonitorService.java
+++ b/services/core/java/com/android/server/storage/DeviceStorageMonitorService.java
@@ -16,6 +16,7 @@
 
 package com.android.server.storage;
 
+import android.app.NotificationChannel;
 import com.android.server.EventLogTags;
 import com.android.server.SystemService;
 import com.android.server.pm.InstructionSets;
@@ -140,6 +141,8 @@
      */
     static final String SERVICE = "devicestoragemonitor";
 
+    private static final String NOTIFICATION_CHANNEL_ID = SERVICE;
+
     /**
     * Handler that checks the amount of disk space on the device and sends a
     * notification if the device runs low on disk space
@@ -365,7 +368,8 @@
     @Override
     public void onStart() {
         // cache storage thresholds
-        final StorageManager sm = StorageManager.from(getContext());
+        Context context = getContext();
+        final StorageManager sm = StorageManager.from(context);
         mMemLowThreshold = sm.getStorageLowBytes(DATA_PATH);
         mMemFullThreshold = sm.getStorageFullBytes(DATA_PATH);
 
@@ -378,6 +382,21 @@
         mCacheFileDeletedObserver = new CacheFileDeletedObserver();
         mCacheFileDeletedObserver.startWatching();
 
+        // Ensure that the notification channel is set up
+        NotificationManager notificationMgr =
+            (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
+        PackageManager packageManager = context.getPackageManager();
+        boolean isTv = packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK);
+
+        int importance = isTv
+            ? NotificationManager.IMPORTANCE_HIGH   // Do not change: this is TV-specific
+            : NotificationManager.IMPORTANCE_LOW;
+        notificationMgr.createNotificationChannel(
+            new NotificationChannel(NOTIFICATION_CHANNEL_ID,
+                context.getString(
+                    com.android.internal.R.string.device_storage_monitor_notification_channel),
+                importance));
+
         publishBinderService(SERVICE, mRemoteService);
         publishLocalService(DeviceStorageMonitorInternal.class, mLocalService);
     }
@@ -466,7 +485,7 @@
         Intent lowMemIntent = new Intent(StorageManager.ACTION_MANAGE_STORAGE);
         lowMemIntent.putExtra("memory", mFreeMem);
         lowMemIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        NotificationManager mNotificationMgr =
+        NotificationManager notificationMgr =
                 (NotificationManager)context.getSystemService(
                         Context.NOTIFICATION_SERVICE);
         CharSequence title = context.getText(
@@ -488,9 +507,11 @@
                       .bigText(details))
                 .setVisibility(Notification.VISIBILITY_PUBLIC)
                 .setCategory(Notification.CATEGORY_SYSTEM)
+                .setChannel(NOTIFICATION_CHANNEL_ID)
+                .extend(new Notification.TvExtender())
                 .build();
         notification.flags |= Notification.FLAG_NO_CLEAR;
-        mNotificationMgr.notifyAsUser(null, LOW_MEMORY_NOTIFICATION_ID, notification,
+        notificationMgr.notifyAsUser(null, LOW_MEMORY_NOTIFICATION_ID, notification,
                 UserHandle.ALL);
         context.sendStickyBroadcastAsUser(mStorageLowIntent, UserHandle.ALL);
     }
diff --git a/tests/UiBench/AndroidManifest.xml b/tests/UiBench/AndroidManifest.xml
index 07f7617..c20be51 100644
--- a/tests/UiBench/AndroidManifest.xml
+++ b/tests/UiBench/AndroidManifest.xml
@@ -100,6 +100,22 @@
             </intent-filter>
         </activity>
         <activity
+            android:name=".FadingEdgeListActivity"
+            android:label="General/Fading Edge ListView" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="com.android.test.uibench.TEST" />
+            </intent-filter>
+        </activity>
+        <activity
+            android:name=".SaveLayerInterleaveActivity"
+            android:label="General/SaveLayer Animation" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="com.android.test.uibench.TEST" />
+            </intent-filter>
+        </activity>
+        <activity
             android:name=".ClippedListActivity"
             android:label="General/Clipped ListView"
             android:theme="@style/NoActionBar">
diff --git a/tests/UiBench/src/com/android/test/uibench/FadingEdgeListActivity.java b/tests/UiBench/src/com/android/test/uibench/FadingEdgeListActivity.java
new file mode 100644
index 0000000..3241e66
--- /dev/null
+++ b/tests/UiBench/src/com/android/test/uibench/FadingEdgeListActivity.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2017 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.test.uibench;
+
+import android.support.v4.app.ListFragment;
+import android.widget.ArrayAdapter;
+import android.widget.ListAdapter;
+
+import com.android.test.uibench.listview.CompatListActivity;
+import com.android.test.uibench.listview.FadingEdgeListFragment;
+
+public class FadingEdgeListActivity extends CompatListActivity {
+
+    @Override
+    protected ListAdapter createListAdapter() {
+        return new ArrayAdapter<>(this, android.R.layout.simple_list_item_1,
+                TextUtils.buildSimpleStringList(40));
+    }
+
+    @Override
+    protected ListFragment createListFragment() {
+        return (ListFragment)new FadingEdgeListFragment();
+    }
+}
diff --git a/tests/UiBench/src/com/android/test/uibench/SaveLayerInterleaveActivity.java b/tests/UiBench/src/com/android/test/uibench/SaveLayerInterleaveActivity.java
new file mode 100644
index 0000000..eec91cb
--- /dev/null
+++ b/tests/UiBench/src/com/android/test/uibench/SaveLayerInterleaveActivity.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2017 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.test.uibench;
+
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.ColorFilter;
+import android.graphics.Paint;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.support.v7.app.AppCompatActivity;
+
+/**
+ * Test Canvas.saveLayer performance by interleaving drawText/drawRect with saveLayer.
+ * This test will be used to measure if drawing interleaved layers at the beginning of a frame will
+ * decrease FBO switching overhead (this is a future optimization in SkiaGL rendering pipeline).
+ */
+public class SaveLayerInterleaveActivity extends AppCompatActivity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        getWindow().setBackgroundDrawable(new Drawable() {
+            private final Paint mBluePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+            private final Paint mGreenPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+
+            @Override
+            public void setAlpha(int alpha) {
+            }
+
+            @Override
+            public int getOpacity() {
+                return PixelFormat.OPAQUE;
+            }
+
+            @Override
+            public void setColorFilter(ColorFilter colorFilter) {
+            }
+
+            @Override
+            public void draw(Canvas canvas) {
+                canvas.drawColor(Color.RED);
+
+                Rect bounds = getBounds();
+                int regions = 20;
+                int smallRectHeight = (bounds.height()/regions);
+                int padding = smallRectHeight / 4;
+                int top = bounds.top;
+                mBluePaint.setColor(Color.BLUE);
+                mBluePaint.setTextSize(padding);
+                mGreenPaint.setColor(Color.GREEN);
+                mGreenPaint.setTextSize(padding);
+
+                //interleave drawText and drawRect with saveLayer ops
+                for (int i = 0; i < regions; i++, top += smallRectHeight) {
+                    canvas.saveLayer(bounds.left, top, bounds.right, top + padding,
+                            mBluePaint);
+                    canvas.drawColor(Color.YELLOW);
+                    canvas.drawText("offscreen line "+ i, bounds.left, top + padding,
+                            mBluePaint);
+                    canvas.restore();
+
+                    Rect partX = new Rect(bounds.left, top + padding,
+                            bounds.right,top + smallRectHeight - padding);
+                    canvas.drawRect(partX, mBluePaint);
+                    canvas.drawText("onscreen line "+ i, bounds.left,
+                            top + smallRectHeight - padding, mGreenPaint);
+                }
+
+                invalidateSelf();
+            }
+        });
+    }
+}
diff --git a/tests/UiBench/src/com/android/test/uibench/listview/CompatListActivity.java b/tests/UiBench/src/com/android/test/uibench/listview/CompatListActivity.java
index 214c074..bb7f4a3 100644
--- a/tests/UiBench/src/com/android/test/uibench/listview/CompatListActivity.java
+++ b/tests/UiBench/src/com/android/test/uibench/listview/CompatListActivity.java
@@ -29,11 +29,15 @@
 
         FragmentManager fm = getSupportFragmentManager();
         if (fm.findFragmentById(android.R.id.content) == null) {
-            ListFragment listFragment = new ListFragment();
+            ListFragment listFragment = createListFragment();
             listFragment.setListAdapter(createListAdapter());
             fm.beginTransaction().add(android.R.id.content, listFragment).commit();
         }
     }
 
     protected abstract ListAdapter createListAdapter();
+
+    protected ListFragment createListFragment() {
+        return new ListFragment();
+    }
 }
diff --git a/tests/UiBench/src/com/android/test/uibench/listview/FadingEdgeListFragment.java b/tests/UiBench/src/com/android/test/uibench/listview/FadingEdgeListFragment.java
new file mode 100644
index 0000000..a018b40
--- /dev/null
+++ b/tests/UiBench/src/com/android/test/uibench/listview/FadingEdgeListFragment.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2017 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.test.uibench.listview;
+
+import android.os.Bundle;
+import android.support.v4.app.ListFragment;
+import android.widget.ListView;
+
+public class FadingEdgeListFragment extends ListFragment {
+
+    @Override
+    public void onActivityCreated(Bundle savedInstanceState) {
+        ListView listView = getListView();
+        listView.setVerticalFadingEdgeEnabled(true);
+        listView.setFadingEdgeLength(500);
+        super.onActivityCreated(savedInstanceState);
+    }
+}
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 8cf7a24..dbf8cc1 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -373,6 +373,12 @@
     public String providerFriendlyName;
 
     /**
+     * Flag indicating if this network is provided by a home Passpoint provider or a roaming
+     * Passpoint provider.
+     */
+    public boolean isHomeProviderNetwork;
+
+    /**
      * Roaming Consortium Id list for passpoint credential; identifies a set of networks where
      * passpoint credential will be considered valid
      */
@@ -1891,6 +1897,7 @@
             FQDN = source.FQDN;
             roamingConsortiumIds = source.roamingConsortiumIds.clone();
             providerFriendlyName = source.providerFriendlyName;
+            isHomeProviderNetwork = source.isHomeProviderNetwork;
             preSharedKey = source.preSharedKey;
 
             mNetworkSelectionStatus.copy(source.getNetworkSelectionStatus());
@@ -1971,6 +1978,7 @@
         dest.writeInt(apChannel);
         dest.writeString(FQDN);
         dest.writeString(providerFriendlyName);
+        dest.writeInt(isHomeProviderNetwork ? 1 : 0);
         dest.writeInt(roamingConsortiumIds.length);
         for (long roamingConsortiumId : roamingConsortiumIds) {
             dest.writeLong(roamingConsortiumId);
@@ -2036,6 +2044,7 @@
                 config.apChannel = in.readInt();
                 config.FQDN = in.readString();
                 config.providerFriendlyName = in.readString();
+                config.isHomeProviderNetwork = in.readInt() != 0;
                 int numRoamingConsortiumIds = in.readInt();
                 config.roamingConsortiumIds = new long[numRoamingConsortiumIds];
                 for (int i = 0; i < numRoamingConsortiumIds; i++) {
diff --git a/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java b/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
index ca4d121..f1174b6 100644
--- a/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
+++ b/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
@@ -217,9 +217,9 @@
         return (homeSp == null ? that.homeSp == null : homeSp.equals(that.homeSp))
                 && (credential == null ? that.credential == null
                         : credential.equals(that.credential))
-                && (policy == null) ? that.policy == null : policy.equals(that.policy)
-                && (subscriptionUpdate == null) ? that.subscriptionUpdate == null
-                        : subscriptionUpdate.equals(that.subscriptionUpdate)
+                && (policy == null ? that.policy == null : policy.equals(that.policy))
+                && (subscriptionUpdate == null ? that.subscriptionUpdate == null
+                        : subscriptionUpdate.equals(that.subscriptionUpdate))
                 && isTrustRootCertListEquals(trustRootCertList, that.trustRootCertList)
                 && updateIdentifier == that.updateIdentifier
                 && credentialPriority == that.credentialPriority
diff --git a/wifi/java/android/net/wifi/hotspot2/pps/Policy.java b/wifi/java/android/net/wifi/hotspot2/pps/Policy.java
index b2583d3..bc29402 100644
--- a/wifi/java/android/net/wifi/hotspot2/pps/Policy.java
+++ b/wifi/java/android/net/wifi/hotspot2/pps/Policy.java
@@ -293,13 +293,13 @@
                 && minRoamingDownlinkBandwidth == that.minRoamingDownlinkBandwidth
                 && minRoamingUplinkBandwidth == that.minRoamingUplinkBandwidth
                 && Arrays.equals(excludedSsidList, that.excludedSsidList)
-                && (requiredProtoPortMap == null) ? that.requiredProtoPortMap == null
-                        : requiredProtoPortMap.equals(that.requiredProtoPortMap)
+                && (requiredProtoPortMap == null ? that.requiredProtoPortMap == null
+                        : requiredProtoPortMap.equals(that.requiredProtoPortMap))
                 && maximumBssLoadValue == that.maximumBssLoadValue
-                && (preferredRoamingPartnerList == null) ? that.preferredRoamingPartnerList == null
-                        : preferredRoamingPartnerList.equals(that.preferredRoamingPartnerList)
-                && (policyUpdate == null) ? that.policyUpdate == null
-                        : policyUpdate.equals(that.policyUpdate);
+                && (preferredRoamingPartnerList == null ? that.preferredRoamingPartnerList == null
+                        : preferredRoamingPartnerList.equals(that.preferredRoamingPartnerList))
+                && (policyUpdate == null ? that.policyUpdate == null
+                        : policyUpdate.equals(that.policyUpdate));
     }
 
     /**