Merge "Fix NPE in JobPackageTracker" into nyc-mr1-dev
diff --git a/cmds/bootanimation/audioplay.cpp b/cmds/bootanimation/audioplay.cpp
index dbb76dc..4983b9a 100644
--- a/cmds/bootanimation/audioplay.cpp
+++ b/cmds/bootanimation/audioplay.cpp
@@ -20,6 +20,7 @@
 #include "audioplay.h"
 
 #define CHATTY ALOGD
+#define LOG_TAG "audioplay"
 
 #include <string.h>
 
@@ -114,10 +115,8 @@
     }
     (void)result;
 
-    // create output mix, with environmental reverb specified as a non-required interface
-    const SLInterfaceID ids[1] = {SL_IID_ENVIRONMENTALREVERB};
-    const SLboolean req[1] = {SL_BOOLEAN_FALSE};
-    result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 1, ids, req);
+    // create output mix
+    result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 0, NULL, NULL);
     if (result != SL_RESULT_SUCCESS) {
         ALOGE("sl engine CreateOutputMix failed with result %d", result);
         return false;
@@ -183,6 +182,14 @@
         ALOGE("SetConfiguration failed with result %d", result);
         return false;
     }
+    // use normal performance mode as low latency is not needed. This is not mandatory so
+    // do not bail if we fail
+    SLuint32 performanceMode = SL_ANDROID_PERFORMANCE_NONE;
+    result = (*playerConfig)->SetConfiguration(
+           playerConfig, SL_ANDROID_KEY_PERFORMANCE_MODE, &performanceMode, sizeof(SLuint32));
+    ALOGW_IF(result != SL_RESULT_SUCCESS,
+            "could not set performance mode on player, error %d", result);
+    (void)result;
 
     // realize the player
     result = (*bqPlayerObject)->Realize(bqPlayerObject, SL_BOOLEAN_FALSE);
@@ -264,6 +271,7 @@
                 break;
             case ID_DATA:
                 /* Stop looking for chunks */
+                *oSoundBufSize = chunkHeader->sz;
                 endLoop = true;
                 break;
             default:
@@ -317,7 +325,8 @@
         return false;
     }
 
-    CHATTY("playClip on player %p: buf=%p size=%d", bqPlayerBufferQueue, buf, size);
+    CHATTY("playClip on player %p: buf=%p size=%d nextSize %d",
+           bqPlayerBufferQueue, buf, size, nextSize);
 
     if (nextSize > 0) {
         // here we only enqueue one buffer because it is a long clip,
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 3f15a75..2c5f881 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -4627,11 +4627,12 @@
         if ((activity == null) || (activity.mCurrentConfig == null)) {
             shouldChangeConfig = true;
         } else {
-            // If the new config is the same as the config this Activity
-            // is already running with then don't bother calling
-            // onConfigurationChanged
+            // If the new config is the same as the config this Activity is already
+            // running with and the override config also didn't change, then don't
+            // bother calling onConfigurationChanged.
             int diff = activity.mCurrentConfig.diff(newConfig);
-            if (diff != 0) {
+            if (diff != 0 || !mResourcesManager.isSameResourcesOverrideConfig(activityToken,
+                    amOverrideConfig)) {
                 // Always send the task-level config changes. For system-level configuration, if
                 // this activity doesn't handle any of the config changes, then don't bother
                 // calling onConfigurationChanged as we're going to destroy it.
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index b889c8f..7754244 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -1396,18 +1396,6 @@
         }
 
         public void death(ComponentName name, IBinder service) {
-            ServiceDispatcher.ConnectionInfo old;
-
-            synchronized (this) {
-                old = mActiveConnections.remove(name);
-                if (old == null || old.binder != service) {
-                    // Death for someone different than who we last
-                    // reported...  just ignore it.
-                    return;
-                }
-                old.binder.unlinkToDeath(old.deathMonitor, 0);
-            }
-
             if (mActivityThread != null) {
                 mActivityThread.post(new RunConnection(name, service, 1));
             } else {
@@ -1456,7 +1444,7 @@
                 }
             }
 
-            // If there was an old service, it is not disconnected.
+            // If there was an old service, it is now disconnected.
             if (old != null) {
                 mConnection.onServiceDisconnected(name);
             }
@@ -1467,6 +1455,17 @@
         }
 
         public void doDeath(ComponentName name, IBinder service) {
+            synchronized (this) {
+                ConnectionInfo old = mActiveConnections.get(name);
+                if (old == null || old.binder != service) {
+                    // Death for someone different than who we last
+                    // reported...  just ignore it.
+                    return;
+                }
+                mActiveConnections.remove(name);
+                old.binder.unlinkToDeath(old.deathMonitor, 0);
+            }
+
             mConnection.onServiceDisconnected(name);
         }
 
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index b12ab75..4802b29 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -39,7 +39,6 @@
 import android.media.session.MediaSession;
 import android.net.Uri;
 import android.os.BadParcelableException;
-import android.os.BaseBundle;
 import android.os.Build;
 import android.os.Bundle;
 import android.os.Parcel;
@@ -51,7 +50,9 @@
 import android.text.Spanned;
 import android.text.TextUtils;
 import android.text.style.AbsoluteSizeSpan;
+import android.text.style.BackgroundColorSpan;
 import android.text.style.CharacterStyle;
+import android.text.style.ForegroundColorSpan;
 import android.text.style.RelativeSizeSpan;
 import android.text.style.TextAppearanceSpan;
 import android.util.ArraySet;
@@ -73,7 +74,6 @@
 import java.lang.reflect.Constructor;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 import java.util.Set;
@@ -3706,8 +3706,6 @@
                     emphazisedMode ? getEmphasizedActionLayoutResource()
                             : tombstone ? getActionTombstoneLayoutResource()
                                     : getActionLayoutResource());
-            final Icon ai = action.getIcon();
-            button.setTextViewText(R.id.action0, processLegacyText(action.title));
             if (!tombstone) {
                 button.setOnClickPendingIntent(R.id.action0, action.actionIntent);
             }
@@ -3716,14 +3714,29 @@
                 button.setRemoteInputs(R.id.action0, action.mRemoteInputs);
             }
             if (emphazisedMode) {
-                // change the background color
-                int color = resolveContrastColor();
-                if (oddAction) {
-                    color = NotificationColorUtil.lightenColor(color, 10);
-                }
-                button.setDrawableParameters(R.id.button_holder, true, -1, color,
+                // change the background bgColor
+                int bgColor = mContext.getColor(oddAction ? R.color.notification_action_list
+                        : R.color.notification_action_list_dark);
+                button.setDrawableParameters(R.id.button_holder, true, -1, bgColor,
                         PorterDuff.Mode.SRC_ATOP, -1);
+                CharSequence title = action.title;
+                ColorStateList[] outResultColor = null;
+                if (isLegacy()) {
+                    title = clearColorSpans(title);
+                } else {
+                    outResultColor = new ColorStateList[1];
+                    title = ensureColorSpanContrast(title, bgColor, outResultColor);
+                }
+                button.setTextViewText(R.id.action0, title);
+                if (outResultColor != null && outResultColor[0] != null) {
+                    // We need to set the text color as well since changing a text to uppercase
+                    // clears its spans.
+                    button.setTextColor(R.id.action0, outResultColor[0]);
+                } else if (mN.color != COLOR_DEFAULT) {
+                    button.setTextColor(R.id.action0,resolveContrastColor());
+                }
             } else {
+                button.setTextViewText(R.id.action0, processLegacyText(action.title));
                 if (mN.color != COLOR_DEFAULT) {
                     button.setTextColor(R.id.action0, resolveContrastColor());
                 }
@@ -3732,6 +3745,112 @@
         }
 
         /**
+         * Clears all color spans of a text
+         * @param charSequence the input text
+         * @return the same text but without color spans
+         */
+        private CharSequence clearColorSpans(CharSequence charSequence) {
+            if (charSequence instanceof Spanned) {
+                Spanned ss = (Spanned) charSequence;
+                Object[] spans = ss.getSpans(0, ss.length(), Object.class);
+                SpannableStringBuilder builder = new SpannableStringBuilder(ss.toString());
+                for (Object span : spans) {
+                    Object resultSpan = span;
+                    if (resultSpan instanceof CharacterStyle) {
+                        resultSpan = ((CharacterStyle) span).getUnderlying();
+                    }
+                    if (resultSpan instanceof TextAppearanceSpan) {
+                        TextAppearanceSpan originalSpan = (TextAppearanceSpan) resultSpan;
+                        if (originalSpan.getTextColor() != null) {
+                            resultSpan = new TextAppearanceSpan(
+                                    originalSpan.getFamily(),
+                                    originalSpan.getTextStyle(),
+                                    originalSpan.getTextSize(),
+                                    null,
+                                    originalSpan.getLinkTextColor());
+                        }
+                    } else if (resultSpan instanceof ForegroundColorSpan
+                            || (resultSpan instanceof BackgroundColorSpan)) {
+                        continue;
+                    } else {
+                        resultSpan = span;
+                    }
+                    builder.setSpan(resultSpan, ss.getSpanStart(span), ss.getSpanEnd(span),
+                            ss.getSpanFlags(span));
+                }
+                return builder;
+            }
+            return charSequence;
+        }
+
+        /**
+         * Ensures contrast on color spans against a background color. also returns the color of the
+         * text if a span was found that spans over the whole text.
+         *
+         * @param charSequence the charSequence on which the spans are
+         * @param background the background color to ensure the contrast against
+         * @param outResultColor an array in which a color will be returned as the first element if
+         *                    there exists a full length color span.
+         * @return the contrasted charSequence
+         */
+        private CharSequence ensureColorSpanContrast(CharSequence charSequence, int background,
+                ColorStateList[] outResultColor) {
+            if (charSequence instanceof Spanned) {
+                Spanned ss = (Spanned) charSequence;
+                Object[] spans = ss.getSpans(0, ss.length(), Object.class);
+                SpannableStringBuilder builder = new SpannableStringBuilder(ss.toString());
+                for (Object span : spans) {
+                    Object resultSpan = span;
+                    int spanStart = ss.getSpanStart(span);
+                    int spanEnd = ss.getSpanEnd(span);
+                    boolean fullLength = (spanEnd - spanStart) == charSequence.length();
+                    if (resultSpan instanceof CharacterStyle) {
+                        resultSpan = ((CharacterStyle) span).getUnderlying();
+                    }
+                    if (resultSpan instanceof TextAppearanceSpan) {
+                        TextAppearanceSpan originalSpan = (TextAppearanceSpan) resultSpan;
+                        ColorStateList textColor = originalSpan.getTextColor();
+                        if (textColor != null) {
+                            int[] colors = textColor.getColors();
+                            int[] newColors = new int[colors.length];
+                            for (int i = 0; i < newColors.length; i++) {
+                                newColors[i] = NotificationColorUtil.ensureLargeTextContrast(
+                                        colors[i], background);
+                            }
+                            textColor = new ColorStateList(textColor.getStates().clone(),
+                                    newColors);
+                            resultSpan = new TextAppearanceSpan(
+                                    originalSpan.getFamily(),
+                                    originalSpan.getTextStyle(),
+                                    originalSpan.getTextSize(),
+                                    textColor,
+                                    originalSpan.getLinkTextColor());
+                            if (fullLength) {
+                                outResultColor[0] = new ColorStateList(
+                                        textColor.getStates().clone(), newColors);
+                            }
+                        }
+                    } else if (resultSpan instanceof ForegroundColorSpan) {
+                        ForegroundColorSpan originalSpan = (ForegroundColorSpan) resultSpan;
+                        int foregroundColor = originalSpan.getForegroundColor();
+                        foregroundColor = NotificationColorUtil.ensureLargeTextContrast(
+                                foregroundColor, background);
+                        resultSpan = new ForegroundColorSpan(foregroundColor);
+                        if (fullLength) {
+                            outResultColor[0] = ColorStateList.valueOf(foregroundColor);
+                        }
+                    } else {
+                        resultSpan = span;
+                    }
+
+                    builder.setSpan(resultSpan, spanStart, spanEnd, ss.getSpanFlags(span));
+                }
+                return builder;
+            }
+            return charSequence;
+        }
+
+        /**
          * @return Whether we are currently building a notification from a legacy (an app that
          *         doesn't create material notifications by itself) app.
          */
diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java
index c4673a3..9a9f793 100644
--- a/core/java/android/app/ResourcesManager.java
+++ b/core/java/android/app/ResourcesManager.java
@@ -364,6 +364,26 @@
         return null;
     }
 
+    /**
+     * Check if activity resources have same override config as the provided on.
+     * @param activityToken The Activity that resources should be associated with.
+     * @param overrideConfig The override configuration to be checked for equality with.
+     * @return true if activity resources override config matches the provided one or they are both
+     *         null, false otherwise.
+     */
+    boolean isSameResourcesOverrideConfig(@Nullable IBinder activityToken,
+            @Nullable Configuration overrideConfig) {
+        synchronized (this) {
+            final ActivityResources activityResources
+                    = activityToken != null ? mActivityResourceReferences.get(activityToken) : null;
+            if (activityResources == null) {
+                return overrideConfig == null;
+            } else {
+                return Objects.equals(activityResources.overrideConfig, overrideConfig);
+            }
+        }
+    }
+
     private ActivityResources getOrCreateActivityResourcesStructLocked(
             @NonNull IBinder activityToken) {
         ActivityResources activityResources = mActivityResourceReferences.get(activityToken);
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 9bc0bb4..0601219 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -173,7 +173,8 @@
             in CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes,
             int icon, int logo, int windowFlags, IBinder transferFrom, boolean createIfNeeded);
     void setAppVisibility(IBinder token, boolean visible);
-    void notifyAppStopped(IBinder token, boolean stopped);
+    void notifyAppResumed(IBinder token, boolean wasStopped);
+    void notifyAppStopped(IBinder token);
     void startAppFreezingScreen(IBinder token, int configChanges);
     void stopAppFreezingScreen(IBinder token, boolean force);
     void removeAppToken(IBinder token);
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index 222a040..184544d 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -545,6 +545,13 @@
      * Subsequent calls to {@link #setImageDrawable(Drawable)} will automatically
      * mutate the drawable and apply the specified tint and tint mode using
      * {@link Drawable#setTintList(ColorStateList)}.
+     * <p>
+     * <em>Note:</em> The default tint mode used by this setter is NOT
+     * consistent with the default tint mode used by the
+     * {@link android.R.styleable#ImageView_tint android:tint}
+     * attribute. If the {@code android:tint} attribute is specified, the
+     * default tint mode will be set to {@link PorterDuff.Mode#SRC_ATOP} to
+     * ensure consistency with earlier versions of the platform.
      *
      * @param tint the tint to apply, may be {@code null} to clear tint
      *
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index c33288b..d0d233e 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -2788,6 +2788,18 @@
     }
 
     /**
+     * @hide
+     * Equivalent to calling {@link android.widget.TextView#setTextColor(ColorStateList)}.
+     *
+     * @param viewId The id of the view whose text color should change
+     * @param colors the text colors to set
+     */
+    public void setTextColor(int viewId, @ColorInt ColorStateList colors) {
+        addAction(new ReflectionAction(viewId, "setTextColor", ReflectionAction.COLOR_STATE_LIST,
+                colors));
+    }
+
+    /**
      * Equivalent to calling {@link android.widget.AbsListView#setRemoteViewsAdapter(Intent)}.
      *
      * @param appWidgetId The id of the app widget which contains the specified view. (This
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 5cbd284..d3cb742 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -3255,6 +3255,7 @@
      *
      * @attr ref android.R.styleable#TextView_textColor
      */
+    @android.view.RemotableViewMethod
     public void setTextColor(ColorStateList colors) {
         if (colors == null) {
             throw new NullPointerException();
diff --git a/core/java/com/android/internal/util/NotificationColorUtil.java b/core/java/com/android/internal/util/NotificationColorUtil.java
index 77452ca..4748e6f 100644
--- a/core/java/com/android/internal/util/NotificationColorUtil.java
+++ b/core/java/com/android/internal/util/NotificationColorUtil.java
@@ -271,7 +271,7 @@
      * Finds a text color with sufficient contrast over bg that has the same hue as the original
      * color, assuming it is for large text.
      */
-    private static int ensureLargeTextContrast(int color, int bg) {
+    public static int ensureLargeTextContrast(int color, int bg) {
         return findContrastColor(color, bg, true, 3);
     }
 
diff --git a/core/res/res/drawable/notification_material_action_background_emphasized.xml b/core/res/res/drawable/notification_material_action_background_emphasized.xml
deleted file mode 100644
index b7153ba..0000000
--- a/core/res/res/drawable/notification_material_action_background_emphasized.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 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 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
-  -->
-
-<ripple xmlns:android="http://schemas.android.com/apk/res/android"
-        android:color="@color/ripple_material_dark">
-    <item android:id="@id/mask">
-        <color android:color="@color/white" />
-    </item>
-</ripple>
-
diff --git a/core/res/res/layout/notification_material_action_emphasized.xml b/core/res/res/layout/notification_material_action_emphasized.xml
index 992e43e..1e364cc 100644
--- a/core/res/res/layout/notification_material_action_emphasized.xml
+++ b/core/res/res/layout/notification_material_action_emphasized.xml
@@ -26,9 +26,9 @@
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:gravity="center"
-        android:textColor="#ffffffff"
+        android:textColor="@color/notification_default_color"
         android:singleLine="true"
         android:ellipsize="end"
-        android:background="@drawable/notification_material_action_background_emphasized"
+        android:background="@drawable/notification_material_action_background"
         />
 </FrameLayout>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index a70c4fd..3f889f9 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -3790,7 +3790,10 @@
         <!-- An optional argument to supply a maximum height for this view.
              See {see android.widget.ImageView#setMaxHeight} for details. -->
         <attr name="maxHeight" format="dimension" />
-        <!-- Set a tinting color for the image. By default, the tint will blend using SRC_ATOP mode. -->
+        <!-- The tinting color for the image. By default, the tint will blend using SRC_ATOP mode.
+             Please note that for compatibility reasons, this is NOT consistent with the default
+             SRC_IN tint mode used by {@link android.widget.ImageView#setImageTintList} and by
+             similar tint attributes on other views. -->
         <attr name="tint" format="color" />
         <!-- If true, the image view will be baseline aligned with based on its
              bottom edge. -->
diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml
index 1843475..de86cef 100644
--- a/core/res/res/values/colors.xml
+++ b/core/res/res/values/colors.xml
@@ -140,6 +140,7 @@
     <color name="notification_progress_background_color">@color/secondary_text_material_light</color>
 
     <color name="notification_action_list">#ffeeeeee</color>
+    <color name="notification_action_list_dark">#ffe0e0e0</color>
 
     <!-- Keyguard colors -->
     <color name="keyguard_avatar_frame_color">#ffffffff</color>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 38749f6..516aa18 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2558,6 +2558,7 @@
 
   <java-symbol type="color" name="notification_action_list" />
   <java-symbol type="color" name="notification_material_background_color" />
+  <java-symbol type="color" name="notification_action_list_dark" />
 
   <!-- Resolver target actions -->
   <java-symbol type="array" name="resolver_target_actions_pin" />
diff --git a/docs/html/topic/libraries/support-library/revisions.jd b/docs/html/topic/libraries/support-library/revisions.jd
index 7e78925..ef73d1d 100644
--- a/docs/html/topic/libraries/support-library/revisions.jd
+++ b/docs/html/topic/libraries/support-library/revisions.jd
@@ -6,9 +6,34 @@
 <p>This page provides details about the Support Library package releases.</p>
 
 <div class="toggle-content opened">
-  <p id="rev24-1-0">
+  <p id="rev24-1-1">
     <a href="#" onclick="return toggleContent(this)"><img src=
     "{@docRoot}assets/images/styles/disclosure_up.png" class=
+    "toggle-content-img" alt="">Android Support Library, revision 24.1.1</a>
+    <em>(July 2016)</em>
+  </p>
+
+  <div class="toggle-content-toggleme">
+
+    <p>Fixed issues:</p>
+
+    <ul>
+      <li>Fixes an issue in the 24.1.0 release which affected resource IDs
+      shared between support libraries. This issue caused apps that depended on
+      support libraries with resources (such as design and appcompat) to
+      encounter issues caused by resource ID mismatches.
+      </li>
+    </ul>
+
+  </div>
+</div>
+
+<!-- end of collapsible section: 24.1.1 -->
+
+<div class="toggle-content closed">
+  <p id="rev24-1-0">
+    <a href="#" onclick="return toggleContent(this)"><img src=
+    "{@docRoot}assets/images/styles/disclosure_down.png" class=
     "toggle-content-img" alt="">Android Support Library, revision 24.1.0</a>
     <em>(July 2016)</em>
   </p>
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index 978ca94..f7e9541 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -153,7 +153,7 @@
     <integer name="def_download_manager_recommended_max_bytes_over_mobile">-1</integer>
 
     <!-- Default for Settings.Secure.LONG_PRESS_TIMEOUT_MILLIS -->
-    <integer name="def_long_press_timeout_millis">500</integer>
+    <integer name="def_long_press_timeout_millis">400</integer>
 
     <!-- Default for Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD -->
     <bool name="def_show_ime_with_hard_keyboard">false</bool>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 1928f92..d27f1f8 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -1202,6 +1202,11 @@
                 restriction = UserManager.DISALLOW_CONFIG_VPN;
                 break;
 
+            case Settings.Global.SAFE_BOOT_DISALLOWED:
+                if ("1".equals(value)) return false;
+                restriction = UserManager.DISALLOW_SAFE_BOOT;
+                break;
+
             default:
                 if (setting != null && setting.startsWith(Settings.Global.DATA_ROAMING)) {
                     if ("0".equals(value)) return false;
@@ -2085,7 +2090,7 @@
         }
 
         private final class UpgradeController {
-            private static final int SETTINGS_VERSION = 129;
+            private static final int SETTINGS_VERSION = 130;
 
             private final int mUserId;
 
@@ -2376,6 +2381,32 @@
                     currentVersion = 129;
                 }
 
+                if (currentVersion == 129) {
+                    // default longpress timeout changed from 500 to 400. If unchanged from the old
+                    // default, update to the new default.
+                    final SettingsState systemSecureSettings =
+                            getSecureSettingsLocked(userId);
+                    final String oldValue = systemSecureSettings.getSettingLocked(
+                            Settings.Secure.LONG_PRESS_TIMEOUT).getValue();
+                    if (TextUtils.equals("500", oldValue)) {
+                        systemSecureSettings.insertSettingLocked(
+                                Settings.Secure.LONG_PRESS_TIMEOUT,
+                                String.valueOf(getContext().getResources().getInteger(
+                                        R.integer.def_long_press_timeout_millis)),
+                                SettingsState.SYSTEM_PACKAGE_NAME);
+                    }
+                    currentVersion = 130;
+                }
+
+                if (currentVersion != newVersion) {
+                    Slog.w("SettingsProvider", "warning: upgrading settings database to version "
+                            + newVersion + " left it at "
+                            + currentVersion + " instead; this is probably a bug", new Throwable());
+                    if (DEBUG) {
+                        throw new RuntimeException("db upgrade error");
+                    }
+                }
+
                 // vXXX: Add new settings above this point.
 
                 // Return the current version.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
index 42c9a126..9afb384 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
@@ -137,11 +137,13 @@
 
     private float mNormalBackgroundVisibilityAmount;
     private ValueAnimator mFadeInFromDarkAnimator;
+    private float mDimmedBackgroundFadeInAmount = -1;
     private ValueAnimator.AnimatorUpdateListener mBackgroundVisibilityUpdater
             = new ValueAnimator.AnimatorUpdateListener() {
         @Override
         public void onAnimationUpdate(ValueAnimator animation) {
             setNormalBackgroundVisibilityAmount(mBackgroundNormal.getAlpha());
+            mDimmedBackgroundFadeInAmount = mBackgroundDimmed.getAlpha();
         }
     };
     private AnimatorListenerAdapter mFadeInEndListener = new AnimatorListenerAdapter() {
@@ -149,6 +151,7 @@
         public void onAnimationEnd(Animator animation) {
             super.onAnimationEnd(animation);
             mFadeInFromDarkAnimator = null;
+            mDimmedBackgroundFadeInAmount = -1;
             updateBackground();
         }
     };
@@ -597,7 +600,10 @@
     }
 
     protected void updateBackgroundAlpha(float transformationAmount) {
-        mBgAlpha = isChildInGroup() && mDimmed ? transformationAmount : 1f;
+        mBgAlpha =  isChildInGroup() && mDimmed ? transformationAmount : 1f;
+        if (mDimmedBackgroundFadeInAmount != -1) {
+            mBgAlpha *= mDimmedBackgroundFadeInAmount;
+        }
         mBackgroundDimmed.setAlpha(mBgAlpha);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index 5f6d958..58d402b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -1122,7 +1122,7 @@
         mPrivateLayout.setUserExpanding(userLocked);
         if (mIsSummaryWithChildren) {
             mChildrenContainer.setUserLocked(userLocked);
-            if (userLocked || (!userLocked && !isGroupExpanded())) {
+            if (userLocked || !isGroupExpanded()) {
                 updateBackgroundForGroupState();
             }
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationHeaderViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationHeaderViewWrapper.java
index 7794d5b..3e4c758 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationHeaderViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationHeaderViewWrapper.java
@@ -240,7 +240,11 @@
         // Also, the notification might have been modified during the animation, so background
         // might be null here.
         if (iconDrawable != null) {
-            iconDrawable.mutate().setColorFilter(mIconColorFilter);
+            Drawable d = iconDrawable.mutate();
+            // DrawableContainer ignores the color filter if it's already set, so clear it first to
+            // get it set and invalidated properly.
+            d.setColorFilter(null);
+            d.setColorFilter(mIconColorFilter);
         }
     }
 
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index eb02dc3..752dbd9 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -1249,7 +1249,7 @@
             r.stopped = true;
             r.state = ActivityState.STOPPED;
 
-            mWindowManager.notifyAppStopped(r.appToken, true);
+            mWindowManager.notifyAppStopped(r.appToken);
 
             if (getVisibleBehindActivity() == r) {
                 mStackSupervisor.requestVisibleBehindLocked(r, false);
@@ -2490,7 +2490,7 @@
 
                 // Well the app will no longer be stopped.
                 // Clear app token stopped state in window manager if needed.
-                mWindowManager.notifyAppStopped(next.appToken, false);
+                mWindowManager.notifyAppResumed(next.appToken, next.stopped);
 
                 EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY, next.userId,
                         System.identityHashCode(next), next.task.taskId, next.shortComponentName);
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index 53289be..5252446 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -895,13 +895,15 @@
             throw new IllegalArgumentException("intents are length different than resolvedTypes");
         }
 
+        final int realCallingPid = Binder.getCallingPid();
+        final int realCallingUid = Binder.getCallingUid();
 
         int callingPid;
         if (callingUid >= 0) {
             callingPid = -1;
         } else if (caller == null) {
-            callingPid = Binder.getCallingPid();
-            callingUid = Binder.getCallingUid();
+            callingPid = realCallingPid;
+            callingUid = realCallingUid;
         } else {
             callingPid = callingUid = -1;
         }
@@ -942,7 +944,8 @@
                             i == intents.length - 1 ? bOptions : null);
                     int res = startActivityLocked(caller, intent, null /*ephemeralIntent*/,
                             resolvedTypes[i], aInfo, null /*rInfo*/, null, null, resultTo, null, -1,
-                            callingPid, callingUid, callingPackage, callingPid, callingUid, 0,
+                            callingPid, callingUid, callingPackage,
+                            realCallingPid, realCallingUid, 0,
                             options, false, componentSpecified, outActivity, null, null);
                     if (res < 0) {
                         return res;
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index 698e762..cd5bcd4 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -459,7 +459,7 @@
             }
             // Note the target activity doesn't have to be exported.
 
-            intents[0].setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            intents[0].addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
             intents[0].setSourceBounds(sourceBounds);
 
             return startShortcutIntentsAsPublisher(
diff --git a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
index 0499757..18bc277 100644
--- a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
+++ b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
@@ -333,6 +333,9 @@
         // set, and in that case even if the restriction is lifted, changing it to ON would be
         // wrong.  So just don't do anything in such a case.  If the user hopes to enable location
         // later, they can do it on the Settings UI.
+        // WARNING: Remember that Settings.Global and Settings.Secure are changeable via adb.
+        // To prevent this from happening for a given user restriction, you have to add a check to
+        // SettingsProvider.isGlobalOrSecureSettingRestrictedForUser.
 
         final ContentResolver cr = context.getContentResolver();
         final long id = Binder.clearCallingIdentity();
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 66e9fd86..eac72b0 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -337,21 +337,41 @@
         }
     }
 
-    // Here we destroy surfaces which have been marked as eligible by the animator, taking care
-    // to ensure the client has finished with them. If the client could still be using them
-    // we will skip destruction and try again when the client has stopped.
     void destroySurfaces() {
+        destroySurfaces(false /*cleanupOnResume*/);
+    }
+
+    /**
+     * Destroy surfaces which have been marked as eligible by the animator, taking care to ensure
+     * the client has finished with them.
+     *
+     * @param cleanupOnResume whether this is done when app is resumed without fully stopped. If
+     * set to true, destroy only surfaces of removed windows, and clear relevant flags of the
+     * others so that they are ready to be reused. If set to false (common case), destroy all
+     * surfaces that's eligible, if the app is already stopped.
+     */
+
+    private void destroySurfaces(boolean cleanupOnResume) {
         final ArrayList<WindowState> allWindows = (ArrayList<WindowState>) allAppWindows.clone();
         final DisplayContentList displayList = new DisplayContentList();
         for (int i = allWindows.size() - 1; i >= 0; i--) {
             final WindowState win = allWindows.get(i);
 
-            if (!(mAppStopped || win.mWindowRemovalAllowed)) {
+            if (!(mAppStopped || win.mWindowRemovalAllowed || cleanupOnResume)) {
                 continue;
             }
 
             win.mWinAnimator.destroyPreservedSurfaceLocked();
 
+            if (cleanupOnResume) {
+                // If the window has an unfinished exit animation, consider that animation
+                // done and mark the window destroying so that it goes through the cleanup.
+                if (win.mAnimatingExit) {
+                    win.mDestroying = true;
+                    win.mAnimatingExit = false;
+                }
+            }
+
             if (!win.mDestroying) {
                 continue;
             }
@@ -361,7 +381,9 @@
                     + " win.mWindowRemovalAllowed=" + win.mWindowRemovalAllowed
                     + " win.mRemoveOnExit=" + win.mRemoveOnExit);
 
-            win.destroyOrSaveSurface();
+            if (!cleanupOnResume || win.mRemoveOnExit) {
+                win.destroyOrSaveSurface();
+            }
             if (win.mRemoveOnExit) {
                 service.removeWindowInnerLocked(win);
             }
@@ -379,21 +401,30 @@
     }
 
     /**
-     * If the application has stopped it is okay to destroy any surfaces which were keeping alive
-     * in case they were still being used.
+     * Notify that the app is now resumed, and it was not stopped before, perform a clean
+     * up of the surfaces
      */
-    void notifyAppStopped(boolean stopped) {
-        if (DEBUG_ADD_REMOVE) Slog.v(TAG, "notifyAppStopped: stopped=" + stopped + " " + this);
-        mAppStopped = stopped;
-
-        if (stopped) {
-            destroySurfaces();
-            // Remove any starting window that was added for this app if they are still around.
-            mTask.mService.scheduleRemoveStartingWindowLocked(this);
+    void notifyAppResumed(boolean wasStopped) {
+        if (DEBUG_ADD_REMOVE) Slog.v(TAG, "notifyAppResumed: wasStopped=" + wasStopped + " " + this);
+        mAppStopped = false;
+        if (!wasStopped) {
+            destroySurfaces(true /*cleanupOnResume*/);
         }
     }
 
     /**
+     * Notify that the app has stopped, and it is okay to destroy any surfaces which were
+     * keeping alive in case they were still being used.
+     */
+    void notifyAppStopped() {
+        if (DEBUG_ADD_REMOVE) Slog.v(TAG, "notifyAppStopped: " + this);
+        mAppStopped = true;
+        destroySurfaces();
+        // Remove any starting window that was added for this app if they are still around.
+        mTask.mService.scheduleRemoveStartingWindowLocked(this);
+    }
+
+    /**
      * Checks whether we should save surfaces for this app.
      *
      * @return true if the surfaces should be saved, false otherwise.
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index d8a4538..8c5481d 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -4476,7 +4476,25 @@
     }
 
     @Override
-    public void notifyAppStopped(IBinder token, boolean stopped) {
+    public void notifyAppResumed(IBinder token, boolean wasStopped) {
+        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
+                "notifyAppResumed()")) {
+            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
+        }
+
+        synchronized(mWindowMap) {
+            final AppWindowToken wtoken;
+            wtoken = findAppWindowToken(token);
+            if (wtoken == null) {
+                Slog.w(TAG_WM, "Attempted to notify resumed of non-existing app token: " + token);
+                return;
+            }
+            wtoken.notifyAppResumed(wasStopped);
+        }
+    }
+
+    @Override
+    public void notifyAppStopped(IBinder token) {
         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
                 "notifyAppStopped()")) {
             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
@@ -4486,10 +4504,10 @@
             final AppWindowToken wtoken;
             wtoken = findAppWindowToken(token);
             if (wtoken == null) {
-                Slog.w(TAG_WM, "Attempted to set visibility of non-existing app token: " + token);
+                Slog.w(TAG_WM, "Attempted to notify stopped of non-existing app token: " + token);
                 return;
             }
-            wtoken.notifyAppStopped(stopped);
+            wtoken.notifyAppStopped();
         }
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
index 82ccd36..c0752e0 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
@@ -2613,10 +2613,12 @@
                     "s1",
                     "Title 1",
                     makeComponent(ShortcutActivity.class),
-            /* icon =*/ null,
-                    makeIntent(Intent.ACTION_ASSIST, ShortcutActivity2.class,
-                            "key1", "val1", "nest", makeBundle("key", 123)),
-            /* rank */ 10);
+                    /* icon =*/ null,
+                    new Intent[] {makeIntent(Intent.ACTION_ASSIST, ShortcutActivity2.class,
+                            "key1", "val1", "nest", makeBundle("key", 123))
+                            .setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK),
+                    new Intent("act2").setFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION)},
+                    /* rank */ 10);
 
             final ShortcutInfo s1_2 = makeShortcut(
                     "s2",
@@ -2658,10 +2660,19 @@
         });
 
         runWithCaller(LAUNCHER_1, USER_0, () -> {
-            assertEquals(
-                    ShortcutActivity2.class.getName(),
-                    launchShortcutAndGetIntent(CALLING_PACKAGE_1, "s1", USER_0)
-                            .getComponent().getClassName());
+            final Intent[] intents = launchShortcutAndGetIntents(CALLING_PACKAGE_1, "s1", USER_0);
+            assertEquals(ShortcutActivity2.class.getName(),
+                    intents[0].getComponent().getClassName());
+            assertEquals(Intent.ACTION_ASSIST,
+                    intents[0].getAction());
+            assertEquals(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK,
+                    intents[0].getFlags());
+
+            assertEquals("act2",
+                    intents[1].getAction());
+            assertEquals(Intent.FLAG_ACTIVITY_NO_ANIMATION,
+                    intents[1].getFlags());
+
             assertEquals(
                     ShortcutActivity3.class.getName(),
                     launchShortcutAndGetIntent(CALLING_PACKAGE_1, "s2", USER_0)
@@ -2682,10 +2693,18 @@
 
         runWithCaller(LAUNCHER_1, USER_0, () -> {
             // Not the default launcher, but pinned shortcuts are still lauchable.
-            assertEquals(
-                    ShortcutActivity2.class.getName(),
-                    launchShortcutAndGetIntent(CALLING_PACKAGE_1, "s1", USER_0)
-                            .getComponent().getClassName());
+            final Intent[] intents = launchShortcutAndGetIntents(CALLING_PACKAGE_1, "s1", USER_0);
+            assertEquals(ShortcutActivity2.class.getName(),
+                    intents[0].getComponent().getClassName());
+            assertEquals(Intent.ACTION_ASSIST,
+                    intents[0].getAction());
+            assertEquals(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK,
+                    intents[0].getFlags());
+
+            assertEquals("act2",
+                    intents[1].getAction());
+            assertEquals(Intent.FLAG_ACTIVITY_NO_ANIMATION,
+                    intents[1].getFlags());
             assertEquals(
                     ShortcutActivity3.class.getName(),
                     launchShortcutAndGetIntent(CALLING_PACKAGE_1, "s2", USER_0)
diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
index 49ab9f9..5a9860d 100644
--- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
+++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
@@ -351,7 +351,12 @@
     }
 
     @Override
-    public void notifyAppStopped(IBinder token, boolean stopped) throws RemoteException {
+    public void notifyAppResumed(IBinder token, boolean wasStopped) throws RemoteException {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
+    public void notifyAppStopped(IBinder token) throws RemoteException {
         // TODO Auto-generated method stub
     }