Merge "Update ringer setting API visibility per council feeedback"
diff --git a/Android.bp b/Android.bp
index e8f3561..5f81191 100644
--- a/Android.bp
+++ b/Android.bp
@@ -736,7 +736,7 @@
         "updatable_media_stubs",
     ],
 
-    jarjar_rules: "jarjar_rules_hidl.txt",
+    jarjar_rules: ":framework-jarjar-rules",
 
     static_libs: [
         "apex_aidl_interface-java",
@@ -789,6 +789,11 @@
 }
 
 filegroup {
+    name: "framework-jarjar-rules",
+    srcs: ["jarjar_rules_hidl.txt"],
+}
+
+filegroup {
     name: "libincident_aidl",
     srcs: [
         "core/java/android/os/IIncidentManager.aidl",
diff --git a/api/current.txt b/api/current.txt
index 5e0f996..ef9b44c 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -15802,7 +15802,7 @@
     ctor public Font.Builder(@NonNull android.os.ParcelFileDescriptor, @IntRange(from=0) long, @IntRange(from=0xffffffff) long);
     ctor public Font.Builder(@NonNull android.content.res.AssetManager, @NonNull String);
     ctor public Font.Builder(@NonNull android.content.res.Resources, int);
-    method @Nullable public android.graphics.fonts.Font build() throws java.io.IOException;
+    method @NonNull public android.graphics.fonts.Font build() throws java.io.IOException;
     method @NonNull public android.graphics.fonts.Font.Builder setFontVariationSettings(@Nullable String);
     method @NonNull public android.graphics.fonts.Font.Builder setFontVariationSettings(@Nullable android.graphics.fonts.FontVariationAxis[]);
     method @NonNull public android.graphics.fonts.Font.Builder setSlant(int);
@@ -15929,13 +15929,13 @@
 
   public static class LineBreaker.ParagraphConstraints {
     ctor public LineBreaker.ParagraphConstraints();
-    method @Px @IntRange(from=0) public int getDefaultTabStop();
+    method @Px @FloatRange(from=0) public float getDefaultTabStop();
     method @Px @FloatRange(from=0.0f) public float getFirstWidth();
     method @Px @IntRange(from=0) public int getFirstWidthLineCount();
-    method @Nullable public int[] getTabStops();
+    method @Nullable public float[] getTabStops();
     method @Px @FloatRange(from=0.0f) public float getWidth();
     method public void setIndent(@Px @FloatRange(from=0.0f) float, @Px @IntRange(from=0) int);
-    method public void setTabStops(@Nullable int[], @Px @IntRange(from=0) int);
+    method public void setTabStops(@Nullable float[], @Px @FloatRange(from=0) float);
     method public void setWidth(@Px @FloatRange(from=0.0f) float);
   }
 
diff --git a/api/system-current.txt b/api/system-current.txt
index d22bbd8..def5a47 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -1198,7 +1198,7 @@
     method public int getUsageSource();
     method @RequiresPermission(allOf={android.Manifest.permission.SUSPEND_APPS, android.Manifest.permission.OBSERVE_APP_USAGE}) public void registerAppUsageLimitObserver(int, @NonNull String[], @NonNull java.time.Duration, @NonNull java.time.Duration, @Nullable android.app.PendingIntent);
     method @RequiresPermission(android.Manifest.permission.OBSERVE_APP_USAGE) public void registerAppUsageObserver(int, @NonNull String[], long, @NonNull java.util.concurrent.TimeUnit, @NonNull android.app.PendingIntent);
-    method @RequiresPermission(android.Manifest.permission.OBSERVE_APP_USAGE) public void registerUsageSessionObserver(int, @NonNull String[], long, @NonNull java.util.concurrent.TimeUnit, long, @NonNull java.util.concurrent.TimeUnit, @NonNull android.app.PendingIntent, @Nullable android.app.PendingIntent);
+    method @RequiresPermission(android.Manifest.permission.OBSERVE_APP_USAGE) public void registerUsageSessionObserver(int, @NonNull String[], @NonNull java.time.Duration, @NonNull java.time.Duration, @NonNull android.app.PendingIntent, @Nullable android.app.PendingIntent);
     method public void reportUsageStart(@NonNull android.app.Activity, @NonNull String);
     method public void reportUsageStart(@NonNull android.app.Activity, @NonNull String, long);
     method public void reportUsageStop(@NonNull android.app.Activity, @NonNull String);
diff --git a/api/system-removed.txt b/api/system-removed.txt
index 18d0ec0..2c65029 100644
--- a/api/system-removed.txt
+++ b/api/system-removed.txt
@@ -28,6 +28,14 @@
 
 }
 
+package android.app.usage {
+
+  public final class UsageStatsManager {
+    method @Deprecated @RequiresPermission(android.Manifest.permission.OBSERVE_APP_USAGE) public void registerUsageSessionObserver(int, @NonNull String[], long, @NonNull java.util.concurrent.TimeUnit, long, @NonNull java.util.concurrent.TimeUnit, @NonNull android.app.PendingIntent, @Nullable android.app.PendingIntent);
+  }
+
+}
+
 package android.content {
 
   public class Intent implements java.lang.Cloneable android.os.Parcelable {
diff --git a/core/java/android/app/usage/UsageStatsManager.java b/core/java/android/app/usage/UsageStatsManager.java
index e47ec22..b5224c7 100644
--- a/core/java/android/app/usage/UsageStatsManager.java
+++ b/core/java/android/app/usage/UsageStatsManager.java
@@ -660,6 +660,30 @@
         }
     }
 
+
+    /**
+     * @deprecated use {@link #registerUsageSessionObserver(int, String[], Duration, Duration,
+     *                                                      PendingIntent, PendingIntent)}.
+     *
+     * @removed
+     * @hide
+     */
+    @Deprecated
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.OBSERVE_APP_USAGE)
+    // STOPSHIP b/128455269: remove this method
+    public void registerUsageSessionObserver(int sessionObserverId,
+            @NonNull String[] observedEntities, long timeLimit, @NonNull TimeUnit timeUnit,
+            long sessionThresholdTime,  @NonNull TimeUnit sessionThresholdTimeUnit,
+            @NonNull PendingIntent limitReachedCallbackIntent,
+            @Nullable PendingIntent sessionEndCallbackIntent) {
+        final Duration timeLimitDuration = Duration.ofMillis(timeUnit.toMillis(timeLimit));
+        final Duration sessionThresholdDuration =
+                Duration.ofMillis(sessionThresholdTimeUnit.toMillis(sessionThresholdTime));
+        registerUsageSessionObserver(sessionObserverId, observedEntities, timeLimitDuration,
+                sessionThresholdDuration, limitReachedCallbackIntent, sessionEndCallbackIntent);
+    }
+
     /**
      * Register a usage session observer that receives a callback on the provided {@code
      * limitReachedCallbackIntent} when the sum of usages of apps and tokens in the {@code
@@ -679,11 +703,8 @@
      *                         null and must include at least one package or token.
      * @param timeLimit The total time the set of apps can be used continuously before the {@code
      *                  limitReachedCallbackIntent} is delivered. Must be at least one minute.
-     * @param timeUnit The unit for time specified in {@code timeLimit}. Cannot be null.
      * @param sessionThresholdTime The time that can take place between usage sessions before the
      *                             next session is considered a new session. Must be non-negative.
-     * @param sessionThresholdTimeUnit The unit for time specified in {@code sessionThreshold}.
-     *                                 Cannot be null.
      * @param limitReachedCallbackIntent The {@link PendingIntent} that will be dispatched when the
      *                                   usage limit is exceeded by the group of apps. The
      *                                   delivered Intent will also contain the extras {@link
@@ -703,14 +724,13 @@
     @SystemApi
     @RequiresPermission(android.Manifest.permission.OBSERVE_APP_USAGE)
     public void registerUsageSessionObserver(int sessionObserverId,
-            @NonNull String[] observedEntities, long timeLimit, @NonNull TimeUnit timeUnit,
-            long sessionThresholdTime,  @NonNull TimeUnit sessionThresholdTimeUnit,
+            @NonNull String[] observedEntities, @NonNull Duration timeLimit,
+            @NonNull Duration sessionThresholdTime,
             @NonNull PendingIntent limitReachedCallbackIntent,
             @Nullable PendingIntent sessionEndCallbackIntent) {
         try {
             mService.registerUsageSessionObserver(sessionObserverId, observedEntities,
-                    timeUnit.toMillis(timeLimit),
-                    sessionThresholdTimeUnit.toMillis(sessionThresholdTime),
+                    timeLimit.toMillis(), sessionThresholdTime.toMillis(),
                     limitReachedCallbackIntent, sessionEndCallbackIntent,
                     mContext.getOpPackageName());
         } catch (RemoteException e) {
diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java
index fb6dc22..bf0ef94 100644
--- a/core/java/android/text/Layout.java
+++ b/core/java/android/text/Layout.java
@@ -2192,26 +2192,26 @@
      */
     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
     public static class TabStops {
-        private int[] mStops;
+        private float[] mStops;
         private int mNumStops;
-        private int mIncrement;
+        private float mIncrement;
 
-        public TabStops(int increment, Object[] spans) {
+        public TabStops(float increment, Object[] spans) {
             reset(increment, spans);
         }
 
-        void reset(int increment, Object[] spans) {
+        void reset(float increment, Object[] spans) {
             this.mIncrement = increment;
 
             int ns = 0;
             if (spans != null) {
-                int[] stops = this.mStops;
+                float[] stops = this.mStops;
                 for (Object o : spans) {
                     if (o instanceof TabStopSpan) {
                         if (stops == null) {
-                            stops = new int[10];
+                            stops = new float[10];
                         } else if (ns == stops.length) {
-                            int[] nstops = new int[ns * 2];
+                            float[] nstops = new float[ns * 2];
                             for (int i = 0; i < ns; ++i) {
                                 nstops[i] = stops[i];
                             }
@@ -2233,9 +2233,9 @@
         float nextTab(float h) {
             int ns = this.mNumStops;
             if (ns > 0) {
-                int[] stops = this.mStops;
+                float[] stops = this.mStops;
                 for (int i = 0; i < ns; ++i) {
-                    int stop = stops[i];
+                    float stop = stops[i];
                     if (stop > h) {
                         return stop;
                     }
@@ -2244,7 +2244,10 @@
             return nextDefaultStop(h, mIncrement);
         }
 
-        public static float nextDefaultStop(float h, int inc) {
+        /**
+         * Returns the position of next tab stop.
+         */
+        public static float nextDefaultStop(float h, float inc) {
             return ((int) ((h + inc) / inc)) * inc;
         }
     }
@@ -2582,7 +2585,7 @@
         ALIGN_RIGHT,
     }
 
-    private static final int TAB_INCREMENT = 20;
+    private static final float TAB_INCREMENT = 20;
 
     /** @hide */
     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java
index 9fefc83..69cfc03 100644
--- a/core/java/android/text/StaticLayout.java
+++ b/core/java/android/text/StaticLayout.java
@@ -737,14 +737,14 @@
                 }
             }
             // tab stop locations
-            int[] variableTabStops = null;
+            float[] variableTabStops = null;
             if (spanned != null) {
                 TabStopSpan[] spans = getParagraphSpans(spanned, paraStart,
                         paraEnd, TabStopSpan.class);
                 if (spans.length > 0) {
-                    int[] stops = new int[spans.length];
+                    float[] stops = new float[spans.length];
                     for (int i = 0; i < spans.length; i++) {
-                        stops[i] = spans[i].getTabStop();
+                        stops[i] = (float) spans[i].getTabStop();
                     }
                     Arrays.sort(stops, 0, stops.length);
                     variableTabStops = stops;
@@ -1422,7 +1422,7 @@
     private static final int START_HYPHEN_MASK = 0x18; // 0b11000
     private static final int END_HYPHEN_MASK = 0x7;  // 0b00111
 
-    private static final int TAB_INCREMENT = 20; // same as Layout, but that's private
+    private static final float TAB_INCREMENT = 20; // same as Layout, but that's private
 
     private static final char CHAR_NEW_LINE = '\n';
 
diff --git a/core/java/android/view/contentcapture/ContentCaptureEvent.java b/core/java/android/view/contentcapture/ContentCaptureEvent.java
index 67d3629..8188e05 100644
--- a/core/java/android/view/contentcapture/ContentCaptureEvent.java
+++ b/core/java/android/view/contentcapture/ContentCaptureEvent.java
@@ -303,6 +303,47 @@
         return mText;
     }
 
+    /**
+     * Merges event of the same type, either {@link #TYPE_VIEW_TEXT_CHANGED}
+     * or {@link #TYPE_VIEW_DISAPPEARED}.
+     *
+     * @hide
+     */
+    public void mergeEvent(@NonNull ContentCaptureEvent event) {
+        Preconditions.checkNotNull(event);
+        final int eventType = event.getType();
+        if (mType != eventType) {
+            Log.e(TAG, "mergeEvent(" + getTypeAsString(eventType) + ") cannot be merged "
+                    + "with different eventType=" + getTypeAsString(mType));
+            return;
+        }
+
+        if (eventType == TYPE_VIEW_DISAPPEARED) {
+            final List<AutofillId> ids = event.getIds();
+            final AutofillId id = event.getId();
+            if (ids != null) {
+                if (id != null) {
+                    Log.w(TAG, "got TYPE_VIEW_DISAPPEARED event with both id and ids: " + event);
+                }
+                for (int i = 0; i < ids.size(); i++) {
+                    addAutofillId(ids.get(i));
+                }
+                return;
+            }
+            if (id != null) {
+                addAutofillId(id);
+                return;
+            }
+            throw new IllegalArgumentException("mergeEvent(): got "
+                    + "TYPE_VIEW_DISAPPEARED event with neither id or ids: " + event);
+        } else if (eventType == TYPE_VIEW_TEXT_CHANGED) {
+            setText(event.getText());
+        } else {
+            Log.e(TAG, "mergeEvent(" + getTypeAsString(eventType)
+                    + ") does not support this event type.");
+        }
+    }
+
     /** @hide */
     public void dump(@NonNull PrintWriter pw) {
         pw.print("type="); pw.print(getTypeAsString(mType));
diff --git a/core/java/android/view/contentcapture/MainContentCaptureSession.java b/core/java/android/view/contentcapture/MainContentCaptureSession.java
index dce8ebe..a2b12e0 100644
--- a/core/java/android/view/contentcapture/MainContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/MainContentCaptureSession.java
@@ -295,8 +295,7 @@
                     Log.v(TAG, "Buffering VIEW_TEXT_CHANGED event, updated text="
                             + getSanitizedString(event.getText()));
                 }
-                // TODO(b/124107816): should call lastEvent.merge(event) instead
-                lastEvent.setText(event.getText());
+                lastEvent.mergeEvent(event);
                 addEvent = false;
             }
         }
@@ -309,7 +308,7 @@
                     Log.v(TAG, "Buffering TYPE_VIEW_DISAPPEARED events for session "
                             + lastEvent.getSessionId());
                 }
-                mergeViewsDisappearedEvent(lastEvent, event);
+                lastEvent.mergeEvent(event);
                 addEvent = false;
             }
         }
@@ -357,30 +356,6 @@
         flush(flushReason);
     }
 
-    // TODO(b/124107816): should be ContentCaptureEvent Event.merge(event) instead (which would
-    // replace the addAutofillId() method - we would also need unit tests on ContentCaptureEventTest
-    // to check these scenarios)
-    private void mergeViewsDisappearedEvent(@NonNull ContentCaptureEvent lastEvent,
-            @NonNull ContentCaptureEvent event) {
-        final List<AutofillId> ids = event.getIds();
-        final AutofillId id = event.getId();
-        if (ids != null) {
-            if (id != null) {
-                Log.w(TAG, "got TYPE_VIEW_DISAPPEARED event with both id and ids: " + event);
-            }
-            for (int i = 0; i < ids.size(); i++) {
-                lastEvent.addAutofillId(ids.get(i));
-            }
-            return;
-        }
-        if (id != null) {
-            lastEvent.addAutofillId(id);
-            return;
-        }
-        throw new IllegalArgumentException(
-                "got TYPE_VIEW_DISAPPEARED event with neither id or ids: " + event);
-    }
-
     @UiThread
     private boolean hasStarted() {
         return mState != UNKNOWN_STATE;
diff --git a/core/jni/android/graphics/text/LineBreaker.cpp b/core/jni/android/graphics/text/LineBreaker.cpp
index c23f1e9..a23f99a 100644
--- a/core/jni/android/graphics/text/LineBreaker.cpp
+++ b/core/jni/android/graphics/text/LineBreaker.cpp
@@ -80,13 +80,13 @@
         jfloat firstWidth,
         jint firstWidthLineCount,
         jfloat restWidth,
-        jintArray variableTabStops,
-        jint defaultTabStop,
+        jfloatArray variableTabStops,
+        jfloat defaultTabStop,
         jint indentsOffset) {
     minikin::android::StaticLayoutNative* builder = toNative(nativePtr);
 
     ScopedCharArrayRO text(env, javaText);
-    ScopedNullableIntArrayRO tabStops(env, variableTabStops);
+    ScopedNullableFloatArrayRO tabStops(env, variableTabStops);
 
     minikin::U16StringPiece u16Text(text.get(), length);
     minikin::MeasuredText* measuredText = reinterpret_cast<minikin::MeasuredText*>(measuredTextPtr);
@@ -151,8 +151,8 @@
         "F"  // firstWidth
         "I"  // firstWidthLineCount
         "F"  // restWidth
-        "[I"  // variableTabStops
-        "I"  // defaultTabStop
+        "[F"  // variableTabStops
+        "F"  // defaultTabStop
         "I"  // indentsOffset
         ")J", (void*) nComputeLineBreaks},
 
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index ea300aa..587d677 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -867,6 +867,7 @@
         android:label="@string/permgrouplab_visual"
         android:description="@string/permgroupdesc_visual"
         android:request="@string/permgrouprequest_visual"
+        android:requestDetail="@string/permgrouprequestdetail_visual"
         android:priority="920" />
 
     <!-- Allows an application to read the user's shared images collection. -->
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index bf7c8f2..bc66756 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -800,7 +800,9 @@
     <string name="permgroupdesc_visual">access your photos &amp; videos</string>
     <!-- Message shown to the user when the apps requests permission from this group. If ever possible this should stay below 80 characters (assuming the parameters takes 20 characters). Don't abbreviate until the message reaches 120 characters though. [CHAR LIMIT=120] -->
     <string name="permgrouprequest_visual">Allow
-        &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access your photos and videos, including tagged locations?</string>
+        &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access your photos and videos?</string>
+    <!-- Subtitle of the message shown to the user when the apps requests permission to access photos and videos [CHAR LIMIT=150]-->
+    <string name="permgrouprequestdetail_visual">Locations and other people in your photos and videos can be identified by the app</string>
 
     <!-- Title for the capability of an accessibility service to retrieve window content. -->
     <string name="capability_title_canRetrieveWindowContent">Retrieve window content</string>
diff --git a/core/tests/coretests/src/android/view/contentcapture/ContentCaptureEventTest.java b/core/tests/coretests/src/android/view/contentcapture/ContentCaptureEventTest.java
index de2edc3..2416de1 100644
--- a/core/tests/coretests/src/android/view/contentcapture/ContentCaptureEventTest.java
+++ b/core/tests/coretests/src/android/view/contentcapture/ContentCaptureEventTest.java
@@ -19,6 +19,7 @@
 import static android.view.contentcapture.ContentCaptureEvent.TYPE_SESSION_FINISHED;
 import static android.view.contentcapture.ContentCaptureEvent.TYPE_SESSION_STARTED;
 import static android.view.contentcapture.ContentCaptureEvent.TYPE_VIEW_DISAPPEARED;
+import static android.view.contentcapture.ContentCaptureEvent.TYPE_VIEW_TEXT_CHANGED;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -230,6 +231,68 @@
         assertContextUpdatedEvent(clone);
     }
 
+    @Test
+    public void testMergeEvent_typeViewTextChanged() {
+        final ContentCaptureEvent event = new ContentCaptureEvent("42", TYPE_VIEW_TEXT_CHANGED)
+                .setText("test");
+        final ContentCaptureEvent event2 = new ContentCaptureEvent("43", TYPE_VIEW_TEXT_CHANGED)
+                .setText("empty");
+
+        event.mergeEvent(event2);
+        assertThat(event.getText()).isEqualTo(event2.getText());
+    }
+
+    @Test
+    public void testMergeEvent_typeViewDisappeared() {
+        final ContentCaptureEvent event = new ContentCaptureEvent("42", TYPE_VIEW_DISAPPEARED)
+                .setAutofillId(new AutofillId(1));
+        final ContentCaptureEvent event2 = new ContentCaptureEvent("43", TYPE_VIEW_DISAPPEARED)
+                .setAutofillId(new AutofillId(2));
+        final ArrayList<AutofillId> autofillIds = new ArrayList<>();
+        autofillIds.add(new AutofillId(3));
+        autofillIds.add(new AutofillId(4));
+        final ContentCaptureEvent event3 = new ContentCaptureEvent("17", TYPE_VIEW_DISAPPEARED)
+                .setAutofillIds(autofillIds);
+
+        event.mergeEvent(event2);
+        assertThat(event.getIds()).containsExactly(new AutofillId(1), new AutofillId(2));
+
+        event2.mergeEvent(event3);
+        assertThat(event2.getIds()).containsExactly(new AutofillId(2), new AutofillId(3),
+                new AutofillId(4));
+    }
+
+    @Test
+    public void testMergeEvent_typeViewDisappeared_noIds() {
+        final ContentCaptureEvent event = new ContentCaptureEvent("42", TYPE_VIEW_DISAPPEARED)
+                .setAutofillId(new AutofillId(1));
+        final ContentCaptureEvent event2 = new ContentCaptureEvent("43", TYPE_VIEW_DISAPPEARED);
+
+        assertThrows(IllegalArgumentException.class, () -> event.mergeEvent(event2));
+    }
+
+    @Test
+    public void testMergeEvent_nullArgument() {
+        final ContentCaptureEvent event = new ContentCaptureEvent("42", TYPE_VIEW_DISAPPEARED);
+        assertThrows(NullPointerException.class, () -> event.mergeEvent(null));
+    }
+
+    @Test
+    public void testMergeEvent_differentEventTypes() {
+        final ContentCaptureEvent event = new ContentCaptureEvent("42", TYPE_VIEW_DISAPPEARED)
+                .setText("test").setAutofillId(new AutofillId(1));
+        final ContentCaptureEvent event2 = new ContentCaptureEvent("17", TYPE_VIEW_TEXT_CHANGED)
+                .setText("empty").setAutofillId(new AutofillId(2));
+
+        event.mergeEvent(event2);
+        assertThat(event.getText()).isEqualTo("test");
+        assertThat(event.getId()).isEqualTo(new AutofillId(1));
+
+        event2.mergeEvent(event);
+        assertThat(event2.getText()).isEqualTo("empty");
+        assertThat(event2.getId()).isEqualTo(new AutofillId(2));
+    }
+
     private void assertContextUpdatedEvent(ContentCaptureEvent event) {
         assertThat(event.getType()).isEqualTo(TYPE_CONTEXT_UPDATED);
         assertThat(event.getEventTime()).isAtLeast(MY_EPOCH);
diff --git a/graphics/java/android/graphics/fonts/Font.java b/graphics/java/android/graphics/fonts/Font.java
index f92802f..c788f32 100644
--- a/graphics/java/android/graphics/fonts/Font.java
+++ b/graphics/java/android/graphics/fonts/Font.java
@@ -360,7 +360,7 @@
          *
          * @return the Font object
          */
-        public @Nullable Font build() throws IOException {
+        public @NonNull Font build() throws IOException {
             if (mException != null) {
                 throw new IOException("Failed to read font contents", mException);
             }
diff --git a/graphics/java/android/graphics/text/LineBreaker.java b/graphics/java/android/graphics/text/LineBreaker.java
index 9cabf1c..2a36276 100644
--- a/graphics/java/android/graphics/text/LineBreaker.java
+++ b/graphics/java/android/graphics/text/LineBreaker.java
@@ -248,8 +248,8 @@
         private @FloatRange(from = 0.0f) float mWidth = 0;
         private @FloatRange(from = 0.0f) float mFirstWidth = 0;
         private @IntRange(from = 0) int mFirstWidthLineCount = 0;
-        private @Nullable int[] mVariableTabStops = null;
-        private @IntRange(from = 0) int mDefaultTabStop = 0;
+        private @Nullable float[] mVariableTabStops = null;
+        private @FloatRange(from = 0) float mDefaultTabStop = 0;
 
         public ParagraphConstraints() {}
 
@@ -284,8 +284,8 @@
          * @see #getTabStops()
          * @see #getDefaultTabStop()
          */
-        public void setTabStops(@Nullable int[] tabStops,
-                @Px @IntRange(from = 0) int defaultTabStop) {
+        public void setTabStops(@Nullable float[] tabStops,
+                @Px @FloatRange(from = 0) float defaultTabStop) {
             mVariableTabStops = tabStops;
             mDefaultTabStop = defaultTabStop;
         }
@@ -320,18 +320,18 @@
         /**
          * Returns the array of tab stops in pixels.
          *
-         * @see #setTabStops(int[], int)
+         * @see #setTabStops(float[], int)
          */
-        public @Nullable int[] getTabStops() {
+        public @Nullable float[] getTabStops() {
             return mVariableTabStops;
         }
 
         /**
          * Returns the default tab stops in pixels.
          *
-         * @see #setTabStop(int[], int)
+         * @see #setTabStop(float[], int)
          */
-        public @Px @IntRange(from = 0) int getDefaultTabStop() {
+        public @Px @FloatRange(from = 0) float getDefaultTabStop() {
             return mDefaultTabStop;
         }
     }
@@ -513,8 +513,8 @@
             @FloatRange(from = 0.0f) float firstWidth,
             @IntRange(from = 0) int firstWidthLineCount,
             @FloatRange(from = 0.0f) float restWidth,
-            @Nullable int[] variableTabStops,
-            int defaultTabStop,
+            @Nullable float[] variableTabStops,
+            float defaultTabStop,
             @IntRange(from = 0) int indentsOffset);
 
     // Result accessors
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeDockHandler.java b/packages/SystemUI/src/com/android/systemui/doze/DozeDockHandler.java
index 06dbdbf..a4592d5 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeDockHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeDockHandler.java
@@ -121,11 +121,17 @@
                     if (dozeState == State.DOZE
                             && mConfig.alwaysOnEnabled(UserHandle.USER_CURRENT)) {
                         mMachine.requestState(State.DOZE_AOD);
-                        break;
                     }
-                    // continue below
+                    else {
+                        requestPulseOutNow(dozeState);
+                    }
+                    break;
                 case DockManager.STATE_DOCKED_HIDE:
-                    requestPulseOutNow(dozeState);
+                    if (dozeState == State.DOZE_AOD) {
+                        mMachine.requestState(State.DOZE);
+                    } else {
+                        requestPulseOutNow(dozeState);
+                    }
                     break;
                 default:
                     // no-op
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeDockHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeDockHandlerTest.java
index 4ba2858..df014a4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeDockHandlerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeDockHandlerTest.java
@@ -202,4 +202,16 @@
 
         verify(mMachine).requestState(eq(State.DOZE));
     }
+
+    @Test
+    public void testTransitionToPulsing_whenDockedHide_requestPulseOut() {
+        mDockHandler.transitionTo(DozeMachine.State.UNINITIALIZED, DozeMachine.State.INITIALIZED);
+        when(mMachine.getState()).thenReturn(DozeMachine.State.DOZE_PULSING);
+        when(mMachine.getPulseReason()).thenReturn(DozeLog.PULSE_REASON_DOCKING);
+        mDockManagerFake.setDockEvent(DockManager.STATE_DOCKED_HIDE);
+
+        mDockHandler.transitionTo(DozeMachine.State.INITIALIZED, State.DOZE_PULSING);
+
+        verify(mHost).stopPulsing();
+    }
 }
diff --git a/services/core/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java
index 710a0ba3..3a50aa8 100644
--- a/services/core/java/com/android/server/UiModeManagerService.java
+++ b/services/core/java/com/android/server/UiModeManagerService.java
@@ -30,13 +30,11 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.os.BatteryManager;
 import android.os.Binder;
-import android.os.Build;
 import android.os.Handler;
 import android.os.PowerManager;
 import android.os.PowerManager.ServiceType;
@@ -356,8 +354,8 @@
             try {
                 synchronized (mLock) {
                     if (mNightMode != mode) {
-                        // Only persist setting if not transient night mode or not in car mode
-                        if (!shouldTransientNightWhenInCarMode() || !mCarModeEnabled) {
+                        // Only persist setting if not in car mode
+                        if (!mCarModeEnabled) {
                             Settings.Secure.putIntForUser(getContext().getContentResolver(),
                                     Settings.Secure.UI_NIGHT_MODE, mode, user);
                         }
@@ -444,34 +442,12 @@
         }
     }
 
-    // Night mode settings in car mode are only persisted below Q.
-    // When targeting Q, changes are not saved and night mode will be re-read
-    // from settings when exiting car mode.
-    private boolean shouldTransientNightWhenInCarMode() {
-        int uid = Binder.getCallingUid();
-        PackageManager packageManager = getContext().getPackageManager();
-        String[] packagesForUid = packageManager.getPackagesForUid(uid);
-        if (packagesForUid == null || packagesForUid.length == 0) {
-            return false;
-        }
-
-        try {
-            ApplicationInfo appInfo = packageManager.getApplicationInfoAsUser(
-                    packagesForUid[0], 0, uid);
-
-            return appInfo.targetSdkVersion >= Build.VERSION_CODES.Q;
-        } catch (PackageManager.NameNotFoundException ignored) {
-        }
-
-        return false;
-    }
-
     void setCarModeLocked(boolean enabled, int flags) {
         if (mCarModeEnabled != enabled) {
             mCarModeEnabled = enabled;
 
-            // When transient night mode and exiting car mode, restore night mode from settings
-            if (shouldTransientNightWhenInCarMode() && !mCarModeEnabled) {
+            // When exiting car mode, restore night mode from settings
+            if (!mCarModeEnabled) {
                 Context context = getContext();
                 updateNightModeFromSettings(context,
                         context.getResources(),
@@ -534,9 +510,8 @@
             uiMode |= mNightMode << 4;
         }
 
-        // Override night mode in power save mode if not transient night mode or not in car mode
-        boolean shouldOverrideNight = !mCarModeEnabled || !shouldTransientNightWhenInCarMode();
-        if (mPowerSave && shouldOverrideNight) {
+        // Override night mode in power save mode if not in car mode
+        if (mPowerSave && !mCarModeEnabled) {
             uiMode &= ~Configuration.UI_MODE_NIGHT_NO;
             uiMode |= Configuration.UI_MODE_NIGHT_YES;
         }
diff --git a/services/core/java/com/android/server/am/OWNERS b/services/core/java/com/android/server/am/OWNERS
index e483b26..877bef7 100644
--- a/services/core/java/com/android/server/am/OWNERS
+++ b/services/core/java/com/android/server/am/OWNERS
@@ -23,6 +23,9 @@
 svetoslavganov@google.com
 toddke@google.com
 
+# Battery Stats
+joeo@google.com
+
 # Londoners
 michaelwr@google.com
 narayan@google.com
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index a7d70de..d249b97 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -589,7 +589,7 @@
         session = new PackageInstallerSession(mInternalCallback, mContext, mPm, this,
                 mInstallThread.getLooper(), mStagingManager, sessionId, userId,
                 installerPackageName, callingUid, params, createdMillis, stageDir, stageCid, false,
-                false, null, SessionInfo.INVALID_ID, false, false, false,
+                false, false, null, SessionInfo.INVALID_ID, false, false, false,
                 SessionInfo.STAGED_SESSION_NO_ERROR, "");
 
         synchronized (mSessions) {
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 2de50e2..81c0a97 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -145,6 +145,7 @@
     private static final String ATTR_SESSION_STAGE_DIR = "sessionStageDir";
     private static final String ATTR_SESSION_STAGE_CID = "sessionStageCid";
     private static final String ATTR_PREPARED = "prepared";
+    private static final String ATTR_COMMITTED = "committed";
     private static final String ATTR_SEALED = "sealed";
     private static final String ATTR_MULTI_PACKAGE = "multiPackage";
     private static final String ATTR_PARENT_SESSION_ID = "parentSessionId";
@@ -401,7 +402,7 @@
             PackageSessionProvider sessionProvider, Looper looper, StagingManager stagingManager,
             int sessionId, int userId,
             String installerPackageName, int installerUid, SessionParams params, long createdMillis,
-            File stageDir, String stageCid, boolean prepared, boolean sealed,
+            File stageDir, String stageCid, boolean prepared, boolean committed, boolean sealed,
             @Nullable int[] childSessionIds, int parentSessionId, boolean isReady,
             boolean isFailed, boolean isApplied, int stagedSessionErrorCode,
             String stagedSessionErrorMessage) {
@@ -434,6 +435,7 @@
         }
 
         mPrepared = prepared;
+        mCommitted = committed;
         mStagedSessionReady = isReady;
         mStagedSessionFailed = isFailed;
         mStagedSessionApplied = isApplied;
@@ -2156,6 +2158,7 @@
 
         pw.printPair("mClientProgress", mClientProgress);
         pw.printPair("mProgress", mProgress);
+        pw.printPair("mCommitted", mCommitted);
         pw.printPair("mSealed", mSealed);
         pw.printPair("mPermissionsManuallyAccepted", mPermissionsManuallyAccepted);
         pw.printPair("mRelinquished", mRelinquished);
@@ -2214,6 +2217,7 @@
                 writeStringAttribute(out, ATTR_SESSION_STAGE_CID, stageCid);
             }
             writeBooleanAttribute(out, ATTR_PREPARED, isPrepared());
+            writeBooleanAttribute(out, ATTR_COMMITTED, isCommitted());
             writeBooleanAttribute(out, ATTR_SEALED, isSealed());
 
             writeBooleanAttribute(out, ATTR_MULTI_PACKAGE, params.isMultiPackage);
@@ -2311,6 +2315,7 @@
         final File stageDir = (stageDirRaw != null) ? new File(stageDirRaw) : null;
         final String stageCid = readStringAttribute(in, ATTR_SESSION_STAGE_CID);
         final boolean prepared = readBooleanAttribute(in, ATTR_PREPARED, true);
+        final boolean committed = readBooleanAttribute(in, ATTR_COMMITTED);
         final boolean sealed = readBooleanAttribute(in, ATTR_SEALED);
         final int parentSessionId = readIntAttribute(in, ATTR_PARENT_SESSION_ID,
                 SessionInfo.INVALID_ID);
@@ -2387,8 +2392,8 @@
 
         return new PackageInstallerSession(callback, context, pm, sessionProvider,
                 installerThread, stagingManager, sessionId, userId, installerPackageName,
-                installerUid, params, createdMillis, stageDir, stageCid, prepared, sealed,
-                childSessionIdsArray, parentSessionId, isReady, isFailed, isApplied,
+                installerUid, params, createdMillis, stageDir, stageCid, prepared, committed,
+                sealed, childSessionIdsArray, parentSessionId, isReady, isFailed, isApplied,
                 stagedSessionErrorCode, stagedSessionErrorMessage);
     }
 
diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java
index ae75574..4a4a8e3 100644
--- a/services/core/java/com/android/server/pm/StagingManager.java
+++ b/services/core/java/com/android/server/pm/StagingManager.java
@@ -603,6 +603,10 @@
     }
 
     private void checkStateAndResume(@NonNull PackageInstallerSession session) {
+        if (!session.isCommitted()) {
+            // Session hasn't been committed yet, ignore.
+            return;
+        }
         // Check the state of the session and decide what to do next.
         if (session.isStagedSessionFailed() || session.isStagedSessionApplied()) {
             // Final states, nothing to do.
diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
index d58707c..2af2342 100644
--- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java
+++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
@@ -443,7 +443,7 @@
          * Returns true if the window is current in multi-windowing mode. i.e. it shares the
          * screen with other application windows.
          */
-        public boolean isInMultiWindowMode();
+        boolean inMultiWindowMode();
 
         public int getRotationAnimationHint();
 
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index bb5a221..af05a27 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -2237,6 +2237,10 @@
                 || transit == TRANSIT_ACTIVITY_RELAUNCH;
     }
 
+    static boolean isChangeTransit(int transit) {
+        return transit == TRANSIT_TASK_CHANGE_WINDOWING_MODE;
+    }
+
     /**
      * @return whether the transition should show the thumbnail being scaled down.
      */
diff --git a/services/core/java/com/android/server/wm/AppTransitionController.java b/services/core/java/com/android/server/wm/AppTransitionController.java
index 8f0a7c0..f6326957 100644
--- a/services/core/java/com/android/server/wm/AppTransitionController.java
+++ b/services/core/java/com/android/server/wm/AppTransitionController.java
@@ -513,8 +513,11 @@
         // Given no app transition pass it through instead of a wallpaper transition.
         // Never convert the crashing transition.
         // Never update the transition for the wallpaper if we are just docking from recents
+        // Never convert a change transition since the top activity isn't changing and will likely
+        // still be above an opening wallpaper.
         if (transit == TRANSIT_NONE || transit == TRANSIT_CRASHING_ACTIVITY_CLOSE
-                || transit == TRANSIT_DOCK_TASK_FROM_RECENTS) {
+                || transit == TRANSIT_DOCK_TASK_FROM_RECENTS
+                || AppTransition.isChangeTransit(transit)) {
             return transit;
         }
 
@@ -601,6 +604,10 @@
      */
     @VisibleForTesting
     int maybeUpdateTransitToTranslucentAnim(int transit) {
+        if (AppTransition.isChangeTransit(transit)) {
+            // There's no special animation to handle change animations with translucent apps
+            return transit;
+        }
         final boolean taskOrActivity = AppTransition.isTaskTransit(transit)
                 || AppTransition.isActivityTransit(transit);
         boolean allOpeningVisible = true;
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 220370c..ea3a7d5 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -1747,7 +1747,7 @@
     }
 
     boolean isInChangeTransition() {
-        return mTransitChangeLeash != null || isChangeTransition(mTransit);
+        return mTransitChangeLeash != null || AppTransition.isChangeTransit(mTransit);
     }
 
     @VisibleForTesting
@@ -1979,7 +1979,14 @@
                 mLetterbox.attachInput(w);
             }
             getPosition(mTmpPoint);
-            mLetterbox.layout(getParent().getBounds(), w.getFrameLw(), mTmpPoint);
+            // Get the bounds of the "space-to-fill". We union the Task and the Stack bounds here
+            // to handle both split window (where task-bounds can be larger) and orientation
+            // letterbox (where the task is letterboxed within stack).
+            Rect spaceToFill = getTask().getBounds();
+            if (getStack() != null) {
+                spaceToFill.union(getStack().getBounds());
+            }
+            mLetterbox.layout(spaceToFill, w.getFrameLw(), mTmpPoint);
         } else if (mLetterbox != null) {
             mLetterbox.hide();
         }
@@ -2448,30 +2455,6 @@
         return boundsLayer;
     }
 
-    /** Get position and crop region of animation. */
-    @VisibleForTesting
-    void getAnimationBounds(Point outPosition, Rect outBounds) {
-        outPosition.set(0, 0);
-        outBounds.setEmpty();
-
-        final TaskStack stack = getStack();
-        final Task task = getTask();
-        if (task != null && task.inFreeformWindowingMode()) {
-            task.getRelativeDisplayedPosition(outPosition);
-        } else if (stack != null) {
-            stack.getRelativeDisplayedPosition(outPosition);
-        }
-
-        // Always use stack bounds in order to have the ability to animate outside the task region.
-        // It also needs to be consistent when {@link #mNeedsAnimationBoundsLayer} is set that crops
-        // according to the bounds.
-        if (stack != null) {
-            stack.getBounds(outBounds);
-        }
-        // We have the relative position so the local position can be removed from bounds.
-        outBounds.offsetTo(0, 0);
-    }
-
     @Override
     Rect getDisplayedBounds() {
         final Task task = getTask();
@@ -2484,10 +2467,6 @@
         return getBounds();
     }
 
-    private static boolean isChangeTransition(int transit) {
-        return transit == TRANSIT_TASK_CHANGE_WINDOWING_MODE;
-    }
-
     boolean applyAnimationLocked(WindowManager.LayoutParams lp, int transit, boolean enter,
             boolean isVoiceInteraction) {
 
@@ -2507,9 +2486,15 @@
         if (okToAnimate()) {
             final AnimationAdapter adapter;
             AnimationAdapter thumbnailAdapter = null;
-            getAnimationBounds(mTmpPoint, mTmpRect);
 
-            boolean isChanging = isChangeTransition(transit) && enter;
+            // Separate position and size for use in animators. Use task-bounds for now so
+            // that activity-level letterbox (maxAspectRatio) is included in the animation.
+            mTmpRect.set(getTask() != null ? getTask().getBounds() : getBounds());
+            mTmpPoint.set(mTmpRect.left, mTmpRect.top);
+            mTmpRect.offsetTo(0, 0);
+
+            final boolean isChanging = AppTransition.isChangeTransit(transit) && enter
+                    && getDisplayContent().mChangingApps.contains(this);
 
             // Delaying animation start isn't compatible with remote animations at all.
             if (getDisplayContent().mAppTransition.getRemoteAnimationController() != null
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index e48361f..d3f6689 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -2146,7 +2146,7 @@
         // TYPE_SYSTEM_ERROR is above the NavigationBar so it can't be allowed to extend over it.
         // Also, we don't allow windows in multi-window mode to extend out of the screen.
         if ((fl & FLAG_LAYOUT_NO_LIMITS) != 0 && type != TYPE_SYSTEM_ERROR
-                && !win.isInMultiWindowMode()) {
+                && !win.inMultiWindowMode()) {
             df.left = df.top = -10000;
             df.right = df.bottom = 10000;
             if (type != TYPE_WALLPAPER) {
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 499cbaf..bb7867c 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -433,29 +433,6 @@
         }
     }
 
-    /** Return true if the current bound can get outputted to the rest of the system as-is. */
-    private boolean useCurrentBounds() {
-        final DisplayContent displayContent = getDisplayContent();
-        return matchParentBounds()
-                || !inSplitScreenSecondaryWindowingMode()
-                || displayContent == null
-                || displayContent.getSplitScreenPrimaryStackIgnoringVisibility() != null;
-    }
-
-    @Override
-    public void getBounds(Rect out) {
-        if (useCurrentBounds()) {
-            // No need to adjust the output bounds if fullscreen or the docked stack is visible
-            // since it is already what we want to represent to the rest of the system.
-            super.getBounds(out);
-            return;
-        }
-
-        // The bounds has been adjusted to accommodate for a docked stack, but the docked stack is
-        // not currently visible. Go ahead a represent it as fullscreen to the rest of the system.
-        mStack.getDisplayContent().getBounds(out);
-    }
-
     @Override
     public Rect getDisplayedBounds() {
         if (mOverrideDisplayedBounds.isEmpty()) {
@@ -506,36 +483,28 @@
         // a DimLayer anyway if we weren't visible.
         final boolean dockedResizing = displayContent != null
                 && displayContent.mDividerControllerLocked.isResizing();
-        if (useCurrentBounds()) {
-            if (inFreeformWindowingMode() && getMaxVisibleBounds(out)) {
-                return;
-            }
-
-            if (!matchParentBounds()) {
-                // When minimizing the docked stack when going home, we don't adjust the task bounds
-                // so we need to intersect the task bounds with the stack bounds here.
-                //
-                // If we are Docked Resizing with snap points, the task bounds could be smaller than the stack
-                // bounds and so we don't even want to use them. Even if the app should not be resized the Dim
-                // should keep up with the divider.
-                if (dockedResizing) {
-                    mStack.getBounds(out);
-                } else {
-                    mStack.getBounds(mTmpRect);
-                    mTmpRect.intersect(getBounds());
-                    out.set(mTmpRect);
-                }
-            } else {
-                out.set(getBounds());
-            }
+        if (inFreeformWindowingMode() && getMaxVisibleBounds(out)) {
             return;
         }
 
-        // The bounds has been adjusted to accommodate for a docked stack, but the docked stack is
-        // not currently visible. Go ahead a represent it as fullscreen to the rest of the system.
-        if (displayContent != null) {
-            displayContent.getBounds(out);
+        if (!matchParentBounds()) {
+            // When minimizing the docked stack when going home, we don't adjust the task bounds
+            // so we need to intersect the task bounds with the stack bounds here.
+            //
+            // If we are Docked Resizing with snap points, the task bounds could be smaller than the
+            // stack bounds and so we don't even want to use them. Even if the app should not be
+            // resized the Dim should keep up with the divider.
+            if (dockedResizing) {
+                mStack.getBounds(out);
+            } else {
+                mStack.getBounds(mTmpRect);
+                mTmpRect.intersect(getBounds());
+                out.set(mTmpRect);
+            }
+        } else {
+            out.set(getBounds());
         }
+        return;
     }
 
     void setDragResizing(boolean dragResizing, int dragResizeMode) {
@@ -702,16 +671,6 @@
         positionChildAt(position, aToken, false /* includeParents */);
     }
 
-    boolean isFullscreen() {
-        if (useCurrentBounds()) {
-            return matchParentBounds();
-        }
-        // The bounds has been adjusted to accommodate for a docked stack, but the docked stack
-        // is not currently visible. Go ahead a represent it as fullscreen to the rest of the
-        // system.
-        return true;
-    }
-
     void forceWindowsScaleable(boolean force) {
         mWmService.openSurfaceTransaction();
         try {
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 241f14e..e6b8112 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -303,17 +303,6 @@
         return super.getBounds();
     }
 
-    /** Return true if the current bound can get outputted to the rest of the system as-is. */
-    private boolean useCurrentBounds() {
-        if (matchParentBounds()
-                || !inSplitScreenSecondaryWindowingMode()
-                || mDisplayContent == null
-                || mDisplayContent.getSplitScreenPrimaryStackIgnoringVisibility() != null) {
-            return true;
-        }
-        return false;
-    }
-
     @Override
     public void getBounds(Rect bounds) {
         bounds.set(getBounds());
@@ -321,22 +310,15 @@
 
     @Override
     public Rect getBounds() {
-        if (useCurrentBounds()) {
-            // If we're currently adjusting for IME or minimized docked stack, we use the adjusted
-            // bounds; otherwise, no need to adjust the output bounds if fullscreen or the docked
-            // stack is visible since it is already what we want to represent to the rest of the
-            // system.
-            if (!mAdjustedBounds.isEmpty()) {
-                return mAdjustedBounds;
-            } else {
-                return super.getBounds();
-            }
-        }
-
-        // The bounds has been adjusted to accommodate for a docked stack, but the docked stack
-        // is not currently visible. Go ahead a represent it as fullscreen to the rest of the
+        // If we're currently adjusting for IME or minimized docked stack, we use the adjusted
+        // bounds; otherwise, no need to adjust the output bounds if fullscreen or the docked
+        // stack is visible since it is already what we want to represent to the rest of the
         // system.
-        return mDisplayContent.getBounds();
+        if (!mAdjustedBounds.isEmpty()) {
+            return mAdjustedBounds;
+        } else {
+            return super.getBounds();
+        }
     }
 
     /**
@@ -1425,13 +1407,7 @@
 
     @Override
     boolean fillsParent() {
-        if (useCurrentBounds()) {
-            return matchParentBounds();
-        }
-        // The bounds has been adjusted to accommodate for a docked stack, but the docked stack
-        // is not currently visible. Go ahead a represent it as fullscreen to the rest of the
-        // system.
-        return true;
+        return matchParentBounds();
     }
 
     @Override
@@ -1516,7 +1492,7 @@
 
         for (int i = mChildren.size() - 1; i >= 0; --i) {
             final Task task = mChildren.get(i);
-            if (task.isFullscreen()) {
+            if (task.getWindowingMode() == WINDOWING_MODE_FULLSCREEN) {
                 results.searchDone = true;
                 return;
             }
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 20cca66..ee445d8 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -826,7 +826,7 @@
         mHaveFrame = true;
 
         final Task task = getTask();
-        final boolean inFullscreenContainer = inFullscreenContainer();
+        final boolean isFullscreenAndFillsDisplay = !inMultiWindowMode() && matchesDisplayBounds();
         final boolean windowsAreFloating = task != null && task.isFloating();
         final DisplayContent dc = getDisplayContent();
 
@@ -845,7 +845,7 @@
         final WindowState imeWin = mWmService.mRoot.getCurrentInputMethodWindow();
         final boolean isImeTarget =
                 imeWin != null && imeWin.isVisibleNow() && isInputMethodTarget();
-        if (inFullscreenContainer || layoutInParentFrame()) {
+        if (isFullscreenAndFillsDisplay || layoutInParentFrame()) {
             // We use the parent frame as the containing frame for fullscreen and child windows
             mWindowFrames.mContainingFrame.set(mWindowFrames.mParentFrame);
             layoutDisplayFrame = mWindowFrames.mDisplayFrame;
@@ -983,7 +983,7 @@
                     Math.min(mWindowFrames.mStableFrame.bottom, mWindowFrames.mFrame.bottom));
         }
 
-        if (inFullscreenContainer && !windowsAreFloating) {
+        if (isFullscreenAndFillsDisplay && !windowsAreFloating) {
             // Windows that are not fullscreen can be positioned outside of the display frame,
             // but that is not a reason to provide them with overscan insets.
             InsetUtils.insetsBetweenFrames(layoutContainingFrame, mWindowFrames.mOverscanFrame,
@@ -996,7 +996,8 @@
             mWindowFrames.calculateDockedDividerInsets(c.getDisplayCutout().getSafeInsets());
         } else {
             getDisplayContent().getBounds(mTmpRect);
-            mWindowFrames.calculateInsets(windowsAreFloating, inFullscreenContainer, mTmpRect);
+            mWindowFrames.calculateInsets(
+                    windowsAreFloating, isFullscreenAndFillsDisplay, mTmpRect);
         }
 
         mWindowFrames.setDisplayCutout(
@@ -1038,9 +1039,7 @@
     // TODO: Look into whether this override is still necessary.
     @Override
     public Rect getBounds() {
-        if (isInMultiWindowMode()) {
-            return getTask().getBounds();
-        } else if (mAppToken != null){
+        if (mAppToken != null) {
             return mAppToken.getBounds();
         } else {
             return super.getBounds();
@@ -1751,6 +1750,10 @@
                 && mWindowFrames.mFrame.bottom >= displayInfo.appHeight;
     }
 
+    private boolean matchesDisplayBounds() {
+        return getDisplayContent().getBounds().equals(getBounds());
+    }
+
     /** Returns true if last applied config was not yet requested by client. */
     boolean isConfigChanged() {
         return !getLastReportedConfiguration().equals(getConfiguration());
@@ -3114,20 +3117,16 @@
         return getDisplayContent().mCurrentFocus == this;
     }
 
-    @Override
-    public boolean isInMultiWindowMode() {
-        final Task task = getTask();
-        return task != null && !task.isFullscreen();
-    }
 
     /** Is this window in a container that takes up the entire screen space? */
-    private boolean inFullscreenContainer() {
-        return mAppToken == null || (mAppToken.matchParentBounds() && !isInMultiWindowMode());
+    private boolean inAppWindowThatMatchesParentBounds() {
+        return mAppToken == null || (mAppToken.matchParentBounds() && !inMultiWindowMode());
     }
 
-    /** @return true when the window is in fullscreen task, but has non-fullscreen bounds set. */
+    /** @return true when the window is in fullscreen mode, but has non-fullscreen bounds set, or
+     *          is transitioning into/out-of fullscreen. */
     boolean isLetterboxedAppWindow() {
-        return !isInMultiWindowMode() && mAppToken != null && !mAppToken.matchParentBounds()
+        return !inMultiWindowMode() && !matchesDisplayBounds()
                 || isLetterboxedForDisplayCutoutLw();
     }
 
@@ -3494,7 +3493,7 @@
         final int pw = containingFrame.width();
         final int ph = containingFrame.height();
         final Task task = getTask();
-        final boolean inNonFullscreenContainer = !inFullscreenContainer();
+        final boolean inNonFullscreenContainer = !inAppWindowThatMatchesParentBounds();
         final boolean noLimits = (mAttrs.flags & FLAG_LAYOUT_NO_LIMITS) != 0;
 
         // We need to fit it to the display if either
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 92bb082..780d471 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -26,7 +26,6 @@
 
 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
-import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_FREEFORM;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
@@ -792,16 +791,10 @@
         if (DEBUG_WINDOW_CROP) Slog.d(TAG, "Applying decor to crop win=" + w + " mDecorFrame="
                 + w.getDecorFrame() + " mSystemDecorRect=" + mSystemDecorRect);
 
-        final Task task = w.getTask();
-        final boolean fullscreen = w.fillsDisplay() || (task != null && task.isFullscreen());
-        final boolean isFreeformResizing =
-                w.isDragResizing() && w.getResizeMode() == DRAG_RESIZE_MODE_FREEFORM;
-
         // We use the clip rect as provided by the tranformation for non-fullscreen windows to
         // avoid premature clipping with the system decor rect.
         clipRect.set(mSystemDecorRect);
-        if (DEBUG_WINDOW_CROP) Slog.d(TAG, "win=" + w + " Initial clip rect: " + clipRect
-                + " fullscreen=" + fullscreen);
+        if (DEBUG_WINDOW_CROP) Slog.d(TAG, "win=" + w + " Initial clip rect: " + clipRect);
 
         w.expandForSurfaceInsets(clipRect);
 
diff --git a/services/core/java/com/android/server/wm/WindowTraceBuffer.java b/services/core/java/com/android/server/wm/WindowTraceBuffer.java
index a4ee907..8c65884 100644
--- a/services/core/java/com/android/server/wm/WindowTraceBuffer.java
+++ b/services/core/java/com/android/server/wm/WindowTraceBuffer.java
@@ -93,8 +93,8 @@
     void writeTraceToFile(File traceFile) throws IOException {
         synchronized (mBufferLock) {
             traceFile.delete();
-            traceFile.setReadable(true, false);
             try (OutputStream os = new FileOutputStream(traceFile)) {
+                traceFile.setReadable(true /* readable */, false /* ownerOnly */);
                 ProtoOutputStream proto = new ProtoOutputStream();
                 proto.write(MAGIC_NUMBER, MAGIC_NUMBER_VALUE);
                 os.write(proto.getBytes());
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageInstallerSessionTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageInstallerSessionTest.java
index 26722fd..d3f33a1 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageInstallerSessionTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageInstallerSessionTest.java
@@ -167,6 +167,7 @@
                 /* stageDir */ mTmpDir,
                 /* stageCid */ null,
                 /* prepared */ true,
+                /* committed */ true,
                 /* sealed */ false,  // Setting to true would trigger some PM logic.
                 /* childSessionIds */ childSessionIds != null ? childSessionIds : new int[0],
                 /* parentSessionId */ parentSessionId,
@@ -300,6 +301,7 @@
         assertEquals(expected.getStagedSessionErrorMessage(),
                 actual.getStagedSessionErrorMessage());
         assertEquals(expected.isPrepared(), actual.isPrepared());
+        assertEquals(expected.isCommitted(), actual.isCommitted());
         assertEquals(expected.isSealed(), actual.isSealed());
         assertEquals(expected.isMultiPackage(), actual.isMultiPackage());
         assertEquals(expected.hasParentSessionId(), actual.hasParentSessionId());
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
index 5e12a95..81133d1 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
@@ -18,6 +18,7 @@
 
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.view.WindowManager.TRANSIT_TASK_CHANGE_WINDOWING_MODE;
 import static android.view.WindowManager.TRANSIT_TASK_CLOSE;
 import static android.view.WindowManager.TRANSIT_TASK_OPEN;
 
@@ -77,4 +78,21 @@
                             TRANSIT_TASK_CLOSE));
         }
     }
+
+    @Test
+    public void testChangeIsNotOverwritten() {
+        synchronized (mWm.mGlobalLock) {
+            final AppWindowToken behind = createAppWindowToken(mDisplayContent,
+                    WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
+            final AppWindowToken translucentOpening = createAppWindowToken(mDisplayContent,
+                    WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
+            translucentOpening.setFillsParent(false);
+            translucentOpening.setHidden(true);
+            mDisplayContent.mOpeningApps.add(behind);
+            mDisplayContent.mOpeningApps.add(translucentOpening);
+            assertEquals(TRANSIT_TASK_CHANGE_WINDOWING_MODE,
+                    mAppTransitionController.maybeUpdateTransitToTranslucentAnim(
+                            TRANSIT_TASK_CHANGE_WINDOWING_MODE));
+        }
+    }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
index 70c8c93..d17e5c3 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
@@ -16,8 +16,6 @@
 
 package com.android.server.wm;
 
-import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
-import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
@@ -48,7 +46,6 @@
 import static org.mockito.Mockito.verify;
 
 import android.content.res.Configuration;
-import android.graphics.Point;
 import android.graphics.Rect;
 import android.platform.test.annotations.Presubmit;
 import android.view.Display;
@@ -475,32 +472,6 @@
         assertHasStartingWindow(tokenBottom);
     }
 
-    @Test
-    public void testTransitionAnimationPositionAndBounds() {
-        final Rect stackBounds = new Rect(
-                0/* left */, 0 /* top */, 1000 /* right */, 1000 /* bottom */);
-        final Rect taskBounds = new Rect(
-                100/* left */, 200 /* top */, 600 /* right */, 600 /* bottom */);
-        mStack.setBounds(stackBounds);
-        mTask.setBounds(taskBounds);
-
-        mTask.setWindowingMode(WINDOWING_MODE_FREEFORM);
-        assertTransitionAnimationPositionAndBounds(taskBounds.left, taskBounds.top, stackBounds);
-
-        mTask.setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
-        assertTransitionAnimationPositionAndBounds(stackBounds.left, stackBounds.top, stackBounds);
-    }
-
-    private void assertTransitionAnimationPositionAndBounds(int expectedX, int expectedY,
-            Rect expectedBounds) {
-        final Point outPosition = new Point();
-        final Rect outBounds = new Rect();
-        mToken.getAnimationBounds(outPosition, outBounds);
-        assertEquals(expectedX, outPosition.x);
-        assertEquals(expectedY, outPosition.y);
-        assertEquals(expectedBounds, outBounds);
-    }
-
     private void assertHasStartingWindow(AppWindowToken atoken) {
         assertNotNull(atoken.startingSurface);
         assertNotNull(atoken.startingData);
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java
index 2ccdb9e..78fca0f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java
@@ -19,6 +19,7 @@
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
 import static android.view.DisplayCutout.BOUNDS_POSITION_TOP;
 import static android.view.DisplayCutout.fromBoundingRect;
 import static android.view.WindowManager.LayoutParams.MATCH_PARENT;
@@ -27,7 +28,6 @@
 import static org.junit.Assert.assertEquals;
 import static org.mockito.Mockito.mock;
 
-import android.app.ActivityManager.TaskDescription;
 import android.content.res.Configuration;
 import android.graphics.Rect;
 import android.platform.test.annotations.Presubmit;
@@ -54,23 +54,15 @@
 @Presubmit
 public class WindowFrameTests extends WindowTestsBase {
 
-    private WindowToken mWindowToken;
     private final IWindow mIWindow = new TestIWindow();
     private final Rect mEmptyRect = new Rect();
 
-    static class WindowStateWithTask extends WindowState {
-        final Task mTask;
+    static class FrameTestWindowState extends WindowState {
         boolean mDockedResizingForTest = false;
-        WindowStateWithTask(WindowManagerService wm, IWindow iWindow, WindowToken windowToken,
-                WindowManager.LayoutParams attrs, Task t) {
+        FrameTestWindowState(WindowManagerService wm, IWindow iWindow, WindowToken windowToken,
+                WindowManager.LayoutParams attrs) {
             super(wm, mock(Session.class), iWindow, windowToken, null, 0, 0, attrs, 0, 0,
                     false /* ownerCanAddInternalSystemWindow */);
-            mTask = t;
-        }
-
-        @Override
-        Task getTask() {
-            return mTask;
         }
 
         @Override
@@ -79,52 +71,10 @@
         }
     }
 
-    private static class TaskWithBounds extends Task {
-        Rect mBounds;
-        final Rect mOverrideDisplayedBounds = new Rect();
-        boolean mFullscreenForTest = true;
-
-        TaskWithBounds(TaskStack stack, WindowManagerService wm, Rect bounds) {
-            super(0, stack, 0, wm, 0, false, new TaskDescription(), null);
-            setBounds(bounds);
-        }
-
-        @Override
-        public int setBounds(Rect bounds) {
-            mBounds = bounds;
-            return super.setBounds(bounds);
-        }
-
-        @Override
-        public Rect getBounds() {
-            return mBounds;
-        }
-
-        @Override
-        public void getBounds(Rect out) {
-            out.set(mBounds);
-        }
-
-        @Override
-        public void getRequestedOverrideBounds(Rect outBounds) {
-            outBounds.set(mBounds);
-        }
-        @Override
-        Rect getOverrideDisplayedBounds() {
-            return mOverrideDisplayedBounds;
-        }
-        @Override
-        boolean isFullscreen() {
-            return mFullscreenForTest;
-        }
-    }
-
     TaskStack mStubStack;
 
     @Before
     public void setUp() throws Exception {
-        mWindowToken = createAppWindowToken(mWm.getDefaultDisplayContentLocked(),
-                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
         mStubStack = mock(TaskStack.class);
     }
 
@@ -168,7 +118,8 @@
                 expectedRect.bottom);
     }
 
-    private void assertPolicyCrop(WindowStateWithTask w, int left, int top, int right, int bottom) {
+    private void assertPolicyCrop(
+            FrameTestWindowState w, int left, int top, int right, int bottom) {
         Rect policyCrop = new Rect();
         w.calculatePolicyCrop(policyCrop);
         assertRect(policyCrop, left, top, right, bottom);
@@ -177,8 +128,7 @@
     @Test
     public void testLayoutInFullscreenTaskInsets() {
         // fullscreen task doesn't use bounds for computeFrame
-        final Task task = new TaskWithBounds(mStubStack, mWm, null);
-        WindowState w = createWindow(task, MATCH_PARENT, MATCH_PARENT);
+        WindowState w = createWindow(MATCH_PARENT, MATCH_PARENT);
         w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;
 
         final int bottomContentInset = 100;
@@ -235,8 +185,7 @@
     @Test
     public void testLayoutInFullscreenTaskNoInsets() {
         // fullscreen task doesn't use bounds for computeFrame
-        final Task task = new TaskWithBounds(mStubStack, mWm, null);
-        WindowState w = createWindow(task, MATCH_PARENT, MATCH_PARENT);
+        WindowState w = createWindow(MATCH_PARENT, MATCH_PARENT);
         w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;
 
         // With no insets or system decor all the frames incoming from PhoneWindowManager
@@ -323,9 +272,11 @@
         final int taskRight = logicalWidth / 4 * 3;
         final int taskBottom = logicalHeight / 4 * 3;
         final Rect taskBounds = new Rect(taskLeft, taskTop, taskRight, taskBottom);
-        final TaskWithBounds task = new TaskWithBounds(mStubStack, mWm, taskBounds);
-        task.mFullscreenForTest = false;
-        WindowState w = createWindow(task, MATCH_PARENT, MATCH_PARENT);
+        WindowState w = createWindow(MATCH_PARENT, MATCH_PARENT);
+        final Task task = w.getTask();
+        // Use split-screen because it is non-fullscreen, but also not floating
+        task.setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
+        task.setBounds(taskBounds);
         w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;
 
         final Rect pf = new Rect(0, 0, logicalWidth, logicalHeight);
@@ -359,8 +310,8 @@
         final int insetTop = logicalHeight / 5;
         final int insetRight = insetLeft + (taskRight - taskLeft);
         final int insetBottom = insetTop + (taskBottom - taskTop);
-        task.mOverrideDisplayedBounds.set(taskBounds);
-        task.mBounds.set(insetLeft, insetTop, insetRight, insetBottom);
+        task.setOverrideDisplayedBounds(taskBounds);
+        task.setBounds(insetLeft, insetTop, insetRight, insetBottom);
         windowFrames.setFrames(pf, pf, pf, cf, cf, pf, cf, mEmptyRect);
         w.computeFrameLw();
         assertFrame(w, taskLeft, taskTop, taskRight, taskBottom);
@@ -373,8 +324,7 @@
 
     @Test
     public void testCalculatePolicyCrop() {
-        final WindowStateWithTask w = createWindow(
-                new TaskWithBounds(mStubStack, mWm, null), MATCH_PARENT, MATCH_PARENT);
+        final FrameTestWindowState w = createWindow(MATCH_PARENT, MATCH_PARENT);
         w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;
 
         final DisplayInfo displayInfo = w.getDisplayContent().getDisplayInfo();
@@ -439,9 +389,11 @@
         final int taskRight = logicalWidth / 4 * 3;
         final int taskBottom = logicalHeight / 4 * 3;
         final Rect taskBounds = new Rect(taskLeft, taskTop, taskRight, taskBottom);
-        final TaskWithBounds task = new TaskWithBounds(mStubStack, mWm, taskBounds);
-        task.mFullscreenForTest = false;
-        WindowState w = createWindow(task, MATCH_PARENT, MATCH_PARENT);
+        WindowState w = createWindow(MATCH_PARENT, MATCH_PARENT);
+        final Task task = w.getTask();
+        // Use split-screen because it is non-fullscreen, but also not floating
+        task.setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
+        task.setBounds(taskBounds);
         w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;
 
         final Rect pf = new Rect(0, 0, logicalWidth, logicalHeight);
@@ -461,7 +413,8 @@
         config.windowConfiguration.setBounds(cf);
         w.mAppToken.onRequestedOverrideConfigurationChanged(config);
         pf.set(0, 0, logicalWidth, logicalHeight);
-        task.mFullscreenForTest = true;
+        task.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
+        task.setBounds(null);
         windowFrames.setFrames(pf, pf, pf, cf, cf, pf, cf, mEmptyRect);
         w.computeFrameLw();
         assertFrame(w, cf.left, cf.top, cf.right, cf.bottom);
@@ -472,8 +425,7 @@
     @Test
     public void testDisplayCutout() {
         // Regular fullscreen task and window
-        final Task task = new TaskWithBounds(mStubStack, mWm, null);
-        WindowState w = createWindow(task, MATCH_PARENT, MATCH_PARENT);
+        WindowState w = createWindow(MATCH_PARENT, MATCH_PARENT);
         w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;
 
         final Rect pf = new Rect(0, 0, 1000, 2000);
@@ -496,11 +448,10 @@
     @Test
     public void testDisplayCutout_tempDisplayedBounds() {
         // Regular fullscreen task and window
-        final TaskWithBounds task = new TaskWithBounds(mStubStack, mWm,
-                new Rect(0, 0, 1000, 2000));
-        task.mFullscreenForTest = false;
+        WindowState w = createWindow(MATCH_PARENT, MATCH_PARENT);
+        final Task task = w.getTask();
+        task.setBounds(new Rect(0, 0, 1000, 2000));
         task.setOverrideDisplayedBounds(new Rect(0, -500, 1000, 1500));
-        WindowState w = createWindow(task, MATCH_PARENT, MATCH_PARENT);
         w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;
 
         final Rect pf = new Rect(0, -500, 1000, 1500);
@@ -523,12 +474,10 @@
     @Test
     public void testFreeformContentInsets() {
         // fullscreen task doesn't use bounds for computeFrame
-        final Task task = new TaskWithBounds(mStubStack, mWm, null);
-        WindowState w = createWindow(task, MATCH_PARENT, MATCH_PARENT);
+        WindowState w = createWindow(MATCH_PARENT, MATCH_PARENT);
+        final Task task = w.getTask();
         w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;
         task.setWindowingMode(WINDOWING_MODE_FREEFORM);
-        ((TaskWithBounds) task).mFullscreenForTest = false;
-        w.setWindowingMode(WINDOWING_MODE_FREEFORM);
 
         DisplayContent dc = mWm.getDefaultDisplayContentLocked();
         dc.mInputMethodTarget = w;
@@ -551,7 +500,6 @@
         final Rect winRect = new Rect(200, 200, 300, 500);
 
         task.setBounds(winRect);
-        w.setBounds(winRect);
         w.getWindowFrames().setFrames(pf, df, of, cf, vf, dcf, sf, mEmptyRect);
         w.computeFrameLw();
 
@@ -580,11 +528,16 @@
         assertEquals(winRect, w.getFrameLw());
     }
 
-    private WindowStateWithTask createWindow(Task task, int width, int height) {
+    private FrameTestWindowState createWindow(int width, int height) {
         final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(TYPE_APPLICATION);
         attrs.width = width;
         attrs.height = height;
 
-        return new WindowStateWithTask(mWm, mIWindow, mWindowToken, attrs, task);
+        AppWindowToken token = createAppWindowToken(mWm.getDefaultDisplayContentLocked(),
+                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
+
+        FrameTestWindowState ws = new FrameTestWindowState(mWm, mIWindow, token, attrs);
+        token.addWindow(ws);
+        return ws;
     }
 }
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index ae12a17..28e6596 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -555,6 +555,15 @@
     public static final String EVENT_CALL_MERGE_FAILED = "android.telecom.event.CALL_MERGE_FAILED";
 
     /**
+     * Connection event used to inform Telecom when a hold operation on a call has failed.
+     * Not intended for use by the UI at this time.
+     * Sent via {@link #sendConnectionEvent(String, Bundle)}.  The {@link Bundle} parameter is
+     * expected to be null when this connection event is used.
+     * @hide
+     */
+    public static final String EVENT_CALL_HOLD_FAILED = "android.telecom.event.CALL_HOLD_FAILED";
+
+    /**
      * Connection event used to inform {@link InCallService}s when the process of merging a
      * Connection into a conference has begun.
      * <p>
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 0c6bc48..f07ac5a 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -6152,7 +6152,7 @@
         // FIXME Need to get it from Telephony Dev Controller when that gets implemented!
         // and then this method shouldn't be used at all!
         if(isMultiSimEnabled()) {
-            return 2;
+            return getPhoneCount();
         } else {
             return 1;
         }
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 869f665..52e03ce 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -1001,8 +1001,9 @@
     /**
      * In this Wi-Fi lock mode, Wi-Fi will not go to power save.
      * This results in operating with low packet latency.
-     * The lock is active  even when the device screen is off or
-     * the acquiring application is running in the background.
+     * The lock is only active when the device is connected to an access point.
+     * The lock is active even when the device screen is off or the acquiring application is
+     * running in the background.
      * This mode will consume more power and hence should be used only
      * when there is a need for this tradeoff.
      * <p>
@@ -1020,6 +1021,7 @@
      * In this Wi-Fi lock mode, Wi-Fi will operate with a priority to achieve low latency.
      * {@link #WIFI_MODE_FULL_LOW_LATENCY} lock has the following limitations:
      * <ol>
+     * <li>The lock is only active when the device is connected to an access point.</li>
      * <li>The lock is only active when the screen is on.</li>
      * <li>The lock is only active when the acquiring app is running in the foreground.</li>
      * </ol>