Merge "Tag foreground notis that use certain services"
diff --git a/api/current.txt b/api/current.txt
index 2c41d5d..39187b8 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -13592,7 +13592,7 @@
   }
 
   public class EmbossMaskFilter extends android.graphics.MaskFilter {
-    ctor public EmbossMaskFilter(float[], float, float, float);
+    ctor public deprecated EmbossMaskFilter(float[], float, float, float);
   }
 
   public final class ImageDecoder implements java.lang.AutoCloseable {
@@ -13605,16 +13605,16 @@
     method public static android.graphics.drawable.Drawable decodeDrawable(android.graphics.ImageDecoder.Source, android.graphics.ImageDecoder.OnHeaderDecodedListener) throws java.io.IOException;
     method public static android.graphics.drawable.Drawable decodeDrawable(android.graphics.ImageDecoder.Source) throws java.io.IOException;
     method public android.util.Size getSampledSize(int);
-    method public void setAllocator(int);
-    method public void setAsAlphaMask(boolean);
-    method public void setConserveMemory(boolean);
-    method public void setCrop(android.graphics.Rect);
-    method public void setMutable(boolean);
-    method public void setOnPartialImageListener(android.graphics.ImageDecoder.OnPartialImageListener);
-    method public void setPostProcessor(android.graphics.PostProcessor);
-    method public void setRequireUnpremultiplied(boolean);
-    method public void setResize(int, int);
-    method public void setResize(int);
+    method public android.graphics.ImageDecoder setAllocator(int);
+    method public android.graphics.ImageDecoder setAsAlphaMask(boolean);
+    method public android.graphics.ImageDecoder setConserveMemory(boolean);
+    method public android.graphics.ImageDecoder setCrop(android.graphics.Rect);
+    method public android.graphics.ImageDecoder setMutable(boolean);
+    method public android.graphics.ImageDecoder setOnPartialImageListener(android.graphics.ImageDecoder.OnPartialImageListener);
+    method public android.graphics.ImageDecoder setPostProcessor(android.graphics.PostProcessor);
+    method public android.graphics.ImageDecoder setRequireUnpremultiplied(boolean);
+    method public android.graphics.ImageDecoder setResize(int, int);
+    method public android.graphics.ImageDecoder setResize(int);
     field public static final int ALLOCATOR_DEFAULT = 0; // 0x0
     field public static final int ALLOCATOR_HARDWARE = 3; // 0x3
     field public static final int ALLOCATOR_SHARED_MEMORY = 2; // 0x2
@@ -14816,6 +14816,10 @@
     method public static android.graphics.drawable.Icon createWithResource(android.content.Context, int);
     method public static android.graphics.drawable.Icon createWithResource(java.lang.String, int);
     method public int describeContents();
+    method public int getResId();
+    method public java.lang.String getResPackage();
+    method public int getType();
+    method public android.net.Uri getUri();
     method public android.graphics.drawable.Drawable loadDrawable(android.content.Context);
     method public void loadDrawableAsync(android.content.Context, android.os.Message);
     method public void loadDrawableAsync(android.content.Context, android.graphics.drawable.Icon.OnDrawableLoadedListener, android.os.Handler);
@@ -14824,6 +14828,11 @@
     method public android.graphics.drawable.Icon setTintMode(android.graphics.PorterDuff.Mode);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.graphics.drawable.Icon> CREATOR;
+    field public static final int TYPE_ADAPTIVE_BITMAP = 5; // 0x5
+    field public static final int TYPE_BITMAP = 1; // 0x1
+    field public static final int TYPE_DATA = 3; // 0x3
+    field public static final int TYPE_RESOURCE = 2; // 0x2
+    field public static final int TYPE_URI = 4; // 0x4
   }
 
   public static abstract interface Icon.OnDrawableLoadedListener {
diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp
index 087e596..9b58a14 100644
--- a/cmds/statsd/src/StatsLogProcessor.cpp
+++ b/cmds/statsd/src/StatsLogProcessor.cpp
@@ -74,7 +74,8 @@
       mAnomalyAlarmMonitor(anomalyAlarmMonitor),
       mPeriodicAlarmMonitor(periodicAlarmMonitor),
       mSendBroadcast(sendBroadcast),
-      mTimeBaseSec(timeBaseSec) {
+      mTimeBaseSec(timeBaseSec),
+      mLastLogTimestamp(0) {
     StatsPullerManager statsPullerManager;
     statsPullerManager.SetTimeBaseSec(mTimeBaseSec);
 }
@@ -144,9 +145,12 @@
     }
 }
 
-// TODO: what if statsd service restarts? How do we know what logs are already processed before?
 void StatsLogProcessor::OnLogEvent(LogEvent* event) {
     std::lock_guard<std::mutex> lock(mMetricsMutex);
+    if (event->GetElapsedTimestampNs() < mLastLogTimestamp) {
+        return;
+    }
+    mLastLogTimestamp = event->GetElapsedTimestampNs();
     StatsdStats::getInstance().noteAtomLogged(
         event->GetTagId(), event->GetElapsedTimestampNs() / NS_PER_SEC);
 
diff --git a/cmds/statsd/src/StatsLogProcessor.h b/cmds/statsd/src/StatsLogProcessor.h
index 4d9f185..7a6aa1e 100644
--- a/cmds/statsd/src/StatsLogProcessor.h
+++ b/cmds/statsd/src/StatsLogProcessor.h
@@ -106,6 +106,8 @@
 
     const long mTimeBaseSec;
 
+    int64_t mLastLogTimestamp;
+
     long mLastPullerCacheClearTimeSec = 0;
 
     FRIEND_TEST(StatsLogProcessorTest, TestRateLimitByteSize);
diff --git a/config/hiddenapi-light-greylist.txt b/config/hiddenapi-light-greylist.txt
index 752b662..8d70a55 100644
--- a/config/hiddenapi-light-greylist.txt
+++ b/config/hiddenapi-light-greylist.txt
@@ -659,7 +659,6 @@
 Landroid/graphics/drawable/GradientDrawable$GradientState;->mPadding:Landroid/graphics/Rect;
 Landroid/graphics/drawable/GradientDrawable$GradientState;->mPositions:[F
 Landroid/graphics/drawable/GradientDrawable;->mPadding:Landroid/graphics/Rect;
-Landroid/graphics/drawable/Icon;->getResPackage()Ljava/lang/String;
 Landroid/graphics/drawable/NinePatchDrawable;->mNinePatchState:Landroid/graphics/drawable/NinePatchDrawable$NinePatchState;
 Landroid/graphics/drawable/NinePatchDrawable$NinePatchState;->mNinePatch:Landroid/graphics/NinePatch;
 Landroid/graphics/drawable/StateListDrawable;->extractStateSet(Landroid/util/AttributeSet;)[I
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 872370e..457f945 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -3716,6 +3716,10 @@
         if (localLOGV) Slog.v(TAG, "Performing resume of " + r
                 + " finished=" + r.activity.mFinished);
         if (r != null && !r.activity.mFinished) {
+            if (r.getLifecycleState() == ON_RESUME) {
+                throw new IllegalStateException(
+                        "Trying to resume activity which is already resumed");
+            }
             if (clearHide) {
                 r.hideForNow = false;
                 r.activity.mStartedActivity = false;
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index c5b3a4a..d76a4f9 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -1738,8 +1738,7 @@
      * @param callback Where to report changes.
      * @hide
      */
-    // TODO: Uncomment below annotation once b/73559440 is fixed
-    // @RequiresPermission(value=Manifest.permission.WATCH_APPOPS, conditional=true)
+    @RequiresPermission(value=android.Manifest.permission.WATCH_APPOPS, conditional=true)
     public void startWatchingMode(int op, String packageName, final OnOpChangedListener callback) {
         synchronized (mModeWatchers) {
             IAppOpsCallback cb = mModeWatchers.get(callback);
diff --git a/core/java/android/app/servertransaction/ActivityResultItem.java b/core/java/android/app/servertransaction/ActivityResultItem.java
index 73b5ec4..545463c 100644
--- a/core/java/android/app/servertransaction/ActivityResultItem.java
+++ b/core/java/android/app/servertransaction/ActivityResultItem.java
@@ -16,7 +16,7 @@
 
 package android.app.servertransaction;
 
-import static android.app.servertransaction.ActivityLifecycleItem.ON_PAUSE;
+import static android.app.servertransaction.ActivityLifecycleItem.ON_RESUME;
 import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
 
 import android.app.ClientTransactionHandler;
@@ -38,8 +38,8 @@
     private List<ResultInfo> mResultInfoList;
 
     @Override
-    public int getPreExecutionState() {
-        return ON_PAUSE;
+    public int getPostExecutionState() {
+        return ON_RESUME;
     }
 
     @Override
diff --git a/core/java/android/app/servertransaction/ClientTransactionItem.java b/core/java/android/app/servertransaction/ClientTransactionItem.java
index 6f2cc00..d94f08b 100644
--- a/core/java/android/app/servertransaction/ClientTransactionItem.java
+++ b/core/java/android/app/servertransaction/ClientTransactionItem.java
@@ -32,12 +32,6 @@
  */
 public abstract class ClientTransactionItem implements BaseClientRequest, Parcelable {
 
-    /** Get the state in which this callback can be executed. */
-    @LifecycleState
-    public int getPreExecutionState() {
-        return UNDEFINED;
-    }
-
     /** Get the state that must follow this callback. */
     @LifecycleState
     public int getPostExecutionState() {
diff --git a/core/java/android/app/servertransaction/NewIntentItem.java b/core/java/android/app/servertransaction/NewIntentItem.java
index 7dfde73..e5ce3b0 100644
--- a/core/java/android/app/servertransaction/NewIntentItem.java
+++ b/core/java/android/app/servertransaction/NewIntentItem.java
@@ -38,11 +38,6 @@
 
     // TODO(lifecycler): Switch new intent handling to this scheme.
     /*@Override
-    public int getPreExecutionState() {
-        return ON_PAUSE;
-    }
-
-    @Override
     public int getPostExecutionState() {
         return ON_RESUME;
     }*/
diff --git a/core/java/android/app/servertransaction/TransactionExecutor.java b/core/java/android/app/servertransaction/TransactionExecutor.java
index 059e0af..0e52b34 100644
--- a/core/java/android/app/servertransaction/TransactionExecutor.java
+++ b/core/java/android/app/servertransaction/TransactionExecutor.java
@@ -24,6 +24,7 @@
 import static android.app.servertransaction.ActivityLifecycleItem.ON_START;
 import static android.app.servertransaction.ActivityLifecycleItem.ON_STOP;
 import static android.app.servertransaction.ActivityLifecycleItem.UNDEFINED;
+import static android.app.servertransaction.TransactionExecutorHelper.lastCallbackRequestingState;
 
 import android.app.ActivityThread.ActivityClientRecord;
 import android.app.ClientTransactionHandler;
@@ -48,11 +49,7 @@
 
     private ClientTransactionHandler mTransactionHandler;
     private PendingTransactionActions mPendingActions = new PendingTransactionActions();
-
-    // Temp holder for lifecycle path.
-    // No direct transition between two states should take more than one complete cycle of 6 states.
-    @ActivityLifecycleItem.LifecycleState
-    private IntArray mLifecycleSequence = new IntArray(6);
+    private TransactionExecutorHelper mHelper = new TransactionExecutorHelper();
 
     /** Initialize an instance with transaction handler, that will execute all requested actions. */
     public TransactionExecutor(ClientTransactionHandler clientTransactionHandler) {
@@ -89,13 +86,25 @@
 
         final IBinder token = transaction.getActivityToken();
         ActivityClientRecord r = mTransactionHandler.getActivityClient(token);
+
+        // In case when post-execution state of the last callback matches the final state requested
+        // for the activity in this transaction, we won't do the last transition here and do it when
+        // moving to final state instead (because it may contain additional parameters from server).
+        final ActivityLifecycleItem finalStateRequest = transaction.getLifecycleStateRequest();
+        final int finalState = finalStateRequest != null ? finalStateRequest.getTargetState()
+                : UNDEFINED;
+        // Index of the last callback that requests some post-execution state.
+        final int lastCallbackRequestingState = lastCallbackRequestingState(transaction);
+
         final int size = callbacks.size();
         for (int i = 0; i < size; ++i) {
             final ClientTransactionItem item = callbacks.get(i);
             log("Resolving callback: " + item);
-            final int preExecutionState = item.getPreExecutionState();
-            if (preExecutionState != UNDEFINED) {
-                cycleToPath(r, preExecutionState);
+            final int postExecutionState = item.getPostExecutionState();
+            final int closestPreExecutionState = mHelper.getClosestPreExecutionState(r,
+                    item.getPostExecutionState());
+            if (closestPreExecutionState != UNDEFINED) {
+                cycleToPath(r, closestPreExecutionState);
             }
 
             item.execute(mTransactionHandler, token, mPendingActions);
@@ -105,9 +114,11 @@
                 r = mTransactionHandler.getActivityClient(token);
             }
 
-            final int postExecutionState = item.getPostExecutionState();
-            if (postExecutionState != UNDEFINED) {
-                cycleToPath(r, postExecutionState);
+            if (postExecutionState != UNDEFINED && r != null) {
+                // Skip the very last transition and perform it by explicit state request instead.
+                final boolean shouldExcludeLastTransition =
+                        i == lastCallbackRequestingState && finalState == postExecutionState;
+                cycleToPath(r, postExecutionState, shouldExcludeLastTransition);
             }
         }
     }
@@ -162,15 +173,15 @@
             boolean excludeLastState) {
         final int start = r.getLifecycleState();
         log("Cycle from: " + start + " to: " + finish + " excludeLastState:" + excludeLastState);
-        initLifecyclePath(start, finish, excludeLastState);
-        performLifecycleSequence(r);
+        final IntArray path = mHelper.getLifecyclePath(start, finish, excludeLastState);
+        performLifecycleSequence(r, path);
     }
 
     /** Transition the client through previously initialized state sequence. */
-    private void performLifecycleSequence(ActivityClientRecord r) {
-        final int size = mLifecycleSequence.size();
+    private void performLifecycleSequence(ActivityClientRecord r, IntArray path) {
+        final int size = path.size();
         for (int i = 0, state; i < size; i++) {
-            state = mLifecycleSequence.get(i);
+            state = path.get(i);
             log("Transitioning to state: " + state);
             switch (state) {
                 case ON_CREATE:
@@ -195,8 +206,7 @@
                 case ON_DESTROY:
                     mTransactionHandler.handleDestroyActivity(r.token, false /* finishing */,
                             0 /* configChanges */, false /* getNonConfigInstance */,
-                            "performLifecycleSequence. cycling to:"
-                                    + mLifecycleSequence.get(size - 1));
+                            "performLifecycleSequence. cycling to:" + path.get(size - 1));
                     break;
                 case ON_RESTART:
                     mTransactionHandler.performRestartActivity(r.token, false /* start */);
@@ -207,60 +217,6 @@
         }
     }
 
-    /**
-     * Calculate the path through main lifecycle states for an activity and fill
-     * @link #mLifecycleSequence} with values starting with the state that follows the initial
-     * state.
-     */
-    public void initLifecyclePath(int start, int finish, boolean excludeLastState) {
-        mLifecycleSequence.clear();
-        if (finish >= start) {
-            // just go there
-            for (int i = start + 1; i <= finish; i++) {
-                mLifecycleSequence.add(i);
-            }
-        } else { // finish < start, can't just cycle down
-            if (start == ON_PAUSE && finish == ON_RESUME) {
-                // Special case when we can just directly go to resumed state.
-                mLifecycleSequence.add(ON_RESUME);
-            } else if (start <= ON_STOP && finish >= ON_START) {
-                // Restart and go to required state.
-
-                // Go to stopped state first.
-                for (int i = start + 1; i <= ON_STOP; i++) {
-                    mLifecycleSequence.add(i);
-                }
-                // Restart
-                mLifecycleSequence.add(ON_RESTART);
-                // Go to required state
-                for (int i = ON_START; i <= finish; i++) {
-                    mLifecycleSequence.add(i);
-                }
-            } else {
-                // Relaunch and go to required state
-
-                // Go to destroyed state first.
-                for (int i = start + 1; i <= ON_DESTROY; i++) {
-                    mLifecycleSequence.add(i);
-                }
-                // Go to required state
-                for (int i = ON_CREATE; i <= finish; i++) {
-                    mLifecycleSequence.add(i);
-                }
-            }
-        }
-
-        // Remove last transition in case we want to perform it with some specific params.
-        if (excludeLastState && mLifecycleSequence.size() != 0) {
-            mLifecycleSequence.remove(mLifecycleSequence.size() - 1);
-        }
-    }
-
-    @VisibleForTesting
-    public int[] getLifecycleSequence() {
-        return mLifecycleSequence.toArray();
-    }
-
     private static void log(String message) {
         if (DEBUG_RESOLVER) Slog.d(TAG, message);
     }
diff --git a/core/java/android/app/servertransaction/TransactionExecutorHelper.java b/core/java/android/app/servertransaction/TransactionExecutorHelper.java
new file mode 100644
index 0000000..7e66fd7
--- /dev/null
+++ b/core/java/android/app/servertransaction/TransactionExecutorHelper.java
@@ -0,0 +1,225 @@
+/*
+ * Copyright 2018 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.app.servertransaction;
+
+import static android.app.servertransaction.ActivityLifecycleItem.ON_CREATE;
+import static android.app.servertransaction.ActivityLifecycleItem.ON_DESTROY;
+import static android.app.servertransaction.ActivityLifecycleItem.ON_PAUSE;
+import static android.app.servertransaction.ActivityLifecycleItem.ON_RESTART;
+import static android.app.servertransaction.ActivityLifecycleItem.ON_RESUME;
+import static android.app.servertransaction.ActivityLifecycleItem.ON_START;
+import static android.app.servertransaction.ActivityLifecycleItem.ON_STOP;
+import static android.app.servertransaction.ActivityLifecycleItem.PRE_ON_CREATE;
+import static android.app.servertransaction.ActivityLifecycleItem.UNDEFINED;
+
+import android.app.ActivityThread;
+import android.util.IntArray;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.util.List;
+
+/**
+ * Helper class for {@link TransactionExecutor} that contains utils for lifecycle path resolution.
+ * @hide
+ */
+public class TransactionExecutorHelper {
+    // A penalty applied to path with destruction when looking for the shortest one.
+    private static final int DESTRUCTION_PENALTY = 10;
+
+    private static final int[] ON_RESUME_PRE_EXCUTION_STATES = new int[] { ON_START, ON_PAUSE };
+
+    // Temp holder for lifecycle path.
+    // No direct transition between two states should take more than one complete cycle of 6 states.
+    @ActivityLifecycleItem.LifecycleState
+    private IntArray mLifecycleSequence = new IntArray(6);
+
+    /**
+     * Calculate the path through main lifecycle states for an activity and fill
+     * @link #mLifecycleSequence} with values starting with the state that follows the initial
+     * state.
+     * <p>NOTE: The returned value is used internally in this class and is not a copy. It's contents
+     * may change after calling other methods of this class.</p>
+     */
+    @VisibleForTesting
+    public IntArray getLifecyclePath(int start, int finish, boolean excludeLastState) {
+        if (start == UNDEFINED || finish == UNDEFINED) {
+            throw new IllegalArgumentException("Can't resolve lifecycle path for undefined state");
+        }
+        if (start == ON_RESTART || finish == ON_RESTART) {
+            throw new IllegalArgumentException(
+                    "Can't start or finish in intermittent RESTART state");
+        }
+        if (finish == PRE_ON_CREATE && start != finish) {
+            throw new IllegalArgumentException("Can only start in pre-onCreate state");
+        }
+
+        mLifecycleSequence.clear();
+        if (finish >= start) {
+            // just go there
+            for (int i = start + 1; i <= finish; i++) {
+                mLifecycleSequence.add(i);
+            }
+        } else { // finish < start, can't just cycle down
+            if (start == ON_PAUSE && finish == ON_RESUME) {
+                // Special case when we can just directly go to resumed state.
+                mLifecycleSequence.add(ON_RESUME);
+            } else if (start <= ON_STOP && finish >= ON_START) {
+                // Restart and go to required state.
+
+                // Go to stopped state first.
+                for (int i = start + 1; i <= ON_STOP; i++) {
+                    mLifecycleSequence.add(i);
+                }
+                // Restart
+                mLifecycleSequence.add(ON_RESTART);
+                // Go to required state
+                for (int i = ON_START; i <= finish; i++) {
+                    mLifecycleSequence.add(i);
+                }
+            } else {
+                // Relaunch and go to required state
+
+                // Go to destroyed state first.
+                for (int i = start + 1; i <= ON_DESTROY; i++) {
+                    mLifecycleSequence.add(i);
+                }
+                // Go to required state
+                for (int i = ON_CREATE; i <= finish; i++) {
+                    mLifecycleSequence.add(i);
+                }
+            }
+        }
+
+        // Remove last transition in case we want to perform it with some specific params.
+        if (excludeLastState && mLifecycleSequence.size() != 0) {
+            mLifecycleSequence.remove(mLifecycleSequence.size() - 1);
+        }
+
+        return mLifecycleSequence;
+    }
+
+    /**
+     * Pick a state that goes before provided post-execution state and would require the least
+     * lifecycle transitions to get to.
+     * It will also make sure to try avoiding a path with activity destruction and relaunch if
+     * possible.
+     * @param r An activity that we're trying to resolve the transition for.
+     * @param postExecutionState Post execution state to compute for.
+     * @return One of states that precede the provided post-execution state, or
+     *         {@link ActivityLifecycleItem#UNDEFINED} if there is not path.
+     */
+    @VisibleForTesting
+    public int getClosestPreExecutionState(ActivityThread.ActivityClientRecord r,
+            int postExecutionState) {
+        switch (postExecutionState) {
+            case UNDEFINED:
+                return UNDEFINED;
+            case ON_RESUME:
+                return getClosestOfStates(r, ON_RESUME_PRE_EXCUTION_STATES);
+            default:
+                throw new UnsupportedOperationException("Pre-execution states for state: "
+                        + postExecutionState + " is not supported.");
+        }
+    }
+
+    /**
+     * Pick a state that would require the least lifecycle transitions to get to.
+     * It will also make sure to try avoiding a path with activity destruction and relaunch if
+     * possible.
+     * @param r An activity that we're trying to resolve the transition for.
+     * @param finalStates An array of valid final states.
+     * @return One of the provided final states, or {@link ActivityLifecycleItem#UNDEFINED} if none
+     *         were provided or there is not path.
+     */
+    @VisibleForTesting
+    public int getClosestOfStates(ActivityThread.ActivityClientRecord r, int[] finalStates) {
+        if (finalStates == null || finalStates.length == 0) {
+            return UNDEFINED;
+        }
+
+        final int currentState = r.getLifecycleState();
+        int closestState = UNDEFINED;
+        for (int i = 0, shortestPath = Integer.MAX_VALUE, pathLength; i < finalStates.length; i++) {
+            getLifecyclePath(currentState, finalStates[i], false /* excludeLastState */);
+            pathLength = mLifecycleSequence.size();
+            if (pathInvolvesDestruction(mLifecycleSequence)) {
+                pathLength += DESTRUCTION_PENALTY;
+            }
+            if (shortestPath > pathLength) {
+                shortestPath = pathLength;
+                closestState = finalStates[i];
+            }
+        }
+        return closestState;
+    }
+
+    /**
+     * Check if there is a destruction involved in the path. We want to avoid a lifecycle sequence
+     * that involves destruction and recreation if there is another path.
+     */
+    private static boolean pathInvolvesDestruction(IntArray lifecycleSequence) {
+        final int size = lifecycleSequence.size();
+        for (int i = 0; i < size; i++) {
+            if (lifecycleSequence.get(i) == ON_DESTROY) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Return the index of the last callback that requests the state in which activity will be after
+     * execution. If there is a group of callbacks in the end that requests the same specific state
+     * or doesn't request any - we will find the first one from such group.
+     *
+     * E.g. ActivityResult requests RESUMED post-execution state, Configuration does not request any
+     * specific state. If there is a sequence
+     *   Configuration - ActivityResult - Configuration - ActivityResult
+     * index 1 will be returned, because ActivityResult request on position 1 will be the last
+     * request that moves activity to the RESUMED state where it will eventually end.
+     */
+    static int lastCallbackRequestingState(ClientTransaction transaction) {
+        final List<ClientTransactionItem> callbacks = transaction.getCallbacks();
+        if (callbacks == null || callbacks.size() == 0) {
+            return -1;
+        }
+
+        // Go from the back of the list to front, look for the request closes to the beginning that
+        // requests the state in which activity will end after all callbacks are executed.
+        int lastRequestedState = UNDEFINED;
+        int lastRequestingCallback = -1;
+        for (int i = callbacks.size() - 1; i >= 0; i--) {
+            final ClientTransactionItem callback = callbacks.get(i);
+            final int postExecutionState = callback.getPostExecutionState();
+            if (postExecutionState != UNDEFINED) {
+                // Found a callback that requests some post-execution state.
+                if (lastRequestedState == UNDEFINED || lastRequestedState == postExecutionState) {
+                    // It's either a first-from-end callback that requests state or it requests
+                    // the same state as the last one. In both cases, we will use it as the new
+                    // candidate.
+                    lastRequestedState = postExecutionState;
+                    lastRequestingCallback = i;
+                } else {
+                    break;
+                }
+            }
+        }
+
+        return lastRequestingCallback;
+    }
+}
diff --git a/core/java/android/content/IntentFilter.java b/core/java/android/content/IntentFilter.java
index a957aed..cec3bad 100644
--- a/core/java/android/content/IntentFilter.java
+++ b/core/java/android/content/IntentFilter.java
@@ -1872,9 +1872,10 @@
                 du.println(sb.toString());
             }
         }
-        if (mPriority != 0 || mHasPartialTypes) {
+        if (mPriority != 0 || mOrder != 0 || mHasPartialTypes) {
             sb.setLength(0);
             sb.append(prefix); sb.append("mPriority="); sb.append(mPriority);
+                    sb.append(", mOrder="); sb.append(mOrder);
                     sb.append(", mHasPartialTypes="); sb.append(mHasPartialTypes);
             du.println(sb.toString());
         }
@@ -1951,6 +1952,7 @@
         dest.writeInt(mHasPartialTypes ? 1 : 0);
         dest.writeInt(getAutoVerify() ? 1 : 0);
         dest.writeInt(mInstantAppVisibility);
+        dest.writeInt(mOrder);
     }
 
     /**
@@ -2020,6 +2022,7 @@
         mHasPartialTypes = source.readInt() > 0;
         setAutoVerify(source.readInt() > 0);
         setVisibilityToInstantApp(source.readInt());
+        mOrder = source.readInt();
     }
 
     private final boolean findMimeType(String type) {
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 2420b63..3641caf 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -3641,7 +3641,9 @@
         // getting added to the wrong package.
         final CachedComponentArgs cachedArgs = new CachedComponentArgs();
         int type;
-
+        boolean hasActivityOrder = false;
+        boolean hasReceiverOrder = false;
+        boolean hasServiceOrder = false;
         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
                 && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
             if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
@@ -3657,6 +3659,7 @@
                     return false;
                 }
 
+                hasActivityOrder |= (a.order != 0);
                 owner.activities.add(a);
 
             } else if (tagName.equals("receiver")) {
@@ -3667,6 +3670,7 @@
                     return false;
                 }
 
+                hasReceiverOrder |= (a.order != 0);
                 owner.receivers.add(a);
 
             } else if (tagName.equals("service")) {
@@ -3676,6 +3680,7 @@
                     return false;
                 }
 
+                hasServiceOrder |= (s.order != 0);
                 owner.services.add(s);
 
             } else if (tagName.equals("provider")) {
@@ -3694,6 +3699,7 @@
                     return false;
                 }
 
+                hasActivityOrder |= (a.order != 0);
                 owner.activities.add(a);
 
             } else if (parser.getName().equals("meta-data")) {
@@ -3827,6 +3833,15 @@
             }
         }
 
+        if (hasActivityOrder) {
+            Collections.sort(owner.activities, (a1, a2) -> Integer.compare(a2.order, a1.order));
+        }
+        if (hasReceiverOrder) {
+            Collections.sort(owner.receivers,  (r1, r2) -> Integer.compare(r2.order, r1.order));
+        }
+        if (hasServiceOrder) {
+            Collections.sort(owner.services,  (s1, s2) -> Integer.compare(s2.order, s1.order));
+        }
         // Must be ran after the entire {@link ApplicationInfo} has been fully processed and after
         // every activity info has had a chance to set it from its attributes.
         setMaxAspectRatio(owner);
@@ -4368,6 +4383,7 @@
                             + mArchiveSourcePath + " "
                             + parser.getPositionDescription());
                 } else {
+                    a.order = Math.max(intent.getOrder(), a.order);
                     a.intents.add(intent);
                 }
                 // adjust activity flags when we implicitly expose it via a browsable filter
@@ -4745,6 +4761,7 @@
                             + mArchiveSourcePath + " "
                             + parser.getPositionDescription());
                 } else {
+                    a.order = Math.max(intent.getOrder(), a.order);
                     a.intents.add(intent);
                 }
                 // adjust activity flags when we implicitly expose it via a browsable filter
@@ -4952,6 +4969,7 @@
                     intent.setVisibilityToInstantApp(IntentFilter.VISIBILITY_EXPLICIT);
                     outInfo.info.flags |= ProviderInfo.FLAG_VISIBLE_TO_INSTANT_APP;
                 }
+                outInfo.order = Math.max(intent.getOrder(), outInfo.order);
                 outInfo.intents.add(intent);
 
             } else if (parser.getName().equals("meta-data")) {
@@ -5241,6 +5259,7 @@
                     intent.setVisibilityToInstantApp(IntentFilter.VISIBILITY_EXPLICIT);
                     s.info.flags |= ServiceInfo.FLAG_VISIBLE_TO_INSTANT_APP;
                 }
+                s.order = Math.max(intent.getOrder(), s.order);
                 s.intents.add(intent);
             } else if (parser.getName().equals("meta-data")) {
                 if ((s.metaData=parseMetaData(res, parser, s.metaData,
@@ -5466,6 +5485,10 @@
                 com.android.internal.R.styleable.AndroidManifestIntentFilter_priority, 0);
         outInfo.setPriority(priority);
 
+        int order = sa.getInt(
+                com.android.internal.R.styleable.AndroidManifestIntentFilter_order, 0);
+        outInfo.setOrder(order);
+
         TypedValue v = sa.peekValue(
                 com.android.internal.R.styleable.AndroidManifestIntentFilter_label);
         if (v != null && (outInfo.labelRes=v.resourceId) == 0) {
@@ -7053,6 +7076,8 @@
 
         public Bundle metaData;
         public Package owner;
+        /** The order of this component in relation to its peers */
+        public int order;
 
         ComponentName componentName;
         String componentShortName;
@@ -7571,6 +7596,7 @@
 
             for (ActivityIntentInfo aii : intents) {
                 aii.activity = this;
+                order = Math.max(aii.getOrder(), order);
             }
 
             if (info.permission != null) {
@@ -7660,6 +7686,7 @@
 
             for (ServiceIntentInfo aii : intents) {
                 aii.service = this;
+                order = Math.max(aii.getOrder(), order);
             }
 
             if (info.permission != null) {
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 8ee31f7..261d89f 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -13348,7 +13348,7 @@
 
         private static final boolean DEFAULT_TRACK_CPU_TIMES_BY_PROC_STATE = true;
         private static final boolean DEFAULT_TRACK_CPU_ACTIVE_CLUSTER_TIME = true;
-        private static final boolean DEFAULT_READ_BINARY_CPU_TIME = false;
+        private static final boolean DEFAULT_READ_BINARY_CPU_TIME = true;
         private static final long DEFAULT_PROC_STATE_CPU_TIMES_READ_DELAY_MS = 5_000;
         private static final long DEFAULT_KERNEL_UID_READERS_THROTTLE_TIME = 10_000;
 
diff --git a/core/jni/android/graphics/YuvToJpegEncoder.cpp b/core/jni/android/graphics/YuvToJpegEncoder.cpp
index 5eecd9c..09adc82 100644
--- a/core/jni/android/graphics/YuvToJpegEncoder.cpp
+++ b/core/jni/android/graphics/YuvToJpegEncoder.cpp
@@ -23,16 +23,28 @@
 YuvToJpegEncoder::YuvToJpegEncoder(int* strides) : fStrides(strides) {
 }
 
+struct ErrorMgr {
+    struct jpeg_error_mgr pub;
+    jmp_buf jmp;
+};
+
+void error_exit(j_common_ptr cinfo) {
+    ErrorMgr* err = (ErrorMgr*) cinfo->err;
+    (*cinfo->err->output_message) (cinfo);
+    longjmp(err->jmp, 1);
+}
+
 bool YuvToJpegEncoder::encode(SkWStream* stream, void* inYuv, int width,
         int height, int* offsets, int jpegQuality) {
     jpeg_compress_struct    cinfo;
-    jpeg_error_mgr          err;
+    ErrorMgr                err;
     skjpeg_destination_mgr  sk_wstream(stream);
 
-    cinfo.err = jpeg_std_error(&err);
-    err.error_exit = skjpeg_error_exit;
-    jmp_buf jmp;
-    if (setjmp(jmp)) {
+    cinfo.err = jpeg_std_error(&err.pub);
+    err.pub.error_exit = error_exit;
+
+    if (setjmp(err.jmp)) {
+        jpeg_destroy_compress(&cinfo);
         return false;
     }
     jpeg_create_compress(&cinfo);
@@ -47,6 +59,8 @@
 
     jpeg_finish_compress(&cinfo);
 
+    jpeg_destroy_compress(&cinfo);
+
     return true;
 }
 
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index cfb5784..c4fa190 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -2348,6 +2348,16 @@
         <attr name="logo" />
         <attr name="priority" />
         <attr name="autoVerify" />
+        <!-- Within an application, multiple intent filters may match a particular
+             intent. This allows the app author to specify the order filters should
+             be considered. We don't want to use priority because that is global
+             across applications.
+             <p>Only use if you really need to forcibly set the order in which
+             filters are evaluated. It is preferred to target an activity with a
+             directed intent instead.
+             <p>The value is a single integer, with higher numbers considered to
+             be better. If not specified, the default order is 0. -->
+        <attr name="order" />
     </declare-styleable>
 
     <!-- Attributes that can be supplied in an AndroidManifest.xml
diff --git a/core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java b/core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java
index e575650..3eefc36 100644
--- a/core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java
+++ b/core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java
@@ -24,6 +24,9 @@
 import static android.app.servertransaction.ActivityLifecycleItem.ON_START;
 import static android.app.servertransaction.ActivityLifecycleItem.ON_STOP;
 import static android.app.servertransaction.ActivityLifecycleItem.PRE_ON_CREATE;
+import static android.app.servertransaction.ActivityLifecycleItem.UNDEFINED;
+
+import static junit.framework.Assert.assertEquals;
 
 import static org.junit.Assert.assertArrayEquals;
 import static org.mockito.ArgumentMatchers.any;
@@ -48,6 +51,10 @@
 import org.mockito.InOrder;
 
 import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
 
 /** Test {@link TransactionExecutor} logic. */
 @RunWith(AndroidJUnit4.class)
@@ -56,6 +63,7 @@
 public class TransactionExecutorTests {
 
     private TransactionExecutor mExecutor;
+    private TransactionExecutorHelper mExecutorHelper;
     private ClientTransactionHandler mTransactionHandler;
     private ActivityClientRecord mClientRecord;
 
@@ -67,6 +75,7 @@
         when(mTransactionHandler.getActivityClient(any())).thenReturn(mClientRecord);
 
         mExecutor = spy(new TransactionExecutor(mTransactionHandler));
+        mExecutorHelper = new TransactionExecutorHelper();
     }
 
     @Test
@@ -166,10 +175,42 @@
                 pathExcludeLast(ON_DESTROY));
     }
 
+    @Test(expected = IllegalArgumentException.class)
+    public void testLifecycleUndefinedStartState() {
+        mClientRecord.setState(UNDEFINED);
+        path(ON_CREATE);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testLifecycleUndefinedFinishState() {
+        mClientRecord.setState(PRE_ON_CREATE);
+        path(UNDEFINED);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testLifecycleInvalidPreOnCreateFinishState() {
+        mClientRecord.setState(ON_CREATE);
+        path(PRE_ON_CREATE);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testLifecycleInvalidOnRestartStartState() {
+        mClientRecord.setState(ON_RESTART);
+        path(ON_RESUME);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testLifecycleInvalidOnRestartFinishState() {
+        mClientRecord.setState(ON_CREATE);
+        path(ON_RESTART);
+    }
+
     @Test
     public void testTransactionResolution() {
         ClientTransactionItem callback1 = mock(ClientTransactionItem.class);
+        when(callback1.getPostExecutionState()).thenReturn(UNDEFINED);
         ClientTransactionItem callback2 = mock(ClientTransactionItem.class);
+        when(callback2.getPostExecutionState()).thenReturn(UNDEFINED);
         ActivityLifecycleItem stateRequest = mock(ActivityLifecycleItem.class);
         IBinder token = mock(IBinder.class);
 
@@ -189,7 +230,7 @@
     }
 
     @Test
-    public void testRequiredStateResolution() {
+    public void testActivityResultRequiredStateResolution() {
         ActivityResultItem activityResultItem = ActivityResultItem.obtain(new ArrayList<>());
 
         IBinder token = mock(IBinder.class);
@@ -197,20 +238,161 @@
                 token /* activityToken */);
         transaction.addCallback(activityResultItem);
 
+        // Verify resolution that should get to onPause
+        mClientRecord.setState(ON_RESUME);
         mExecutor.executeCallbacks(transaction);
-
         verify(mExecutor, times(1)).cycleToPath(eq(mClientRecord), eq(ON_PAUSE));
+
+        // Verify resolution that should get to onStart
+        mClientRecord.setState(ON_STOP);
+        mExecutor.executeCallbacks(transaction);
+        verify(mExecutor, times(1)).cycleToPath(eq(mClientRecord), eq(ON_START));
+    }
+
+    @Test
+    public void testClosestStateResolutionForSameState() {
+        final int[] allStates = new int[] {
+                ON_CREATE, ON_START, ON_RESUME, ON_PAUSE, ON_STOP, ON_DESTROY};
+
+        mClientRecord.setState(ON_CREATE);
+        assertEquals(ON_CREATE, mExecutorHelper.getClosestOfStates(mClientRecord,
+                shuffledArray(allStates)));
+
+        mClientRecord.setState(ON_START);
+        assertEquals(ON_START, mExecutorHelper.getClosestOfStates(mClientRecord,
+                shuffledArray(allStates)));
+
+        mClientRecord.setState(ON_RESUME);
+        assertEquals(ON_RESUME, mExecutorHelper.getClosestOfStates(mClientRecord,
+                shuffledArray(allStates)));
+
+        mClientRecord.setState(ON_PAUSE);
+        assertEquals(ON_PAUSE, mExecutorHelper.getClosestOfStates(mClientRecord,
+                shuffledArray(allStates)));
+
+        mClientRecord.setState(ON_STOP);
+        assertEquals(ON_STOP, mExecutorHelper.getClosestOfStates(mClientRecord,
+                shuffledArray(allStates)));
+
+        mClientRecord.setState(ON_DESTROY);
+        assertEquals(ON_DESTROY, mExecutorHelper.getClosestOfStates(mClientRecord,
+                shuffledArray(allStates)));
+
+        mClientRecord.setState(PRE_ON_CREATE);
+        assertEquals(PRE_ON_CREATE, mExecutorHelper.getClosestOfStates(mClientRecord,
+                new int[] {PRE_ON_CREATE}));
+    }
+
+    @Test
+    public void testClosestStateResolution() {
+        mClientRecord.setState(PRE_ON_CREATE);
+        assertEquals(ON_CREATE, mExecutorHelper.getClosestOfStates(mClientRecord, shuffledArray(
+                new int[] {ON_CREATE, ON_START, ON_RESUME, ON_PAUSE, ON_STOP, ON_DESTROY})));
+        assertEquals(ON_START, mExecutorHelper.getClosestOfStates(mClientRecord, shuffledArray(
+                new int[] {ON_START, ON_RESUME, ON_PAUSE, ON_STOP, ON_DESTROY})));
+        assertEquals(ON_RESUME, mExecutorHelper.getClosestOfStates(mClientRecord, shuffledArray(
+                new int[] {ON_RESUME, ON_PAUSE, ON_STOP, ON_DESTROY})));
+        assertEquals(ON_PAUSE, mExecutorHelper.getClosestOfStates(mClientRecord, shuffledArray(
+                new int[] {ON_PAUSE, ON_STOP, ON_DESTROY})));
+        assertEquals(ON_STOP, mExecutorHelper.getClosestOfStates(mClientRecord, shuffledArray(
+                new int[] {ON_STOP, ON_DESTROY})));
+        assertEquals(ON_DESTROY, mExecutorHelper.getClosestOfStates(mClientRecord, shuffledArray(
+                new int[] {ON_DESTROY})));
+    }
+
+    @Test
+    public void testClosestStateResolutionFromOnCreate() {
+        mClientRecord.setState(ON_CREATE);
+        assertEquals(ON_START, mExecutorHelper.getClosestOfStates(mClientRecord, shuffledArray(
+                new int[] {ON_START, ON_RESUME, ON_PAUSE, ON_STOP, ON_DESTROY})));
+    }
+
+    @Test
+    public void testClosestStateResolutionFromOnStart() {
+        mClientRecord.setState(ON_START);
+        assertEquals(ON_RESUME, mExecutorHelper.getClosestOfStates(mClientRecord, shuffledArray(
+                new int[] {ON_CREATE, ON_RESUME, ON_PAUSE, ON_STOP, ON_DESTROY})));
+        assertEquals(ON_CREATE, mExecutorHelper.getClosestOfStates(mClientRecord, shuffledArray(
+                new int[] {ON_CREATE})));
+    }
+
+    @Test
+    public void testClosestStateResolutionFromOnResume() {
+        mClientRecord.setState(ON_RESUME);
+        assertEquals(ON_PAUSE, mExecutorHelper.getClosestOfStates(mClientRecord, shuffledArray(
+                new int[] {ON_CREATE, ON_START, ON_PAUSE, ON_STOP, ON_DESTROY})));
+        assertEquals(ON_DESTROY, mExecutorHelper.getClosestOfStates(mClientRecord, shuffledArray(
+                new int[] {ON_CREATE, ON_DESTROY})));
+        assertEquals(ON_START, mExecutorHelper.getClosestOfStates(mClientRecord, shuffledArray(
+                new int[] {ON_CREATE, ON_START})));
+        assertEquals(ON_CREATE, mExecutorHelper.getClosestOfStates(mClientRecord, shuffledArray(
+                new int[] {ON_CREATE})));
+    }
+
+    @Test
+    public void testClosestStateResolutionFromOnPause() {
+        mClientRecord.setState(ON_PAUSE);
+        assertEquals(ON_RESUME, mExecutorHelper.getClosestOfStates(mClientRecord, shuffledArray(
+                new int[] {ON_CREATE, ON_START, ON_RESUME, ON_DESTROY})));
+        assertEquals(ON_STOP, mExecutorHelper.getClosestOfStates(mClientRecord, shuffledArray(
+                new int[] {ON_CREATE, ON_START, ON_STOP, ON_DESTROY})));
+        assertEquals(ON_START, mExecutorHelper.getClosestOfStates(mClientRecord, shuffledArray(
+                new int[] {ON_CREATE, ON_START})));
+        assertEquals(ON_CREATE, mExecutorHelper.getClosestOfStates(mClientRecord, shuffledArray(
+                new int[] {ON_CREATE})));
+    }
+
+    @Test
+    public void testClosestStateResolutionFromOnStop() {
+        mClientRecord.setState(ON_STOP);
+        assertEquals(ON_RESUME, mExecutorHelper.getClosestOfStates(mClientRecord, shuffledArray(
+                new int[] {ON_CREATE, ON_RESUME, ON_PAUSE, ON_DESTROY})));
+        assertEquals(ON_DESTROY, mExecutorHelper.getClosestOfStates(mClientRecord, shuffledArray(
+                new int[] {ON_CREATE, ON_DESTROY})));
+        assertEquals(ON_START, mExecutorHelper.getClosestOfStates(mClientRecord, shuffledArray(
+                new int[] {ON_CREATE, ON_START, ON_RESUME, ON_PAUSE})));
+    }
+
+    @Test
+    public void testClosestStateResolutionFromOnDestroy() {
+        mClientRecord.setState(ON_DESTROY);
+        assertEquals(ON_CREATE, mExecutorHelper.getClosestOfStates(mClientRecord, shuffledArray(
+                new int[] {ON_CREATE, ON_START, ON_RESUME, ON_PAUSE, ON_STOP})));
+    }
+
+    @Test
+    public void testClosestStateResolutionToUndefined() {
+        mClientRecord.setState(ON_CREATE);
+        assertEquals(UNDEFINED,
+                mExecutorHelper.getClosestPreExecutionState(mClientRecord, UNDEFINED));
+    }
+
+    @Test
+    public void testClosestStateResolutionToOnResume() {
+        mClientRecord.setState(ON_DESTROY);
+        assertEquals(ON_START,
+                mExecutorHelper.getClosestPreExecutionState(mClientRecord, ON_RESUME));
+        mClientRecord.setState(ON_START);
+        assertEquals(ON_START,
+                mExecutorHelper.getClosestPreExecutionState(mClientRecord, ON_RESUME));
+        mClientRecord.setState(ON_PAUSE);
+        assertEquals(ON_PAUSE,
+                mExecutorHelper.getClosestPreExecutionState(mClientRecord, ON_RESUME));
+    }
+
+    private static int[] shuffledArray(int[] inputArray) {
+        final List<Integer> list = Arrays.stream(inputArray).boxed().collect(Collectors.toList());
+        Collections.shuffle(list);
+        return list.stream().mapToInt(Integer::intValue).toArray();
     }
 
     private int[] path(int finish) {
-        mExecutor.initLifecyclePath(mClientRecord.getLifecycleState(), finish,
-                false /* excludeLastState */);
-        return mExecutor.getLifecycleSequence();
+        return mExecutorHelper.getLifecyclePath(mClientRecord.getLifecycleState(), finish,
+                false /* excludeLastState */).toArray();
     }
 
     private int[] pathExcludeLast(int finish) {
-        mExecutor.initLifecyclePath(mClientRecord.getLifecycleState(), finish,
-                true /* excludeLastState */);
-        return mExecutor.getLifecycleSequence();
+        return mExecutorHelper.getLifecyclePath(mClientRecord.getLifecycleState(), finish,
+                true /* excludeLastState */).toArray();
     }
 }
diff --git a/graphics/java/android/graphics/EmbossMaskFilter.java b/graphics/java/android/graphics/EmbossMaskFilter.java
index a9e180f..003678a 100644
--- a/graphics/java/android/graphics/EmbossMaskFilter.java
+++ b/graphics/java/android/graphics/EmbossMaskFilter.java
@@ -20,12 +20,15 @@
     /**
      * Create an emboss maskfilter
      *
+     * @deprecated This subclass is not supported and should not be instantiated.
+     *
      * @param direction  array of 3 scalars [x, y, z] specifying the direction of the light source
      * @param ambient    0...1 amount of ambient light
      * @param specular   coefficient for specular highlights (e.g. 8)
      * @param blurRadius amount to blur before applying lighting (e.g. 3)
      * @return           the emboss maskfilter
      */
+    @Deprecated
     public EmbossMaskFilter(float[] direction, float ambient, float specular, float blurRadius) {
         if (direction.length < 3) {
             throw new ArrayIndexOutOfBoundsException();
diff --git a/graphics/java/android/graphics/ImageDecoder.java b/graphics/java/android/graphics/ImageDecoder.java
index 1344093..5abd31a 100644
--- a/graphics/java/android/graphics/ImageDecoder.java
+++ b/graphics/java/android/graphics/ImageDecoder.java
@@ -19,6 +19,8 @@
 import static android.system.OsConstants.SEEK_CUR;
 import static android.system.OsConstants.SEEK_SET;
 
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -52,8 +54,6 @@
 import java.nio.ByteBuffer;
 import java.util.concurrent.atomic.AtomicBoolean;
 
-import static java.lang.annotation.RetentionPolicy.SOURCE;
-
 /**
  *  Class for decoding images as {@link Bitmap}s or {@link Drawable}s.
  */
@@ -621,16 +621,18 @@
     /**
      * Create a new {@link Source} from a {@link java.nio.ByteBuffer}.
      *
-     * <p>The returned {@link Source} effectively takes ownership of the
-     * {@link java.nio.ByteBuffer}; i.e. no other code should modify it after
-     * this call.</p>
+     * <p>Decoding will start from {@link java.nio.ByteBuffer#position()}. The
+     * position of {@code buffer} will not be affected.</p>
      *
-     * Decoding will start from {@link java.nio.ByteBuffer#position()}. The
-     * position after decoding is undefined.
+     * <p>Note: If this {@code Source} is passed to {@link #decodeDrawable}, and
+     * the encoded image is animated, the returned {@link AnimatedImageDrawable}
+     * will continue reading from the {@code buffer}, so its contents must not
+     * be modified, even after the {@code AnimatedImageDrawable} is returned.
+     * {@code buffer}'s contents should never be modified during decode.</p>
      */
     @NonNull
     public static Source createSource(@NonNull ByteBuffer buffer) {
-        return new ByteBufferSource(buffer);
+        return new ByteBufferSource(buffer.slice());
     }
 
     /**
@@ -690,8 +692,9 @@
      *
      *  @param width must be greater than 0.
      *  @param height must be greater than 0.
+     *  @return this object for chaining.
      */
-    public void setResize(int width, int height) {
+    public ImageDecoder setResize(int width, int height) {
         if (width <= 0 || height <= 0) {
             throw new IllegalArgumentException("Dimensions must be positive! "
                     + "provided (" + width + ", " + height + ")");
@@ -699,6 +702,7 @@
 
         mDesiredWidth = width;
         mDesiredHeight = height;
+        return this;
     }
 
     /**
@@ -708,10 +712,11 @@
      *  {@link #getSampledSize} to {@link #setResize(int, int)}.</p>
      *
      *  @param sampleSize Sampling rate of the encoded image.
+     *  @return this object for chaining.
      */
-    public void setResize(int sampleSize) {
+    public ImageDecoder setResize(int sampleSize) {
         Size size = this.getSampledSize(sampleSize);
-        this.setResize(size.getWidth(), size.getHeight());
+        return this.setResize(size.getWidth(), size.getHeight());
     }
 
     private boolean requestedResize() {
@@ -767,18 +772,20 @@
      *  This is ignored for animated drawables.
      *
      *  @param allocator Type of allocator to use.
+     *  @return this object for chaining.
      */
-    public void setAllocator(@Allocator int allocator) {
+    public ImageDecoder setAllocator(@Allocator int allocator) {
         if (allocator < ALLOCATOR_DEFAULT || allocator > ALLOCATOR_HARDWARE) {
             throw new IllegalArgumentException("invalid allocator " + allocator);
         }
         mAllocator = allocator;
+        return this;
     }
 
     /**
      *  Specify whether the {@link Bitmap} should have unpremultiplied pixels.
      *
-     *  By default, ImageDecoder will create a {@link Bitmap} with
+     *  <p>By default, ImageDecoder will create a {@link Bitmap} with
      *  premultiplied pixels, which is required for drawing with the
      *  {@link android.view.View} system (i.e. to a {@link Canvas}). Calling
      *  this method with a value of {@code true} will result in
@@ -786,9 +793,13 @@
      *  pixels. See {@link Bitmap#isPremultiplied}. This is incompatible with
      *  {@link #decodeDrawable}; attempting to decode an unpremultiplied
      *  {@link Drawable} will throw an {@link java.lang.IllegalStateException}.
+     *  </p>
+     *
+     *  @return this object for chaining.
      */
-    public void setRequireUnpremultiplied(boolean requireUnpremultiplied) {
+    public ImageDecoder setRequireUnpremultiplied(boolean requireUnpremultiplied) {
         mRequireUnpremultiplied = requireUnpremultiplied;
+        return this;
     }
 
     /**
@@ -803,19 +814,25 @@
      *  <p>For an animated image, the drawing commands drawn on the
      *  {@link Canvas} will be recorded immediately and then applied to each
      *  frame.</p>
+     *
+     *  @return this object for chaining.
      */
-    public void setPostProcessor(@Nullable PostProcessor p) {
+    public ImageDecoder setPostProcessor(@Nullable PostProcessor p) {
         mPostProcessor = p;
+        return this;
     }
 
     /**
      *  Set (replace) the {@link OnPartialImageListener} on this object.
      *
-     *  Will be called if there is an error in the input. Without one, a
-     *  partial {@link Bitmap} will be created.
+     *  <p>Will be called if there is an error in the input. Without one, an
+     *  error will result in an Exception being thrown.</p>
+     *
+     *  @return this object for chaining.
      */
-    public void setOnPartialImageListener(@Nullable OnPartialImageListener l) {
+    public ImageDecoder setOnPartialImageListener(@Nullable OnPartialImageListener l) {
         mOnPartialImageListener = l;
+        return this;
     }
 
     /**
@@ -829,9 +846,12 @@
      *  <p>NOT intended as a replacement for
      *  {@link BitmapRegionDecoder#decodeRegion}. This supports all formats,
      *  but merely crops the output.</p>
+     *
+     *  @return this object for chaining.
      */
-    public void setCrop(@Nullable Rect subset) {
+    public ImageDecoder setCrop(@Nullable Rect subset) {
         mCropRect = subset;
+        return this;
     }
 
     /**
@@ -840,10 +860,13 @@
      *  If the image is a nine patch, this Rect will be set to the padding
      *  rectangle during decode. Otherwise it will not be modified.
      *
+     *  @return this object for chaining.
+     *
      *  @hide
      */
-    public void setOutPaddingRect(@NonNull Rect outPadding) {
+    public ImageDecoder setOutPaddingRect(@NonNull Rect outPadding) {
         mOutPaddingRect = outPadding;
+        return this;
     }
 
     /**
@@ -861,25 +884,31 @@
      *  which would require retrieving the Bitmap from the returned Drawable in
      *  order to modify. Attempting to decode a mutable {@link Drawable} will
      *  throw an {@link java.lang.IllegalStateException}.</p>
+     *
+     *  @return this object for chaining.
      */
-    public void setMutable(boolean mutable) {
+    public ImageDecoder setMutable(boolean mutable) {
         mMutable = mutable;
+        return this;
     }
 
     /**
      *  Specify whether to potentially save RAM at the expense of quality.
      *
-     *  Setting this to {@code true} may result in a {@link Bitmap} with a
+     *  <p>Setting this to {@code true} may result in a {@link Bitmap} with a
      *  denser {@link Bitmap.Config}, depending on the image. For example, an
      *  opaque {@link Bitmap} with 8 bits or precision for each of its red,
      *  green and blue components would decode to
      *  {@link Bitmap.Config#ARGB_8888} by default, but setting this to
      *  {@code true} will result in decoding to {@link Bitmap.Config#RGB_565}.
      *  This necessarily lowers the quality of the output, but saves half
-     *  the memory used.
+     *  the memory used.</p>
+     *
+     *  @return this object for chaining.
      */
-    public void setConserveMemory(boolean conserveMemory) {
+    public ImageDecoder setConserveMemory(boolean conserveMemory) {
         mConserveMemory = conserveMemory;
+        return this;
     }
 
     /**
@@ -893,9 +922,12 @@
      *  combine them will result in {@link #decodeDrawable}/
      *  {@link #decodeBitmap} throwing an
      *  {@link java.lang.IllegalStateException}.</p>
+     *
+     *  @return this object for chaining.
      */
-    public void setAsAlphaMask(boolean asAlphaMask) {
+    public ImageDecoder setAsAlphaMask(boolean asAlphaMask) {
         mAsAlphaMask = asAlphaMask;
+        return this;
     }
 
     @Override
diff --git a/graphics/java/android/graphics/drawable/Icon.java b/graphics/java/android/graphics/drawable/Icon.java
index 749b7594..361fe0b 100644
--- a/graphics/java/android/graphics/drawable/Icon.java
+++ b/graphics/java/android/graphics/drawable/Icon.java
@@ -18,11 +18,14 @@
 
 import android.annotation.ColorInt;
 import android.annotation.DrawableRes;
-import android.content.res.ColorStateList;
+import android.annotation.IdRes;
+import android.annotation.IntDef;
+import android.annotation.NonNull;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
+import android.content.res.ColorStateList;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
@@ -60,17 +63,40 @@
 public final class Icon implements Parcelable {
     private static final String TAG = "Icon";
 
-    /** @hide */
+    /**
+     * An icon that was created using {@link Icon#createWithBitmap(Bitmap)}.
+     * @see #getType
+     */
     public static final int TYPE_BITMAP   = 1;
-    /** @hide */
+    /**
+     * An icon that was created using {@link Icon#createWithResource}.
+     * @see #getType
+     */
     public static final int TYPE_RESOURCE = 2;
-    /** @hide */
+    /**
+     * An icon that was created using {@link Icon#createWithData(byte[], int, int)}.
+     * @see #getType
+     */
     public static final int TYPE_DATA     = 3;
-    /** @hide */
+    /**
+     * An icon that was created using {@link Icon#createWithContentUri}
+     * or {@link Icon#createWithFilePath(String)}.
+     * @see #getType
+     */
     public static final int TYPE_URI      = 4;
-    /** @hide */
+    /**
+     * An icon that was created using {@link Icon#createWithAdaptiveBitmap}.
+     * @see #getType
+     */
     public static final int TYPE_ADAPTIVE_BITMAP = 5;
 
+    /**
+     * @hide
+     */
+    @IntDef({TYPE_BITMAP, TYPE_RESOURCE, TYPE_DATA, TYPE_URI, TYPE_ADAPTIVE_BITMAP})
+    public @interface IconType {
+    }
+
     private static final int VERSION_STREAM_SERIALIZER = 1;
 
     private final int mType;
@@ -99,14 +125,12 @@
     private int             mInt2;
 
     /**
-     * @return The type of image data held in this Icon. One of
-     * {@link #TYPE_BITMAP},
-     * {@link #TYPE_RESOURCE},
-     * {@link #TYPE_DATA}, or
-     * {@link #TYPE_URI}.
-     * {@link #TYPE_ADAPTIVE_BITMAP}
-     * @hide
+     * Gets the type of the icon provided.
+     * <p>
+     * Note that new types may be added later, so callers should guard against other
+     * types being returned.
      */
+    @IconType
     public int getType() {
         return mType;
     }
@@ -179,9 +203,13 @@
     }
 
     /**
-     * @return The package containing resources for this {@link #TYPE_RESOURCE} Icon.
-     * @hide
+     * Gets the package used to create this icon.
+     * <p>
+     * Only valid for icons of type {@link #TYPE_RESOURCE}.
+     * Note: This package may not be available if referenced in the future, and it is
+     * up to the caller to ensure safety if this package is re-used and/or persisted.
      */
+    @NonNull
     public String getResPackage() {
         if (mType != TYPE_RESOURCE) {
             throw new IllegalStateException("called getResPackage() on " + this);
@@ -190,9 +218,13 @@
     }
 
     /**
-     * @return The resource ID for this {@link #TYPE_RESOURCE} Icon.
-     * @hide
+     * Gets the resource used to create this icon.
+     * <p>
+     * Only valid for icons of type {@link #TYPE_RESOURCE}.
+     * Note: This resource may not be available if the application changes at all, and it is
+     * up to the caller to ensure safety if this resource is re-used and/or persisted.
      */
+    @IdRes
     public int getResId() {
         if (mType != TYPE_RESOURCE) {
             throw new IllegalStateException("called getResId() on " + this);
@@ -212,9 +244,13 @@
     }
 
     /**
-     * @return The {@link android.net.Uri} for this {@link #TYPE_URI} Icon.
-     * @hide
+     * Gets the uri used to create this icon.
+     * <p>
+     * Only valid for icons of type {@link #TYPE_URI}.
+     * Note: This uri may not be available in the future, and it is
+     * up to the caller to ensure safety if this uri is re-used and/or persisted.
      */
+    @NonNull
     public Uri getUri() {
         return Uri.parse(getUriString());
     }
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java
index 7e23ee1..16ef59f 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java
@@ -41,7 +41,8 @@
     private static final boolean DEBUG = false;
     private static final String LOG_TAG = "DeviceChooserActivity";
 
-    private ListView mDeviceListView;
+    View mLoadingIndicator = null;
+    ListView mDeviceListView;
     private View mPairButton;
     private View mCancelButton;
 
@@ -80,8 +81,9 @@
                     onSelectionUpdate();
                 }
             });
-            mDeviceListView.addFooterView(getProgressBar(), null, false);
+            mDeviceListView.addFooterView(mLoadingIndicator = getProgressBar(), null, false);
         }
+        getService().mActivity = this;
 
         mCancelButton = findViewById(R.id.button_cancel);
         mCancelButton.setOnClickListener(v -> cancel());
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
index 1e26231..a5f0f24 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
@@ -22,6 +22,7 @@
 import static com.android.internal.util.ArrayUtils.isEmpty;
 import static com.android.internal.util.CollectionUtils.emptyIfNull;
 import static com.android.internal.util.CollectionUtils.size;
+import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -50,6 +51,7 @@
 import android.graphics.Color;
 import android.graphics.drawable.Drawable;
 import android.net.wifi.WifiManager;
+import android.os.Handler;
 import android.os.IBinder;
 import android.os.Parcelable;
 import android.os.RemoteException;
@@ -63,7 +65,9 @@
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.CollectionUtils;
 import com.android.internal.util.Preconditions;
+import com.android.internal.util.function.pooled.PooledLambda;
 
+import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Objects;
@@ -73,6 +77,8 @@
     private static final boolean DEBUG = false;
     private static final String LOG_TAG = "DeviceDiscoveryService";
 
+    private static final long SCAN_TIMEOUT = 20000;
+
     static DeviceDiscoveryService sInstance;
 
     private BluetoothAdapter mBluetoothAdapter;
@@ -93,6 +99,8 @@
     IFindDeviceCallback mFindCallback;
 
     ICompanionDeviceDiscoveryServiceCallback mServiceCallback;
+    boolean mIsScanning = false;
+    @Nullable DeviceChooserActivity mActivity = null;
 
     private final ICompanionDeviceDiscoveryService mBinder =
             new ICompanionDeviceDiscoveryService.Stub() {
@@ -196,6 +204,10 @@
                     new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
             mWifiManager.startScan();
         }
+        mIsScanning = true;
+        Handler.getMain().sendMessageDelayed(
+                obtainMessage(DeviceDiscoveryService::stopScan, this),
+                SCAN_TIMEOUT);
     }
 
     private boolean shouldScan(List<? extends DeviceFilter> mediumSpecificFilters) {
@@ -219,6 +231,15 @@
     private void stopScan() {
         if (DEBUG) Log.i(LOG_TAG, "stopScan()");
 
+        if (!mIsScanning) return;
+        mIsScanning = false;
+
+        DeviceChooserActivity activity = mActivity;
+        if (activity != null) {
+            activity.mDeviceListView.removeFooterView(activity.mLoadingIndicator);
+            mActivity = null;
+        }
+
         mBluetoothAdapter.cancelDiscovery();
         if (mBluetoothBroadcastReceiver != null) {
             unregisterReceiver(mBluetoothBroadcastReceiver);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 2f05726..cccdb58 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -4524,7 +4524,7 @@
             if (isScreenTurningOnOrOn()) {
                 if (DEBUG_CAMERA_LIFT) Slog.d(TAG, "Launching camera");
                 if (mStatusBarKeyguardViewManager.isBouncerShowing()) {
-                    mStatusBarKeyguardViewManager.hideBouncer(false /* destroyView */);
+                    mStatusBarKeyguardViewManager.reset(true /* hide */);
                 }
                 mNotificationPanel.launchCamera(mDeviceInteractive /* animate */, source);
                 updateScrimController();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 49cffc0..a009d80 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -164,7 +164,7 @@
         updateStates();
     }
 
-    public void hideBouncer(boolean destroyView) {
+    private void hideBouncer(boolean destroyView) {
         mBouncer.hide(destroyView);
         cancelPendingWakeupAction();
     }
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 2f6afd2..728c07d 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -109,6 +109,7 @@
 import android.app.WindowConfiguration.ActivityType;
 import android.app.WindowConfiguration.WindowingMode;
 import android.app.servertransaction.ActivityResultItem;
+import android.app.servertransaction.ClientTransaction;
 import android.app.servertransaction.NewIntentItem;
 import android.app.servertransaction.WindowVisibilityItem;
 import android.app.servertransaction.DestroyActivityItem;
@@ -2609,6 +2610,8 @@
                 }
 
                 try {
+                    final ClientTransaction transaction = ClientTransaction.obtain(next.app.thread,
+                            next.appToken);
                     // Deliver all pending results.
                     ArrayList<ResultInfo> a = next.results;
                     if (a != null) {
@@ -2616,15 +2619,13 @@
                         if (!next.finishing && N > 0) {
                             if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
                                     "Delivering results to " + next + ": " + a);
-                            mService.mLifecycleManager.scheduleTransaction(next.app.thread,
-                                    next.appToken, ActivityResultItem.obtain(a));
+                            transaction.addCallback(ActivityResultItem.obtain(a));
                         }
                     }
 
                     if (next.newIntents != null) {
-                        mService.mLifecycleManager.scheduleTransaction(next.app.thread,
-                                next.appToken, NewIntentItem.obtain(next.newIntents,
-                                        false /* andPause */));
+                        transaction.addCallback(NewIntentItem.obtain(next.newIntents,
+                                false /* andPause */));
                     }
 
                     // Well the app will no longer be stopped.
@@ -2641,11 +2642,13 @@
                     next.app.pendingUiClean = true;
                     next.app.forceProcessStateUpTo(mService.mTopProcessState);
                     next.clearOptionsLocked();
-                    mService.mLifecycleManager.scheduleTransaction(next.app.thread, next.appToken,
+
+                    transaction.setLifecycleStateRequest(
                             ResumeActivityItem.obtain(next.app.repProcState,
                                     mService.isNextTransitionForward())
                                     .setDescription(next.getLifecycleDescription(
                                             "resumeTopActivityInnerLocked")));
+                    mService.mLifecycleManager.scheduleTransaction(transaction);
 
                     if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Resumed "
                             + next);
diff --git a/services/core/java/com/android/server/display/BrightnessTracker.java b/services/core/java/com/android/server/display/BrightnessTracker.java
index 524de91..df60c66 100644
--- a/services/core/java/com/android/server/display/BrightnessTracker.java
+++ b/services/core/java/com/android/server/display/BrightnessTracker.java
@@ -70,6 +70,8 @@
 import java.util.ArrayList;
 
 import java.util.Deque;
+import java.util.HashMap;
+import java.util.Map;
 import java.util.concurrent.TimeUnit;
 
 /**
@@ -225,15 +227,24 @@
      * @return List of recent {@link BrightnessChangeEvent}s
      */
     public ParceledListSlice<BrightnessChangeEvent> getEvents(int userId, boolean includePackage) {
-        // TODO include apps from any managed profiles in the brightness information.
         BrightnessChangeEvent[] events;
         synchronized (mEventsLock) {
             events = mEvents.toArray();
         }
+        int[] profiles = mInjector.getProfileIds(mUserManager, userId);
+        Map<Integer, Boolean> toRedact = new HashMap<>();
+        for (int i = 0; i < profiles.length; ++i) {
+            int profileId = profiles[i];
+            // Include slider interactions when a managed profile app is in the
+            // foreground but always redact the package name.
+            boolean redact = (!includePackage) || profileId != userId;
+            toRedact.put(profiles[i], redact);
+        }
         ArrayList<BrightnessChangeEvent> out = new ArrayList<>(events.length);
         for (int i = 0; i < events.length; ++i) {
-            if (events[i].userId == userId) {
-                if (includePackage) {
+            Boolean redact = toRedact.get(events[i].userId);
+            if (redact != null) {
+                if (!redact) {
                     out.add(events[i]);
                 } else {
                     BrightnessChangeEvent event = new BrightnessChangeEvent((events[i]),
@@ -817,6 +828,14 @@
             return userManager.getUserHandle(userSerialNumber);
         }
 
+        public int[] getProfileIds(UserManager userManager, int userId) {
+            if (userManager != null) {
+                return userManager.getProfileIds(userId, false);
+            } else {
+                return new int[]{userId};
+            }
+        }
+
         public ActivityManager.StackInfo getFocusedStack() throws RemoteException {
             return ActivityManager.getService().getFocusedStackInfo();
         }
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java
index fb1595e..a527e17 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java
@@ -111,8 +111,6 @@
         assertEquals(mStack.onActivityRemovedFromStackInvocationCount(), 0);
     }
 
-    // TODO: b/71582913
-    @Ignore("b/71582913")
     @Test
     public void testPausingWhenVisibleFromStopped() throws Exception {
         final MutableBoolean pauseFound = new MutableBoolean(false);
diff --git a/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java b/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java
index 501f966..b4f8474 100644
--- a/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java
@@ -338,6 +338,26 @@
         assertFalse(event.isDefaultBrightnessConfig);
         assertEquals(1.0, event.powerBrightnessFactor, FLOAT_DELTA);
         assertFalse(event.isUserSetBrightness);
+
+        // Pretend user 1 is a profile of user 0.
+        mInjector.mProfiles = new int[]{0, 1};
+        events = tracker.getEvents(0, true).getList();
+        // Both events should now be returned.
+        assertEquals(2, events.size());
+        BrightnessChangeEvent userZeroEvent;
+        BrightnessChangeEvent userOneEvent;
+        if (events.get(0).userId == 0) {
+            userZeroEvent = events.get(0);
+            userOneEvent = events.get(1);
+        } else {
+            userZeroEvent = events.get(1);
+            userOneEvent = events.get(0);
+        }
+        assertEquals(0, userZeroEvent.userId);
+        assertEquals("com.example.app", userZeroEvent.packageName);
+        assertEquals(1, userOneEvent.userId);
+        // Events from user 1 should have the package name redacted
+        assertNull(userOneEvent.packageName);
     }
 
     @Test
@@ -597,6 +617,7 @@
         Handler mHandler;
         boolean mIdleScheduled;
         boolean mInteractive = true;
+        int[] mProfiles;
 
         public TestInjector(Handler handler) {
             mHandler = handler;
@@ -682,6 +703,15 @@
         }
 
         @Override
+        public int[] getProfileIds(UserManager userManager, int userId) {
+            if (mProfiles != null) {
+                return mProfiles;
+            } else {
+                return new int[]{userId};
+            }
+        }
+
+        @Override
         public ActivityManager.StackInfo getFocusedStack() throws RemoteException {
             ActivityManager.StackInfo focusedStack = new ActivityManager.StackInfo();
             focusedStack.userId = 0;
@@ -689,15 +719,18 @@
             return focusedStack;
         }
 
+        @Override
         public void scheduleIdleJob(Context context) {
             // Don't actually schedule jobs during unit tests.
             mIdleScheduled = true;
         }
 
+        @Override
         public void cancelIdleJob(Context context) {
             mIdleScheduled = false;
         }
 
+        @Override
         public boolean isInteractive(Context context) {
             return mInteractive;
         }
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareManager.java b/wifi/java/android/net/wifi/aware/WifiAwareManager.java
index 06a5c2e..8529a89 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareManager.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareManager.java
@@ -27,6 +27,7 @@
 import android.net.NetworkRequest;
 import android.net.NetworkSpecifier;
 import android.os.Binder;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
@@ -420,9 +421,12 @@
                     "createNetworkSpecifier: Invalid 'role' argument when creating a network "
                             + "specifier");
         }
-        if (peerHandle == null) {
-            throw new IllegalArgumentException(
-                    "createNetworkSpecifier: Invalid peer handle - cannot be null");
+        if (role == WIFI_AWARE_DATA_PATH_ROLE_INITIATOR || !WifiAwareUtils.isLegacyVersion(mContext,
+                Build.VERSION_CODES.P)) {
+            if (peerHandle == null) {
+                throw new IllegalArgumentException(
+                        "createNetworkSpecifier: Invalid peer handle - cannot be null");
+            }
         }
 
         return new WifiAwareNetworkSpecifier(
@@ -453,9 +457,12 @@
                     "createNetworkSpecifier: Invalid 'role' argument when creating a network "
                             + "specifier");
         }
-        if (peer == null) {
-            throw new IllegalArgumentException(
-                    "createNetworkSpecifier: Invalid peer MAC - cannot be null");
+        if (role == WIFI_AWARE_DATA_PATH_ROLE_INITIATOR || !WifiAwareUtils.isLegacyVersion(mContext,
+                Build.VERSION_CODES.P)) {
+            if (peer == null) {
+                throw new IllegalArgumentException(
+                        "createNetworkSpecifier: Invalid peer MAC - cannot be null");
+            }
         }
         if (peer != null && peer.length != 6) {
             throw new IllegalArgumentException("createNetworkSpecifier: Invalid peer MAC address");
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareUtils.java b/wifi/java/android/net/wifi/aware/WifiAwareUtils.java
index fda7a9a..3ece93d 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareUtils.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareUtils.java
@@ -16,6 +16,8 @@
 
 package android.net.wifi.aware;
 
+import android.content.Context;
+import android.content.pm.PackageManager;
 import android.hardware.wifi.V1_0.Constants;
 
 /**
@@ -84,4 +86,21 @@
 
         return true;
     }
+
+    /**
+     * Returns true if the App version is older than minVersion.
+     */
+    public static boolean isLegacyVersion(Context context, int minVersion) {
+        try {
+            if (context.getPackageManager().getApplicationInfo(context.getOpPackageName(), 0)
+                    .targetSdkVersion < minVersion) {
+                return true;
+            }
+        } catch (PackageManager.NameNotFoundException e) {
+            // In case of exception, assume known app (more strict checking)
+            // Note: This case will never happen since checkPackage is
+            // called to verify valididity before checking App's version.
+        }
+        return false;
+    }
 }
diff --git a/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java b/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java
index 84e3ed9..272f727 100644
--- a/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java
+++ b/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java
@@ -19,14 +19,20 @@
 import static org.hamcrest.core.IsEqual.equalTo;
 import static org.junit.Assert.assertEquals;
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.ArgumentMatchers.isNull;
 import static org.mockito.Mockito.inOrder;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
 
 import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
 import android.net.wifi.RttManager;
+import android.os.Build;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Parcel;
@@ -79,12 +85,32 @@
     @Mock
     public RttManager.RttListener mockRttListener;
 
+    @Mock
+    public PackageManager mockPackageManager;
+
+    @Mock
+    public ApplicationInfo mockApplicationInfo;
+
     private static final int AWARE_STATUS_ERROR = -1;
 
+    private static final byte[] PMK_VALID = "01234567890123456789012345678901".getBytes();
+    private static final byte[] PMK_INVALID = "012".getBytes();
+
+    private static final String PASSPHRASE_VALID = "SomeLongEnoughPassphrase";
+    private static final String PASSPHRASE_TOO_SHORT = "012";
+    private static final String PASSPHRASE_TOO_LONG =
+            "0123456789012345678901234567890123456789012345678901234567890123456789";
+
     @Before
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
 
+        mockApplicationInfo.targetSdkVersion = Build.VERSION_CODES.P;
+        when(mockPackageManager.getApplicationInfo(anyString(), anyInt())).thenReturn(
+                mockApplicationInfo);
+        when(mockContext.getOpPackageName()).thenReturn("XXX");
+        when(mockContext.getPackageManager()).thenReturn(mockPackageManager);
+
         mDut = new WifiAwareManager(mockContext, mockAwareService);
         mMockLooper = new TestLooper();
         mMockLooperHandler = new Handler(mMockLooper.getLooper());
@@ -884,8 +910,8 @@
         final int sessionId = 123;
         final PeerHandle peerHandle = new PeerHandle(123412);
         final int role = WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER;
-        final byte[] pmk = "01234567890123456789012345678901".getBytes();
-        final String passphrase = "A really bad password";
+        final byte[] pmk = PMK_VALID;
+        final String passphrase = PASSPHRASE_VALID;
         final ConfigRequest configRequest = new ConfigRequest.Builder().build();
         final PublishConfig publishConfig = new PublishConfig.Builder().build();
 
@@ -965,8 +991,8 @@
         final ConfigRequest configRequest = new ConfigRequest.Builder().build();
         final byte[] someMac = HexEncoding.decode("000102030405".toCharArray(), false);
         final int role = WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR;
-        final byte[] pmk = "01234567890123456789012345678901".getBytes();
-        final String passphrase = "A really bad password";
+        final byte[] pmk = PMK_VALID;
+        final String passphrase = PASSPHRASE_VALID;
 
         ArgumentCaptor<WifiAwareSession> sessionCaptor = ArgumentCaptor.forClass(
                 WifiAwareSession.class);
@@ -1030,7 +1056,7 @@
      */
     @Test(expected = IllegalArgumentException.class)
     public void testNetworkSpecifierWithClientIncorrectLengthPmk() throws Exception {
-        executeNetworkSpecifierWithClient(new PeerHandle(123412), true, "012".getBytes(), null);
+        executeNetworkSpecifierWithClient(new PeerHandle(123412), true, PMK_INVALID, null);
     }
 
     /**
@@ -1045,17 +1071,17 @@
      * Validate that a too short Passphrase triggers an exception.
      */
     @Test(expected = IllegalArgumentException.class)
-    public void testNetworkSpecifierWithClientShortPassphrase() throws Exception {
-        executeNetworkSpecifierWithClient(new PeerHandle(123412), false, null, "012");
+    public void testNetworkSpecifierWithClientTooShortPassphrase() throws Exception {
+        executeNetworkSpecifierWithClient(new PeerHandle(123412), false, null,
+                PASSPHRASE_TOO_SHORT);
     }
 
     /**
      * Validate that a too long Passphrase triggers an exception.
      */
     @Test(expected = IllegalArgumentException.class)
-    public void testNetworkSpecifierWithClientLongPassphrase() throws Exception {
-        executeNetworkSpecifierWithClient(new PeerHandle(123412), false, null,
-                "0123456789012345678901234567890123456789012345678901234567890123456789");
+    public void testNetworkSpecifierWithClientTooLongPassphrase() throws Exception {
+        executeNetworkSpecifierWithClient(new PeerHandle(123412), false, null, PASSPHRASE_TOO_LONG);
     }
 
     /**
@@ -1063,8 +1089,16 @@
      */
     @Test(expected = IllegalArgumentException.class)
     public void testNetworkSpecifierWithClientNullPeer() throws Exception {
-        executeNetworkSpecifierWithClient(null, false, null,
-                "0123456789012345678901234567890123456789012345678901234567890123456789");
+        executeNetworkSpecifierWithClient(null, false, null, PASSPHRASE_VALID);
+    }
+
+    /**
+     * Validate that a null PeerHandle does not trigger an exception for legacy API.
+     */
+    @Test
+    public void testNetworkSpecifierWithClientNullPeerLegacyApi() throws Exception {
+        mockApplicationInfo.targetSdkVersion = Build.VERSION_CODES.O;
+        executeNetworkSpecifierWithClient(null, false, null, PASSPHRASE_VALID);
     }
 
     private void executeNetworkSpecifierWithClient(PeerHandle peerHandle, boolean doPmk, byte[] pmk,
@@ -1117,7 +1151,7 @@
     @Test(expected = IllegalArgumentException.class)
     public void testNetworkSpecifierDirectNullPmk() throws Exception {
         executeNetworkSpecifierDirect(HexEncoding.decode("000102030405".toCharArray(), false), true,
-                null, null);
+                null, null, true);
     }
 
     /**
@@ -1126,7 +1160,7 @@
     @Test(expected = IllegalArgumentException.class)
     public void testNetworkSpecifierDirectIncorrectLengthPmk() throws Exception {
         executeNetworkSpecifierDirect(HexEncoding.decode("000102030405".toCharArray(), false), true,
-                "012".getBytes(), null);
+                PMK_INVALID, null, true);
     }
 
     /**
@@ -1135,40 +1169,57 @@
     @Test(expected = IllegalArgumentException.class)
     public void testNetworkSpecifierDirectNullPassphrase() throws Exception {
         executeNetworkSpecifierDirect(HexEncoding.decode("000102030405".toCharArray(), false),
-                false, null, null);
+                false, null, null, true);
     }
 
     /**
      * Validate that a too short Passphrase triggers an exception.
      */
     @Test(expected = IllegalArgumentException.class)
-    public void testNetworkSpecifierDirectShortPassphrase() throws Exception {
+    public void testNetworkSpecifierDirectTooShortPassphrase() throws Exception {
         executeNetworkSpecifierDirect(HexEncoding.decode("000102030405".toCharArray(), false),
-                false, null, "012");
+                false, null, PASSPHRASE_TOO_SHORT, true);
     }
 
     /**
      * Validate that a too long Passphrase triggers an exception.
      */
     @Test(expected = IllegalArgumentException.class)
-    public void testNetworkSpecifierDirectLongPassphrase() throws Exception {
+    public void testNetworkSpecifierDirectTooLongPassphrase() throws Exception {
         executeNetworkSpecifierDirect(HexEncoding.decode("000102030405".toCharArray(), false),
-                false, null,
-                "0123456789012345678901234567890123456789012345678901234567890123456789");
+                false, null, PASSPHRASE_TOO_LONG, true);
     }
 
     /**
-     * Validate that a null peer MAC triggers an exception.
+     * Validate that a null peer MAC triggers an exception for an Initiator.
      */
     @Test(expected = IllegalArgumentException.class)
-    public void testNetworkSpecifierDirectNullPeer() throws Exception {
-        executeNetworkSpecifierDirect(null, false, null, null);
+    public void testNetworkSpecifierDirectNullPeerInitiator() throws Exception {
+        executeNetworkSpecifierDirect(null, false, null, PASSPHRASE_VALID, true);
+    }
+
+    /**
+     * Validate that a null peer MAC triggers an exception for a Resonder.
+     */
+    @Test(expected = IllegalArgumentException.class)
+    public void testNetworkSpecifierDirectNullPeerResponder() throws Exception {
+        executeNetworkSpecifierDirect(null, false, null, PASSPHRASE_VALID, false);
+    }
+
+    /**
+     * Validate that a null peer MAC does not trigger an exception for a Resonder on legacy API.
+     */
+    @Test
+    public void testNetworkSpecifierDirectNullPeerResponderLegacyApi() throws Exception {
+        mockApplicationInfo.targetSdkVersion = Build.VERSION_CODES.O;
+        executeNetworkSpecifierDirect(null, false, null, PASSPHRASE_VALID, false);
     }
 
     private void executeNetworkSpecifierDirect(byte[] someMac, boolean doPmk, byte[] pmk,
-            String passphrase) throws Exception {
+            String passphrase, boolean doInitiator) throws Exception {
         final int clientId = 134;
-        final int role = WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR;
+        final int role = doInitiator ? WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR
+                : WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER;
         final ConfigRequest configRequest = new ConfigRequest.Builder().build();
 
         ArgumentCaptor<WifiAwareSession> sessionCaptor = ArgumentCaptor.forClass(