Merge "Move lower idle alarm throttling to rolling quotas" into udc-dev
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index e6d6361..c14de70 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -13040,6 +13040,21 @@
     method public int getStart();
   }
 
+  public final class DetectedPhrase implements android.os.Parcelable {
+    method public int describeContents();
+    method public int getId();
+    method @Nullable public String getPhrase();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.service.voice.DetectedPhrase> CREATOR;
+  }
+
+  public static final class DetectedPhrase.Builder {
+    ctor public DetectedPhrase.Builder();
+    method @NonNull public android.service.voice.DetectedPhrase build();
+    method @NonNull public android.service.voice.DetectedPhrase.Builder setId(int);
+    method @NonNull public android.service.voice.DetectedPhrase.Builder setPhrase(@NonNull String);
+  }
+
   public abstract class DetectorFailure implements android.os.Parcelable {
     method public int describeContents();
     method @NonNull public String getErrorMessage();
@@ -13080,12 +13095,13 @@
     method public int getAudioChannel();
     method @NonNull public java.util.List<android.service.voice.HotwordAudioStream> getAudioStreams();
     method public int getConfidenceLevel();
+    method @NonNull public android.service.voice.DetectedPhrase getDetectedPhrase();
     method @NonNull public android.os.PersistableBundle getExtras();
     method public int getHotwordDurationMillis();
     method public int getHotwordOffsetMillis();
-    method public int getHotwordPhraseId();
+    method @Deprecated public int getHotwordPhraseId();
     method public static int getMaxBundleSize();
-    method public static int getMaxHotwordPhraseId();
+    method @Deprecated public static int getMaxHotwordPhraseId();
     method public static int getMaxScore();
     method @Nullable public android.media.MediaSyncEvent getMediaSyncEvent();
     method public int getPersonalizedScore();
@@ -13114,11 +13130,12 @@
     method @NonNull public android.service.voice.HotwordDetectedResult.Builder setAudioChannel(int);
     method @NonNull public android.service.voice.HotwordDetectedResult.Builder setAudioStreams(@NonNull java.util.List<android.service.voice.HotwordAudioStream>);
     method @NonNull public android.service.voice.HotwordDetectedResult.Builder setConfidenceLevel(int);
+    method @NonNull public android.service.voice.HotwordDetectedResult.Builder setDetectedPhrase(@NonNull android.service.voice.DetectedPhrase);
     method @NonNull public android.service.voice.HotwordDetectedResult.Builder setExtras(@NonNull android.os.PersistableBundle);
     method @NonNull public android.service.voice.HotwordDetectedResult.Builder setHotwordDetectionPersonalized(boolean);
     method @NonNull public android.service.voice.HotwordDetectedResult.Builder setHotwordDurationMillis(int);
     method @NonNull public android.service.voice.HotwordDetectedResult.Builder setHotwordOffsetMillis(int);
-    method @NonNull public android.service.voice.HotwordDetectedResult.Builder setHotwordPhraseId(int);
+    method @Deprecated @NonNull public android.service.voice.HotwordDetectedResult.Builder setHotwordPhraseId(int);
     method @NonNull public android.service.voice.HotwordDetectedResult.Builder setMediaSyncEvent(@NonNull android.media.MediaSyncEvent);
     method @NonNull public android.service.voice.HotwordDetectedResult.Builder setPersonalizedScore(int);
     method @NonNull public android.service.voice.HotwordDetectedResult.Builder setScore(int);
diff --git a/core/java/android/service/voice/DetectedPhrase.aidl b/core/java/android/service/voice/DetectedPhrase.aidl
new file mode 100644
index 0000000..23a405d
--- /dev/null
+++ b/core/java/android/service/voice/DetectedPhrase.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2023 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.service.voice;
+
+parcelable DetectedPhrase;
diff --git a/core/java/android/service/voice/DetectedPhrase.java b/core/java/android/service/voice/DetectedPhrase.java
new file mode 100644
index 0000000..bd90612
--- /dev/null
+++ b/core/java/android/service/voice/DetectedPhrase.java
@@ -0,0 +1,286 @@
+/*
+ * Copyright (C) 2023 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.service.voice;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.os.Parcelable;
+
+import com.android.internal.util.DataClass;
+import com.android.internal.util.Preconditions;
+
+/**
+ * Details about the phrase used to generate a {@link HotwordDetectedResult}
+ *
+ * @hide
+ */
+@DataClass(
+        genConstructor = false,
+        genBuilder = true,
+        genEqualsHashCode = true,
+        genHiddenConstDefs = true,
+        genParcelable = true,
+        genToString = true
+)
+@SystemApi
+public final class DetectedPhrase implements Parcelable {
+
+    /**
+     * An ID representing the keyphrase that triggered the successful detection.
+     */
+    private int mId = 0;
+
+    static int defaultHotwordPhraseId() {
+        return 0;
+    }
+
+    /**
+     * A string representing exactly what was heard and interpreted by the service leading to
+     * a successful detection.
+     *
+     * <p>Can be null if not set in {@link DetectedPhrase.Builder}
+     */
+    @Nullable
+    private String mPhrase = null;
+
+    /**
+     * Provides an instance of {@link DetectedPhrase.Builder} with state corresponding to
+     * this instance.
+     * @hide
+     */
+    public DetectedPhrase.Builder buildUpon() {
+        return new DetectedPhrase.Builder()
+                .setId(mId)
+                .setPhrase(mPhrase);
+    }
+
+    private void onConstructed() {
+        Preconditions.checkArgumentNonnegative(mId, "hotwordPhraseId");
+    }
+
+
+
+    // Code below generated by codegen v1.0.23.
+    //
+    // DO NOT MODIFY!
+    // CHECKSTYLE:OFF Generated code
+    //
+    // To regenerate run:
+    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/service/voice/DetectedPhrase.java
+    //
+    // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+    //   Settings > Editor > Code Style > Formatter Control
+    //@formatter:off
+
+
+    @DataClass.Generated.Member
+    /* package-private */ DetectedPhrase(
+            int id,
+            @Nullable String phrase) {
+        this.mId = id;
+        this.mPhrase = phrase;
+
+        onConstructed();
+    }
+
+    /**
+     * An ID representing the keyphrase that triggered the successful detection.
+     */
+    @DataClass.Generated.Member
+    public int getId() {
+        return mId;
+    }
+
+    /**
+     * A string representing exactly what was heard and interpreted by the service leading to
+     * a successful detection.
+     *
+     * <p>Can be null if not set in {@link DetectedPhrase.Builder}
+     */
+    @DataClass.Generated.Member
+    public @Nullable String getPhrase() {
+        return mPhrase;
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public String toString() {
+        // You can override field toString logic by defining methods like:
+        // String fieldNameToString() { ... }
+
+        return "DetectedPhrase { " +
+                "id = " + mId + ", " +
+                "phrase = " + mPhrase +
+        " }";
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public boolean equals(@Nullable Object o) {
+        // You can override field equality logic by defining either of the methods like:
+        // boolean fieldNameEquals(DetectedPhrase other) { ... }
+        // boolean fieldNameEquals(FieldType otherValue) { ... }
+
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        @SuppressWarnings("unchecked")
+        DetectedPhrase that = (DetectedPhrase) o;
+        //noinspection PointlessBooleanExpression
+        return true
+                && mId == that.mId
+                && java.util.Objects.equals(mPhrase, that.mPhrase);
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public int hashCode() {
+        // You can override field hashCode logic by defining methods like:
+        // int fieldNameHashCode() { ... }
+
+        int _hash = 1;
+        _hash = 31 * _hash + mId;
+        _hash = 31 * _hash + java.util.Objects.hashCode(mPhrase);
+        return _hash;
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public void writeToParcel(@NonNull android.os.Parcel dest, int flags) {
+        // You can override field parcelling by defining methods like:
+        // void parcelFieldName(Parcel dest, int flags) { ... }
+
+        byte flg = 0;
+        if (mPhrase != null) flg |= 0x2;
+        dest.writeByte(flg);
+        dest.writeInt(mId);
+        if (mPhrase != null) dest.writeString(mPhrase);
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public int describeContents() { return 0; }
+
+    /** @hide */
+    @SuppressWarnings({"unchecked", "RedundantCast"})
+    @DataClass.Generated.Member
+    /* package-private */ DetectedPhrase(@NonNull android.os.Parcel in) {
+        // You can override field unparcelling by defining methods like:
+        // static FieldType unparcelFieldName(Parcel in) { ... }
+
+        byte flg = in.readByte();
+        int id = in.readInt();
+        String phrase = (flg & 0x2) == 0 ? null : in.readString();
+
+        this.mId = id;
+        this.mPhrase = phrase;
+
+        onConstructed();
+    }
+
+    @DataClass.Generated.Member
+    public static final @NonNull Parcelable.Creator<DetectedPhrase> CREATOR
+            = new Parcelable.Creator<DetectedPhrase>() {
+        @Override
+        public DetectedPhrase[] newArray(int size) {
+            return new DetectedPhrase[size];
+        }
+
+        @Override
+        public DetectedPhrase createFromParcel(@NonNull android.os.Parcel in) {
+            return new DetectedPhrase(in);
+        }
+    };
+
+    /**
+     * A builder for {@link DetectedPhrase}
+     */
+    @SuppressWarnings("WeakerAccess")
+    @DataClass.Generated.Member
+    public static final class Builder {
+
+        private int mId;
+        private @Nullable String mPhrase;
+
+        private long mBuilderFieldsSet = 0L;
+
+        public Builder() {
+        }
+
+        /**
+         * An ID representing the keyphrase that triggered the successful detection.
+         */
+        @DataClass.Generated.Member
+        public @NonNull Builder setId(int value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x1;
+            mId = value;
+            return this;
+        }
+
+        /**
+         * A string representing exactly what was heard and interpreted by the service leading to
+         * a successful detection.
+         *
+         * <p>Can be null if not set in {@link DetectedPhrase.Builder}
+         */
+        @DataClass.Generated.Member
+        public @NonNull Builder setPhrase(@NonNull String value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x2;
+            mPhrase = value;
+            return this;
+        }
+
+        /** Builds the instance. This builder should not be touched after calling this! */
+        public @NonNull DetectedPhrase build() {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x4; // Mark builder used
+
+            if ((mBuilderFieldsSet & 0x1) == 0) {
+                mId = 0;
+            }
+            if ((mBuilderFieldsSet & 0x2) == 0) {
+                mPhrase = null;
+            }
+            DetectedPhrase o = new DetectedPhrase(
+                    mId,
+                    mPhrase);
+            return o;
+        }
+
+        private void checkNotUsed() {
+            if ((mBuilderFieldsSet & 0x4) != 0) {
+                throw new IllegalStateException(
+                        "This Builder should not be reused. Use a new Builder instance instead");
+            }
+        }
+    }
+
+    @DataClass.Generated(
+            time = 1676870329959L,
+            codegenVersion = "1.0.23",
+            sourceFile = "frameworks/base/core/java/android/service/voice/DetectedPhrase.java",
+            inputSignatures = "private  int mId\nprivate @android.annotation.Nullable java.lang.String mPhrase\nstatic  int defaultHotwordPhraseId()\npublic  android.service.voice.DetectedPhrase.Builder buildUpon()\nprivate  void onConstructed()\nclass DetectedPhrase extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genConstructor=false, genBuilder=true, genEqualsHashCode=true, genHiddenConstDefs=true, genParcelable=true, genToString=true)")
+    @Deprecated
+    private void __metadata() {}
+
+
+    //@formatter:on
+    // End of generated code
+
+}
diff --git a/core/java/android/service/voice/HotwordDetectedResult.java b/core/java/android/service/voice/HotwordDetectedResult.java
index dee560b..dd3f99c 100644
--- a/core/java/android/service/voice/HotwordDetectedResult.java
+++ b/core/java/android/service/voice/HotwordDetectedResult.java
@@ -203,17 +203,23 @@
      * An ID representing the keyphrase that triggered the successful detection.
      *
      * <p>Only values between 0 and {@link #getMaxHotwordPhraseId()} (inclusive) are accepted.
+     *
+     * @deprecated Use {@link #getDetectedPhrase()} and
+     *     {@link DetectedPhrase#getId()}.
      */
-    private final int mHotwordPhraseId;
-    private static int defaultHotwordPhraseId() {
-        return 0;
+    @Deprecated
+    public int getHotwordPhraseId() {
+        return mDetectedPhrase.getId();
     }
 
     /**
      * Returns the maximum value of {@link #getHotwordPhraseId()}.
+     *
+     * @deprecated There is no maximum phrase ID enforced
      */
+    @Deprecated
     public static int getMaxHotwordPhraseId() {
-        return 63;
+        return Integer.MAX_VALUE;
     }
 
     /**
@@ -285,6 +291,10 @@
         return mMediaSyncEvent;
     }
 
+    @NonNull
+    private DetectedPhrase mDetectedPhrase =
+            new DetectedPhrase.Builder().build();
+
     /**
      * Returns how many bytes should be written into the Parcel
      *
@@ -302,6 +312,9 @@
     /**
      * Returns how many bits have been written into the HotwordDetectedResult.
      *
+     * <p>{@link #getAudioStreams()} and {@link #getDetectedPhrase()}
+     * are not counted here.
+     *
      * @hide
      */
     public static int getUsageSize(@NonNull HotwordDetectedResult hotwordDetectedResult) {
@@ -329,9 +342,6 @@
         if (hotwordDetectedResult.getPersonalizedScore() != defaultPersonalizedScore()) {
             totalBits += bitCount(HotwordDetectedResult.getMaxScore());
         }
-        if (hotwordDetectedResult.getHotwordPhraseId() != defaultHotwordPhraseId()) {
-            totalBits += bitCount(HotwordDetectedResult.getMaxHotwordPhraseId());
-        }
         PersistableBundle persistableBundle = hotwordDetectedResult.getExtras();
         if (!persistableBundle.isEmpty()) {
             totalBits += getParcelableSize(persistableBundle) * Byte.SIZE;
@@ -339,7 +349,7 @@
         return totalBits;
     }
 
-    private static int bitCount(long value) {
+    static int bitCount(long value) {
         int bits = 0;
         while (value > 0) {
             bits++;
@@ -352,8 +362,6 @@
         Preconditions.checkArgumentInRange(mScore, 0, getMaxScore(), "score");
         Preconditions.checkArgumentInRange(mPersonalizedScore, 0, getMaxScore(),
                 "personalizedScore");
-        Preconditions.checkArgumentInRange(mHotwordPhraseId, 0, getMaxHotwordPhraseId(),
-                "hotwordPhraseId");
         Preconditions.checkArgumentInRange((long) mHotwordDurationMillis, 0,
                 AudioRecord.getMaxSharedAudioHistoryMillis(), "hotwordDurationMillis");
         if (mHotwordOffsetMillis != HOTWORD_OFFSET_UNSET) {
@@ -448,10 +456,25 @@
             Objects.requireNonNull(value, "value should not be null");
             final Builder builder = (Builder) this;
             // If the code gen flag in build() is changed, we must update the flag e.g. 0x200 here.
-            builder.mBuilderFieldsSet |= 0x200;
+            builder.mBuilderFieldsSet |= 0x100;
             builder.mAudioStreams = List.copyOf(value);
             return builder;
         }
+
+        /**
+         * An ID representing the keyphrase that triggered the successful detection.
+         *
+         * <p>Only values between 0 and {@link #getMaxHotwordPhraseId()} (inclusive) are accepted.
+         *
+         * @deprecated Use {@link HotwordDetectedResult.Builder#setDetectedPhrase(DetectedPhrase)}
+         *      and {@link DetectedPhrase.Builder#setId(int)}
+         */
+        @Deprecated
+        public @NonNull Builder setHotwordPhraseId(int value) {
+            final Builder builder = (Builder) this;
+            builder.setDetectedPhrase(new DetectedPhrase.Builder().setId(value).build());
+            return builder;
+        }
     }
 
     /**
@@ -468,9 +491,9 @@
             .setHotwordDetectionPersonalized(mHotwordDetectionPersonalized)
             .setScore(mScore)
             .setPersonalizedScore(mPersonalizedScore)
-            .setHotwordPhraseId(mHotwordPhraseId)
             .setAudioStreams(mAudioStreams)
-            .setExtras(mExtras);
+            .setExtras(mExtras)
+            .setDetectedPhrase(mDetectedPhrase);
     }
 
 
@@ -579,9 +602,9 @@
             boolean hotwordDetectionPersonalized,
             int score,
             int personalizedScore,
-            int hotwordPhraseId,
             @NonNull List<HotwordAudioStream> audioStreams,
-            @NonNull PersistableBundle extras) {
+            @NonNull PersistableBundle extras,
+            @NonNull DetectedPhrase detectedPhrase) {
         this.mConfidenceLevel = confidenceLevel;
         com.android.internal.util.AnnotationValidations.validate(
                 HotwordConfidenceLevelValue.class, null, mConfidenceLevel);
@@ -592,13 +615,15 @@
         this.mHotwordDetectionPersonalized = hotwordDetectionPersonalized;
         this.mScore = score;
         this.mPersonalizedScore = personalizedScore;
-        this.mHotwordPhraseId = hotwordPhraseId;
         this.mAudioStreams = audioStreams;
         com.android.internal.util.AnnotationValidations.validate(
                 NonNull.class, null, mAudioStreams);
         this.mExtras = extras;
         com.android.internal.util.AnnotationValidations.validate(
                 NonNull.class, null, mExtras);
+        this.mDetectedPhrase = detectedPhrase;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mDetectedPhrase);
 
         onConstructed();
     }
@@ -673,16 +698,6 @@
     }
 
     /**
-     * An ID representing the keyphrase that triggered the successful detection.
-     *
-     * <p>Only values between 0 and {@link #getMaxHotwordPhraseId()} (inclusive) are accepted.
-     */
-    @DataClass.Generated.Member
-    public int getHotwordPhraseId() {
-        return mHotwordPhraseId;
-    }
-
-    /**
      * App-specific extras to support trigger.
      *
      * <p>The size of this bundle will be limited to {@link #getMaxBundleSize}. Results will larger
@@ -712,6 +727,11 @@
         return mExtras;
     }
 
+    @DataClass.Generated.Member
+    public @NonNull DetectedPhrase getDetectedPhrase() {
+        return mDetectedPhrase;
+    }
+
     @Override
     @DataClass.Generated.Member
     public String toString() {
@@ -727,9 +747,9 @@
                 "hotwordDetectionPersonalized = " + mHotwordDetectionPersonalized + ", " +
                 "score = " + mScore + ", " +
                 "personalizedScore = " + mPersonalizedScore + ", " +
-                "hotwordPhraseId = " + mHotwordPhraseId + ", " +
                 "audioStreams = " + mAudioStreams + ", " +
-                "extras = " + mExtras +
+                "extras = " + mExtras + ", " +
+                "detectedPhrase = " + mDetectedPhrase +
         " }";
     }
 
@@ -754,9 +774,9 @@
                 && mHotwordDetectionPersonalized == that.mHotwordDetectionPersonalized
                 && mScore == that.mScore
                 && mPersonalizedScore == that.mPersonalizedScore
-                && mHotwordPhraseId == that.mHotwordPhraseId
                 && Objects.equals(mAudioStreams, that.mAudioStreams)
-                && Objects.equals(mExtras, that.mExtras);
+                && Objects.equals(mExtras, that.mExtras)
+                && Objects.equals(mDetectedPhrase, that.mDetectedPhrase);
     }
 
     @Override
@@ -774,9 +794,9 @@
         _hash = 31 * _hash + Boolean.hashCode(mHotwordDetectionPersonalized);
         _hash = 31 * _hash + mScore;
         _hash = 31 * _hash + mPersonalizedScore;
-        _hash = 31 * _hash + mHotwordPhraseId;
         _hash = 31 * _hash + Objects.hashCode(mAudioStreams);
         _hash = 31 * _hash + Objects.hashCode(mExtras);
+        _hash = 31 * _hash + Objects.hashCode(mDetectedPhrase);
         return _hash;
     }
 
@@ -797,9 +817,9 @@
         dest.writeInt(mAudioChannel);
         dest.writeInt(mScore);
         dest.writeInt(mPersonalizedScore);
-        dest.writeInt(mHotwordPhraseId);
         dest.writeParcelableList(mAudioStreams, flags);
         dest.writeTypedObject(mExtras, flags);
+        dest.writeTypedObject(mDetectedPhrase, flags);
     }
 
     @Override
@@ -822,10 +842,10 @@
         int audioChannel = in.readInt();
         int score = in.readInt();
         int personalizedScore = in.readInt();
-        int hotwordPhraseId = in.readInt();
         List<HotwordAudioStream> audioStreams = new ArrayList<>();
         in.readParcelableList(audioStreams, HotwordAudioStream.class.getClassLoader());
         PersistableBundle extras = (PersistableBundle) in.readTypedObject(PersistableBundle.CREATOR);
+        DetectedPhrase detectedPhrase = (DetectedPhrase) in.readTypedObject(DetectedPhrase.CREATOR);
 
         this.mConfidenceLevel = confidenceLevel;
         com.android.internal.util.AnnotationValidations.validate(
@@ -837,13 +857,15 @@
         this.mHotwordDetectionPersonalized = hotwordDetectionPersonalized;
         this.mScore = score;
         this.mPersonalizedScore = personalizedScore;
-        this.mHotwordPhraseId = hotwordPhraseId;
         this.mAudioStreams = audioStreams;
         com.android.internal.util.AnnotationValidations.validate(
                 NonNull.class, null, mAudioStreams);
         this.mExtras = extras;
         com.android.internal.util.AnnotationValidations.validate(
                 NonNull.class, null, mExtras);
+        this.mDetectedPhrase = detectedPhrase;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mDetectedPhrase);
 
         onConstructed();
     }
@@ -877,9 +899,9 @@
         private boolean mHotwordDetectionPersonalized;
         private int mScore;
         private int mPersonalizedScore;
-        private int mHotwordPhraseId;
         private @NonNull List<HotwordAudioStream> mAudioStreams;
         private @NonNull PersistableBundle mExtras;
+        private @NonNull DetectedPhrase mDetectedPhrase;
 
         private long mBuilderFieldsSet = 0L;
 
@@ -990,19 +1012,6 @@
         }
 
         /**
-         * An ID representing the keyphrase that triggered the successful detection.
-         *
-         * <p>Only values between 0 and {@link #getMaxHotwordPhraseId()} (inclusive) are accepted.
-         */
-        @DataClass.Generated.Member
-        public @NonNull Builder setHotwordPhraseId(int value) {
-            checkNotUsed();
-            mBuilderFieldsSet |= 0x100;
-            mHotwordPhraseId = value;
-            return this;
-        }
-
-        /**
          * App-specific extras to support trigger.
          *
          * <p>The size of this bundle will be limited to {@link #getMaxBundleSize}. Results will larger
@@ -1030,11 +1039,19 @@
         @DataClass.Generated.Member
         public @NonNull Builder setExtras(@NonNull PersistableBundle value) {
             checkNotUsed();
-            mBuilderFieldsSet |= 0x400;
+            mBuilderFieldsSet |= 0x200;
             mExtras = value;
             return this;
         }
 
+        @DataClass.Generated.Member
+        public @NonNull Builder setDetectedPhrase(@NonNull DetectedPhrase value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x400;
+            mDetectedPhrase = value;
+            return this;
+        }
+
         /** Builds the instance. This builder should not be touched after calling this! */
         public @NonNull HotwordDetectedResult build() {
             checkNotUsed();
@@ -1065,14 +1082,14 @@
                 mPersonalizedScore = defaultPersonalizedScore();
             }
             if ((mBuilderFieldsSet & 0x100) == 0) {
-                mHotwordPhraseId = defaultHotwordPhraseId();
-            }
-            if ((mBuilderFieldsSet & 0x200) == 0) {
                 mAudioStreams = defaultAudioStreams();
             }
-            if ((mBuilderFieldsSet & 0x400) == 0) {
+            if ((mBuilderFieldsSet & 0x200) == 0) {
                 mExtras = defaultExtras();
             }
+            if ((mBuilderFieldsSet & 0x400) == 0) {
+                mDetectedPhrase = new DetectedPhrase.Builder().build();
+            }
             HotwordDetectedResult o = new HotwordDetectedResult(
                     mConfidenceLevel,
                     mMediaSyncEvent,
@@ -1082,9 +1099,9 @@
                     mHotwordDetectionPersonalized,
                     mScore,
                     mPersonalizedScore,
-                    mHotwordPhraseId,
                     mAudioStreams,
-                    mExtras);
+                    mExtras,
+                    mDetectedPhrase);
             return o;
         }
 
@@ -1097,10 +1114,10 @@
     }
 
     @DataClass.Generated(
-            time = 1668385264834L,
+            time = 1676870324215L,
             codegenVersion = "1.0.23",
             sourceFile = "frameworks/base/core/java/android/service/voice/HotwordDetectedResult.java",
-            inputSignatures = "public static final  int CONFIDENCE_LEVEL_NONE\npublic static final  int CONFIDENCE_LEVEL_LOW\npublic static final  int CONFIDENCE_LEVEL_LOW_MEDIUM\npublic static final  int CONFIDENCE_LEVEL_MEDIUM\npublic static final  int CONFIDENCE_LEVEL_MEDIUM_HIGH\npublic static final  int CONFIDENCE_LEVEL_HIGH\npublic static final  int CONFIDENCE_LEVEL_VERY_HIGH\npublic static final  int HOTWORD_OFFSET_UNSET\npublic static final  int AUDIO_CHANNEL_UNSET\nprivate static final  int LIMIT_HOTWORD_OFFSET_MAX_VALUE\nprivate static final  int LIMIT_AUDIO_CHANNEL_MAX_VALUE\nprivate static final  java.lang.String EXTRA_PROXIMITY\npublic static final  int PROXIMITY_UNKNOWN\npublic static final  int PROXIMITY_NEAR\npublic static final  int PROXIMITY_FAR\nprivate final @android.service.voice.HotwordDetectedResult.HotwordConfidenceLevelValue int mConfidenceLevel\nprivate @android.annotation.Nullable android.media.MediaSyncEvent mMediaSyncEvent\nprivate  int mHotwordOffsetMillis\nprivate  int mHotwordDurationMillis\nprivate  int mAudioChannel\nprivate  boolean mHotwordDetectionPersonalized\nprivate final  int mScore\nprivate final  int mPersonalizedScore\nprivate final  int mHotwordPhraseId\nprivate final @android.annotation.NonNull java.util.List<android.service.voice.HotwordAudioStream> mAudioStreams\nprivate final @android.annotation.NonNull android.os.PersistableBundle mExtras\nprivate static  int sMaxBundleSize\nprivate static  int defaultConfidenceLevel()\nprivate static  int defaultScore()\nprivate static  int defaultPersonalizedScore()\npublic static  int getMaxScore()\nprivate static  int defaultHotwordPhraseId()\npublic static  int getMaxHotwordPhraseId()\nprivate static  java.util.List<android.service.voice.HotwordAudioStream> defaultAudioStreams()\nprivate static  android.os.PersistableBundle defaultExtras()\npublic static  int getMaxBundleSize()\npublic @android.annotation.Nullable android.media.MediaSyncEvent getMediaSyncEvent()\npublic static  int getParcelableSize(android.os.Parcelable)\npublic static  int getUsageSize(android.service.voice.HotwordDetectedResult)\nprivate static  int bitCount(long)\nprivate  void onConstructed()\npublic @android.annotation.NonNull java.util.List<android.service.voice.HotwordAudioStream> getAudioStreams()\npublic  void setProximity(double)\npublic @android.service.voice.HotwordDetectedResult.ProximityValue int getProximity()\nprivate @android.service.voice.HotwordDetectedResult.ProximityValue int convertToProximityLevel(double)\npublic  android.service.voice.HotwordDetectedResult.Builder buildUpon()\nclass HotwordDetectedResult extends java.lang.Object implements [android.os.Parcelable]\npublic @android.annotation.NonNull android.service.voice.HotwordDetectedResult.Builder setAudioStreams(java.util.List<android.service.voice.HotwordAudioStream>)\nclass BaseBuilder extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genConstructor=false, genBuilder=true, genEqualsHashCode=true, genHiddenConstDefs=true, genParcelable=true, genToString=true)\npublic @android.annotation.NonNull android.service.voice.HotwordDetectedResult.Builder setAudioStreams(java.util.List<android.service.voice.HotwordAudioStream>)\nclass BaseBuilder extends java.lang.Object implements []")
+            inputSignatures = "public static final  int CONFIDENCE_LEVEL_NONE\npublic static final  int CONFIDENCE_LEVEL_LOW\npublic static final  int CONFIDENCE_LEVEL_LOW_MEDIUM\npublic static final  int CONFIDENCE_LEVEL_MEDIUM\npublic static final  int CONFIDENCE_LEVEL_MEDIUM_HIGH\npublic static final  int CONFIDENCE_LEVEL_HIGH\npublic static final  int CONFIDENCE_LEVEL_VERY_HIGH\npublic static final  int HOTWORD_OFFSET_UNSET\npublic static final  int AUDIO_CHANNEL_UNSET\nprivate static final  int LIMIT_HOTWORD_OFFSET_MAX_VALUE\nprivate static final  int LIMIT_AUDIO_CHANNEL_MAX_VALUE\nprivate static final  java.lang.String EXTRA_PROXIMITY\npublic static final  int PROXIMITY_UNKNOWN\npublic static final  int PROXIMITY_NEAR\npublic static final  int PROXIMITY_FAR\nprivate final @android.service.voice.HotwordDetectedResult.HotwordConfidenceLevelValue int mConfidenceLevel\nprivate @android.annotation.Nullable android.media.MediaSyncEvent mMediaSyncEvent\nprivate  int mHotwordOffsetMillis\nprivate  int mHotwordDurationMillis\nprivate  int mAudioChannel\nprivate  boolean mHotwordDetectionPersonalized\nprivate final  int mScore\nprivate final  int mPersonalizedScore\nprivate final @android.annotation.NonNull java.util.List<android.service.voice.HotwordAudioStream> mAudioStreams\nprivate final @android.annotation.NonNull android.os.PersistableBundle mExtras\nprivate static  int sMaxBundleSize\nprivate @android.annotation.NonNull android.service.voice.DetectedPhrase mDetectedPhrase\nprivate static  int defaultConfidenceLevel()\nprivate static  int defaultScore()\nprivate static  int defaultPersonalizedScore()\npublic static  int getMaxScore()\npublic @java.lang.Deprecated int getHotwordPhraseId()\npublic static @java.lang.Deprecated int getMaxHotwordPhraseId()\nprivate static  java.util.List<android.service.voice.HotwordAudioStream> defaultAudioStreams()\nprivate static  android.os.PersistableBundle defaultExtras()\npublic static  int getMaxBundleSize()\npublic @android.annotation.Nullable android.media.MediaSyncEvent getMediaSyncEvent()\npublic static  int getParcelableSize(android.os.Parcelable)\npublic static  int getUsageSize(android.service.voice.HotwordDetectedResult)\nstatic  int bitCount(long)\nprivate  void onConstructed()\npublic @android.annotation.NonNull java.util.List<android.service.voice.HotwordAudioStream> getAudioStreams()\npublic  void setProximity(double)\npublic @android.service.voice.HotwordDetectedResult.ProximityValue int getProximity()\nprivate @android.service.voice.HotwordDetectedResult.ProximityValue int convertToProximityLevel(double)\npublic  android.service.voice.HotwordDetectedResult.Builder buildUpon()\nclass HotwordDetectedResult extends java.lang.Object implements [android.os.Parcelable]\npublic @android.annotation.NonNull android.service.voice.HotwordDetectedResult.Builder setAudioStreams(java.util.List<android.service.voice.HotwordAudioStream>)\npublic @java.lang.Deprecated @android.annotation.NonNull android.service.voice.HotwordDetectedResult.Builder setHotwordPhraseId(int)\nclass BaseBuilder extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genConstructor=false, genBuilder=true, genEqualsHashCode=true, genHiddenConstDefs=true, genParcelable=true, genToString=true)\npublic @android.annotation.NonNull android.service.voice.HotwordDetectedResult.Builder setAudioStreams(java.util.List<android.service.voice.HotwordAudioStream>)\npublic @java.lang.Deprecated @android.annotation.NonNull android.service.voice.HotwordDetectedResult.Builder setHotwordPhraseId(int)\nclass BaseBuilder extends java.lang.Object implements []")
     @Deprecated
     private void __metadata() {}
 
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index eb36a70..a746dc6 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -220,9 +220,9 @@
         DEFAULT_FLAGS.put(SETTINGS_APP_ALLOW_DARK_THEME_ACTIVATION_AT_BEDTIME, "true");
         DEFAULT_FLAGS.put(SETTINGS_NEED_CONNECTED_BLE_DEVICE_FOR_BROADCAST, "true");
         DEFAULT_FLAGS.put(SETTINGS_AUTO_TEXT_WRAPPING, "false");
-        DEFAULT_FLAGS.put(SETTINGS_NEW_KEYBOARD_UI, "true");
-        DEFAULT_FLAGS.put(SETTINGS_NEW_KEYBOARD_MODIFIER_KEY, "true");
-        DEFAULT_FLAGS.put(SETTINGS_NEW_KEYBOARD_TRACKPAD, "true");
+        DEFAULT_FLAGS.put(SETTINGS_NEW_KEYBOARD_UI, "false");
+        DEFAULT_FLAGS.put(SETTINGS_NEW_KEYBOARD_MODIFIER_KEY, "false");
+        DEFAULT_FLAGS.put(SETTINGS_NEW_KEYBOARD_TRACKPAD, "false");
         DEFAULT_FLAGS.put(SETTINGS_NEW_KEYBOARD_TRACKPAD_GESTURE, "false");
         DEFAULT_FLAGS.put(SETTINGS_ENABLE_SPA, "true");
         DEFAULT_FLAGS.put(SETTINGS_ENABLE_SPA_PHASE2, "false");
diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
index 1a5613e..66442bb 100644
--- a/core/java/android/view/KeyEvent.java
+++ b/core/java/android/view/KeyEvent.java
@@ -1352,6 +1352,7 @@
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private int mSource;
     private int mDisplayId = INVALID_DISPLAY;
+    // NOTE: mHmac is private and not used in this class, but it's used on native side / parcel.
     private @Nullable byte[] mHmac;
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
     private int mMetaState;
@@ -1377,7 +1378,7 @@
      */
     private long mEventTime;
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    private String mCharacters;
+    private @Nullable String mCharacters;
 
     public interface Callback {
         /**
@@ -1441,7 +1442,11 @@
     private static native int nativeKeyCodeFromString(String keyCode);
     private static native int nativeNextId();
 
-    private KeyEvent() {}
+    private KeyEvent() {
+        this(/* downTime= */ 0, /* eventTime= */ 0, /* action= */ 0, /* code= */0, /* repeat= */ 0,
+                /* metaState= */ 0, /* deviceId= */ 0, /* scancode= */ 0, /* flags= */ 0,
+                /* source= */ 0);
+    }
 
     /**
      * Create a new key event.
@@ -1451,11 +1456,9 @@
      * @param code The key code.
      */
     public KeyEvent(int action, int code) {
-        mId = nativeNextId();
-        mAction = action;
-        mKeyCode = code;
-        mRepeatCount = 0;
-        mDeviceId = KeyCharacterMap.VIRTUAL_KEYBOARD;
+        this(/* downTime= */ 0, /* eventTime= */ 0, action, code, /* repeat= */ 0,
+                /* metaState= */ 0, /* deviceId= */ KeyCharacterMap.VIRTUAL_KEYBOARD,
+                /* scancode= */ 0, /* flags= */ 0, /* source= */ 0);
     }
 
     /**
@@ -1473,13 +1476,9 @@
      */
     public KeyEvent(long downTime, long eventTime, int action,
                     int code, int repeat) {
-        mId = nativeNextId();
-        mDownTime = TimeUnit.NANOSECONDS.convert(downTime, TimeUnit.MILLISECONDS);
-        mEventTime = TimeUnit.NANOSECONDS.convert(eventTime, TimeUnit.MILLISECONDS);
-        mAction = action;
-        mKeyCode = code;
-        mRepeatCount = repeat;
-        mDeviceId = KeyCharacterMap.VIRTUAL_KEYBOARD;
+        this(downTime, eventTime, action, code, repeat, /* metaState= */ 0,
+                KeyCharacterMap.VIRTUAL_KEYBOARD, /* scancode= */ 0, /* flags= */ 0,
+                /* source= */ 0);
     }
 
     /**
@@ -1498,14 +1497,8 @@
      */
     public KeyEvent(long downTime, long eventTime, int action,
                     int code, int repeat, int metaState) {
-        mId = nativeNextId();
-        mDownTime = TimeUnit.NANOSECONDS.convert(downTime, TimeUnit.MILLISECONDS);
-        mEventTime = TimeUnit.NANOSECONDS.convert(eventTime, TimeUnit.MILLISECONDS);
-        mAction = action;
-        mKeyCode = code;
-        mRepeatCount = repeat;
-        mMetaState = metaState;
-        mDeviceId = KeyCharacterMap.VIRTUAL_KEYBOARD;
+        this(downTime, eventTime, action, code, repeat, metaState, KeyCharacterMap.VIRTUAL_KEYBOARD,
+                /* scancode= */ 0, /* flags= */ 0, /* source= */ 0);
     }
 
     /**
@@ -1527,15 +1520,8 @@
     public KeyEvent(long downTime, long eventTime, int action,
                     int code, int repeat, int metaState,
                     int deviceId, int scancode) {
-        mId = nativeNextId();
-        mDownTime = TimeUnit.NANOSECONDS.convert(downTime, TimeUnit.MILLISECONDS);
-        mEventTime = TimeUnit.NANOSECONDS.convert(eventTime, TimeUnit.MILLISECONDS);
-        mAction = action;
-        mKeyCode = code;
-        mRepeatCount = repeat;
-        mMetaState = metaState;
-        mDeviceId = deviceId;
-        mScanCode = scancode;
+        this(downTime, eventTime, action, code, repeat, metaState, deviceId, scancode,
+                /* flags= */ 0, /* source= */ 0);
     }
 
     /**
@@ -1558,16 +1544,8 @@
     public KeyEvent(long downTime, long eventTime, int action,
                     int code, int repeat, int metaState,
                     int deviceId, int scancode, int flags) {
-        mId = nativeNextId();
-        mDownTime = TimeUnit.NANOSECONDS.convert(downTime, TimeUnit.MILLISECONDS);
-        mEventTime = TimeUnit.NANOSECONDS.convert(eventTime, TimeUnit.MILLISECONDS);
-        mAction = action;
-        mKeyCode = code;
-        mRepeatCount = repeat;
-        mMetaState = metaState;
-        mDeviceId = deviceId;
-        mScanCode = scancode;
-        mFlags = flags;
+        this(downTime, eventTime, action, code, repeat, metaState, deviceId, scancode, flags,
+                /* source= */ 0);
     }
 
     /**
@@ -1591,6 +1569,8 @@
     public KeyEvent(long downTime, long eventTime, int action,
                     int code, int repeat, int metaState,
                     int deviceId, int scancode, int flags, int source) {
+        // NOTE: this is the canonical constructor, every other constructor that takes KeyEvent
+        // attributes should call it
         mId = nativeNextId();
         mDownTime = TimeUnit.NANOSECONDS.convert(downTime, TimeUnit.MILLISECONDS);
         mEventTime = TimeUnit.NANOSECONDS.convert(eventTime, TimeUnit.MILLISECONDS);
@@ -1617,36 +1597,18 @@
      * @param flags The flags for this key event
      */
     public KeyEvent(long time, String characters, int deviceId, int flags) {
-        mId = nativeNextId();
-        mDownTime = TimeUnit.NANOSECONDS.convert(time, TimeUnit.MILLISECONDS);
-        mEventTime = TimeUnit.NANOSECONDS.convert(time, TimeUnit.MILLISECONDS);
-        mCharacters = characters;
-        mAction = ACTION_MULTIPLE;
-        mKeyCode = KEYCODE_UNKNOWN;
-        mRepeatCount = 0;
-        mDeviceId = deviceId;
-        mFlags = flags;
-        mSource = InputDevice.SOURCE_KEYBOARD;
+        this(/* downTime= */ time, /* eventTime= */ time, ACTION_MULTIPLE, KEYCODE_UNKNOWN,
+                /* repeat= */ 0, /* metaState= */ 0, deviceId, /* scancode= */ 0, flags,
+                /* source= */ InputDevice.SOURCE_KEYBOARD);
     }
 
     /**
      * Make an exact copy of an existing key event.
      */
     public KeyEvent(KeyEvent origEvent) {
-        mId = origEvent.mId;
-        mDownTime = origEvent.mDownTime;
-        mEventTime = origEvent.mEventTime;
-        mAction = origEvent.mAction;
-        mKeyCode = origEvent.mKeyCode;
-        mRepeatCount = origEvent.mRepeatCount;
-        mMetaState = origEvent.mMetaState;
-        mDeviceId = origEvent.mDeviceId;
-        mSource = origEvent.mSource;
-        mDisplayId = origEvent.mDisplayId;
-        mHmac = origEvent.mHmac == null ? null : origEvent.mHmac.clone();
-        mScanCode = origEvent.mScanCode;
-        mFlags = origEvent.mFlags;
-        mCharacters = origEvent.mCharacters;
+        this(origEvent, origEvent.mId, origEvent.mEventTime, origEvent.mAction,
+                origEvent.mRepeatCount, origEvent.mHmac == null ? null : origEvent.mHmac.clone(),
+                origEvent.mCharacters);
     }
 
     /**
@@ -1662,20 +1624,30 @@
      */
     @Deprecated
     public KeyEvent(KeyEvent origEvent, long eventTime, int newRepeat) {
-        mId = nativeNextId();  // Not an exact copy so assign a new ID.
+        // Not an exact copy so assign a new ID.
+        // Don't copy HMAC, it will be invalid because eventTime is changing
+        this(origEvent, nativeNextId(),
+                TimeUnit.NANOSECONDS.convert(eventTime, TimeUnit.MILLISECONDS), origEvent.mAction,
+                newRepeat, /* hmac= */ null, origEvent.mCharacters);
+    }
+
+    // This is the canonical constructor that should be called for constructors that take a KeyEvent
+    private KeyEvent(KeyEvent origEvent, int id, long eventTime, int action, int newRepeat,
+            @Nullable byte[] hmac, @Nullable String characters) {
+        mId = id;
         mDownTime = origEvent.mDownTime;
-        mEventTime = TimeUnit.NANOSECONDS.convert(eventTime, TimeUnit.MILLISECONDS);
-        mAction = origEvent.mAction;
+        mEventTime = eventTime;
+        mAction = action;
         mKeyCode = origEvent.mKeyCode;
         mRepeatCount = newRepeat;
         mMetaState = origEvent.mMetaState;
         mDeviceId = origEvent.mDeviceId;
         mSource = origEvent.mSource;
         mDisplayId = origEvent.mDisplayId;
-        mHmac = null; // Don't copy HMAC, it will be invalid because eventTime is changing
+        mHmac = hmac;
         mScanCode = origEvent.mScanCode;
         mFlags = origEvent.mFlags;
-        mCharacters = origEvent.mCharacters;
+        mCharacters = characters;
     }
 
     private static KeyEvent obtain() {
@@ -1857,21 +1829,11 @@
      * @param action The new action code of the event.
      */
     private KeyEvent(KeyEvent origEvent, int action) {
-        mId = nativeNextId();  // Not an exact copy so assign a new ID.
-        mDownTime = origEvent.mDownTime;
-        mEventTime = origEvent.mEventTime;
-        mAction = action;
-        mKeyCode = origEvent.mKeyCode;
-        mRepeatCount = origEvent.mRepeatCount;
-        mMetaState = origEvent.mMetaState;
-        mDeviceId = origEvent.mDeviceId;
-        mSource = origEvent.mSource;
-        mDisplayId = origEvent.mDisplayId;
-        mHmac = null; // Don't copy the hmac, it will be invalid since action is changing
-        mScanCode = origEvent.mScanCode;
-        mFlags = origEvent.mFlags;
-        // Don't copy mCharacters, since one way or the other we'll lose it
-        // when changing the action.
+        // Not an exact copy so assign a new ID
+        // Don't copy the hmac, it will be invalid since action is changing
+        // Don't copy mCharacters, since one way or the other we'll lose it when changing action.
+        this(origEvent, nativeNextId(), origEvent.mEventTime, action, origEvent.mRepeatCount,
+                /* hmac= */ null, /* characters= */ null);
     }
 
     /**
@@ -3219,6 +3181,8 @@
     }
 
     private KeyEvent(Parcel in) {
+        // NOTE: ideally this constructor should call the canonical one, but that would require
+        // changing the order the fields are written to the parcel, which could break native code
         mId = in.readInt();
         mDeviceId = in.readInt();
         mSource = in.readInt();
diff --git a/core/java/android/window/IWindowOrganizerController.aidl b/core/java/android/window/IWindowOrganizerController.aidl
index 57e0ce8..534c9de 100644
--- a/core/java/android/window/IWindowOrganizerController.aidl
+++ b/core/java/android/window/IWindowOrganizerController.aidl
@@ -63,7 +63,7 @@
      * @param transitionToken A token associated with the transition to start.
      * @param t Operations that are part of the transition.
      */
-    oneway void startTransition(IBinder transitionToken, in @nullable WindowContainerTransaction t);
+    void startTransition(IBinder transitionToken, in @nullable WindowContainerTransaction t);
 
     /**
      * Starts a legacy transition.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java
index 3ade1ed..bb6e391 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java
@@ -369,7 +369,9 @@
 
         // Start animating the drop UI out with the drag surface
         hide(event, dropCompleteCallback);
-        hideDragSurface(dragSurface);
+        if (handledDrop) {
+            hideDragSurface(dragSurface);
+        }
         return handledDrop;
     }
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
index 0826fe2..0a67477 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
@@ -709,15 +709,22 @@
         for (int iA = activeIdx + 1; iA < mActiveTransitions.size(); ++iA) {
             final ActiveTransition toMerge = mActiveTransitions.get(iA);
             if (!toMerge.mMerged) break;
-            // aborted transitions have no start/finish transactions
-            if (mActiveTransitions.get(iA).mStartT == null) break;
-            if (fullFinish == null) {
-                fullFinish = new SurfaceControl.Transaction();
-            }
             // Include start. It will be a no-op if it was already applied. Otherwise, we need it
             // to maintain consistent state.
-            fullFinish.merge(mActiveTransitions.get(iA).mStartT);
-            fullFinish.merge(mActiveTransitions.get(iA).mFinishT);
+            if (toMerge.mStartT != null) {
+                if (fullFinish == null) {
+                    fullFinish = toMerge.mStartT;
+                } else {
+                    fullFinish.merge(toMerge.mStartT);
+                }
+            }
+            if (toMerge.mFinishT != null) {
+                if (fullFinish == null) {
+                    fullFinish = toMerge.mFinishT;
+                } else {
+                    fullFinish.merge(toMerge.mFinishT);
+                }
+            }
         }
         if (fullFinish != null) {
             fullFinish.apply();
diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleShader.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleShader.kt
index aad2d70..0b842ad 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleShader.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleShader.kt
@@ -431,8 +431,9 @@
                             "[setSizeAtProgresses] before playing the animation."
                     )
                 }
-                // If there's no size is set, we set everything to 0.
+                // If there's no size is set, we set everything to 0 and return early.
                 setSizeAtProgresses(initialSize)
+                return currentSizeIndex
             }
 
             var candidate = sizes[currentSizeIndex]
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java
index e1e8063..90f44a7 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java
@@ -36,7 +36,6 @@
 import android.annotation.Nullable;
 import android.annotation.SuppressLint;
 import android.app.ActivityManager;
-import android.app.TaskInfo;
 import android.app.WindowConfiguration;
 import android.graphics.Rect;
 import android.util.ArrayMap;
@@ -48,7 +47,7 @@
 import android.window.TransitionInfo.Change;
 
 import java.util.ArrayList;
-import java.util.function.BiPredicate;
+import java.util.function.Predicate;
 
 /**
  * Some utility methods for creating {@link RemoteAnimationTarget} instances.
@@ -145,6 +144,18 @@
     public static RemoteAnimationTarget newTarget(TransitionInfo.Change change, int order,
             TransitionInfo info, SurfaceControl.Transaction t,
             @Nullable ArrayMap<SurfaceControl, SurfaceControl> leashMap) {
+        final SurfaceControl leash = createLeash(info, change, order, t);
+        if (leashMap != null) {
+            leashMap.put(change.getLeash(), leash);
+        }
+        return newTarget(change, order, leash);
+    }
+
+    /**
+     * Creates a new RemoteAnimationTarget from the provided change and leash
+     */
+    public static RemoteAnimationTarget newTarget(TransitionInfo.Change change, int order,
+            SurfaceControl leash) {
         int taskId;
         boolean isNotInRecents;
         ActivityManager.RunningTaskInfo taskInfo;
@@ -169,7 +180,7 @@
                 newModeToLegacyMode(change.getMode()),
                 // TODO: once we can properly sync transactions across process,
                 // then get rid of this leash.
-                createLeash(info, change, order, t),
+                leash,
                 (change.getFlags() & TransitionInfo.FLAG_TRANSLUCENT) != 0,
                 null,
                 // TODO(shell-transitions): we need to send content insets? evaluate how its used.
@@ -190,9 +201,6 @@
         target.setWillShowImeOnTarget(
                 (change.getFlags() & TransitionInfo.FLAG_WILL_IME_SHOWN) != 0);
         target.setRotationChange(change.getEndRotation() - change.getStartRotation());
-        if (leashMap != null) {
-            leashMap.put(change.getLeash(), target.leash);
-        }
         return target;
     }
 
@@ -204,18 +212,7 @@
      */
     public static RemoteAnimationTarget[] wrapApps(TransitionInfo info,
             SurfaceControl.Transaction t, ArrayMap<SurfaceControl, SurfaceControl> leashMap) {
-        SparseBooleanArray childTaskTargets = new SparseBooleanArray();
-        return wrap(info, t, leashMap, (change, taskInfo) -> {
-            // Children always come before parent since changes are in top-to-bottom z-order.
-            if ((taskInfo == null) || childTaskTargets.get(taskInfo.taskId)) {
-                // has children, so not a leaf. Skip.
-                return false;
-            }
-            if (taskInfo.hasParentTask()) {
-                childTaskTargets.put(taskInfo.parentTaskId, true);
-            }
-            return true;
-        });
+        return wrap(info, t, leashMap, new LeafTaskFilter());
     }
 
     /**
@@ -228,21 +225,56 @@
      */
     public static RemoteAnimationTarget[] wrapNonApps(TransitionInfo info, boolean wallpapers,
             SurfaceControl.Transaction t, ArrayMap<SurfaceControl, SurfaceControl> leashMap) {
-        return wrap(info, t, leashMap, (change, taskInfo) -> (taskInfo == null)
-                && wallpapers == change.hasFlags(FLAG_IS_WALLPAPER)
-                && !change.hasFlags(FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY));
+        return wrap(info, t, leashMap, (change) ->
+                (wallpapers ? isWallpaper(change) : isNonApp(change)));
     }
 
     private static RemoteAnimationTarget[] wrap(TransitionInfo info,
             SurfaceControl.Transaction t, ArrayMap<SurfaceControl, SurfaceControl> leashMap,
-            BiPredicate<Change, TaskInfo> filter) {
+            Predicate<Change> filter) {
         final ArrayList<RemoteAnimationTarget> out = new ArrayList<>();
         for (int i = 0; i < info.getChanges().size(); i++) {
             TransitionInfo.Change change = info.getChanges().get(i);
-            if (filter.test(change, change.getTaskInfo())) {
+            if (filter.test(change)) {
                 out.add(newTarget(change, info.getChanges().size() - i, info, t, leashMap));
             }
         }
         return out.toArray(new RemoteAnimationTarget[out.size()]);
     }
+
+    /** Returns `true` if `change` is a wallpaper. */
+    public static boolean isWallpaper(Change change) {
+        return (change.getTaskInfo() == null)
+                && change.hasFlags(FLAG_IS_WALLPAPER)
+                && !change.hasFlags(FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY);
+    }
+
+    /** Returns `true` if `change` is not an app window or wallpaper. */
+    public static boolean isNonApp(Change change) {
+        return (change.getTaskInfo() == null)
+                && !change.hasFlags(FLAG_IS_WALLPAPER)
+                && !change.hasFlags(FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY);
+    }
+
+    /**
+     * Filter that selects leaf-tasks only. THIS IS ORDER-DEPENDENT! For it to work properly, you
+     * MUST call `test` in the same order that the changes appear in the TransitionInfo.
+     */
+    public static class LeafTaskFilter implements Predicate<Change> {
+        private final SparseBooleanArray mChildTaskTargets = new SparseBooleanArray();
+
+        @Override
+        public boolean test(Change change) {
+            final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
+            // Children always come before parent since changes are in top-to-bottom z-order.
+            if ((taskInfo == null) || mChildTaskTargets.get(taskInfo.taskId)) {
+                // has children, so not a leaf. Skip.
+                return false;
+            }
+            if (taskInfo.hasParentTask()) {
+                mChildTaskTargets.put(taskInfo.parentTaskId, true);
+            }
+            return true;
+        }
+    }
 }
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java
index 44c0e16..2a37bd3 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java
@@ -18,7 +18,6 @@
 
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
-import static android.view.RemoteAnimationTarget.MODE_CLOSING;
 import static android.view.WindowManager.TRANSIT_CHANGE;
 import static android.view.WindowManager.TRANSIT_CLOSE;
 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_LOCKED;
@@ -72,71 +71,23 @@
             public void startAnimation(IBinder transition, TransitionInfo info,
                     SurfaceControl.Transaction t,
                     IRemoteTransitionFinishedCallback finishedCallback) {
-                final ArrayMap<SurfaceControl, SurfaceControl> leashMap = new ArrayMap<>();
-                final RemoteAnimationTarget[] apps =
-                        RemoteAnimationTargetCompat.wrapApps(info, t, leashMap);
-                final RemoteAnimationTarget[] wallpapers =
-                        RemoteAnimationTargetCompat.wrapNonApps(
-                                info, true /* wallpapers */, t, leashMap);
                 // TODO(b/177438007): Move this set-up logic into launcher's animation impl.
                 mToken = transition;
-                // This transition is for opening recents, so recents is on-top. We want to draw
-                // the current going-away tasks on top of recents, though, so move them to front.
-                // Note that we divide up the "layer space" into 3 regions each the size of
-                // the change count. This way we can easily move changes into above/below/between
-                // while maintaining their relative ordering.
-                final ArrayList<WindowContainerToken> pausingTasks = new ArrayList<>();
-                WindowContainerToken pipTask = null;
-                WindowContainerToken recentsTask = null;
-                int recentsTaskId = -1;
-                for (int i = apps.length - 1; i >= 0; --i) {
-                    final ActivityManager.RunningTaskInfo taskInfo = apps[i].taskInfo;
-                    if (apps[i].mode == MODE_CLOSING) {
-                        t.setLayer(apps[i].leash, info.getChanges().size() * 3 - i);
-                        if (taskInfo == null) {
-                            continue;
-                        }
-                        // Add to front since we are iterating backwards.
-                        pausingTasks.add(0, taskInfo.token);
-                        if (taskInfo.pictureInPictureParams != null
-                                && taskInfo.pictureInPictureParams.isAutoEnterEnabled()) {
-                            pipTask = taskInfo.token;
-                        }
-                    } else if (taskInfo != null
-                            && taskInfo.topActivityType == ACTIVITY_TYPE_RECENTS) {
-                        // This task is for recents, keep it on top.
-                        t.setLayer(apps[i].leash, info.getChanges().size() * 3 - i);
-                        recentsTask = taskInfo.token;
-                        recentsTaskId = taskInfo.taskId;
-                    } else if (taskInfo != null && taskInfo.topActivityType == ACTIVITY_TYPE_HOME) {
-                        recentsTask = taskInfo.token;
-                        recentsTaskId = taskInfo.taskId;
-                    }
-                }
-                // Also make all the wallpapers opaque since we want the visible from the start
-                for (int i = wallpapers.length - 1; i >= 0; --i) {
-                    t.setAlpha(wallpapers[i].leash, 1);
-                }
-                t.apply();
-                mRecentsSession.setup(controller, info, finishedCallback, pausingTasks, pipTask,
-                        recentsTask, recentsTaskId, leashMap, mToken,
-                        (info.getFlags() & TRANSIT_FLAG_KEYGUARD_LOCKED) != 0);
-                recents.onAnimationStart(mRecentsSession, apps, wallpapers, new Rect(0, 0, 0, 0),
-                        new Rect());
+                mRecentsSession.start(controller, recents, mToken, info, t, finishedCallback);
             }
 
             @Override
             public void mergeAnimation(IBinder transition, TransitionInfo info,
                     SurfaceControl.Transaction t, IBinder mergeTarget,
                     IRemoteTransitionFinishedCallback finishedCallback) {
-                if (mergeTarget.equals(mToken) && mRecentsSession.merge(info, t, recents)) {
+                if (mergeTarget.equals(mToken) && mRecentsSession.merge(info, t)) {
                     try {
                         finishedCallback.onTransitionFinished(null /* wct */, null /* sct */);
                     } catch (RemoteException e) {
                         Log.e(TAG, "Error merging transition.", e);
                     }
                     // commit taskAppeared after merge transition finished.
-                    mRecentsSession.commitTasksAppearedIfNeeded(recents);
+                    mRecentsSession.commitTasksAppearedIfNeeded();
                 } else {
                     t.close();
                     info.releaseAllSurfaces();
@@ -152,15 +103,16 @@
      */
     @VisibleForTesting
     static class RecentsControllerWrap extends RecentsAnimationControllerCompat {
+        private RecentsAnimationListener mListener = null;
         private RecentsAnimationControllerCompat mWrapped = null;
         private IRemoteTransitionFinishedCallback mFinishCB = null;
-        private ArrayList<WindowContainerToken> mPausingTasks = null;
+        private ArrayList<TaskState> mPausingTasks = null;
         private WindowContainerToken mPipTask = null;
         private WindowContainerToken mRecentsTask = null;
         private int mRecentsTaskId = 0;
         private TransitionInfo mInfo = null;
         private ArrayList<SurfaceControl> mOpeningLeashes = null;
-        private boolean mOpeningHome = false;
+        private boolean mOpeningSeparateHome = false;
         private ArrayMap<SurfaceControl, SurfaceControl> mLeashMap = null;
         private PictureInPictureSurfaceTransaction mPipTransaction = null;
         private IBinder mTransition = null;
@@ -168,34 +120,79 @@
         private RemoteAnimationTarget[] mAppearedTargets;
         private boolean mWillFinishToHome = false;
 
-        void setup(RecentsAnimationControllerCompat wrapped, TransitionInfo info,
-                IRemoteTransitionFinishedCallback finishCB,
-                ArrayList<WindowContainerToken> pausingTasks, WindowContainerToken pipTask,
-                WindowContainerToken recentsTask, int recentsTaskId, ArrayMap<SurfaceControl,
-                SurfaceControl> leashMap, IBinder transition, boolean keyguardLocked) {
+        void start(RecentsAnimationControllerCompat wrapped, RecentsAnimationListener listener,
+                IBinder transition, TransitionInfo info, SurfaceControl.Transaction t,
+                IRemoteTransitionFinishedCallback finishedCallback) {
             if (mInfo != null) {
                 throw new IllegalStateException("Trying to run a new recents animation while"
                         + " recents is already active.");
             }
+            mListener = listener;
             mWrapped = wrapped;
             mInfo = info;
-            mFinishCB = finishCB;
-            mPausingTasks = pausingTasks;
-            mPipTask = pipTask;
-            mRecentsTask = recentsTask;
-            mRecentsTaskId = recentsTaskId;
-            mLeashMap = leashMap;
+            mFinishCB = finishedCallback;
+            mPausingTasks = new ArrayList<>();
+            mPipTask = null;
+            mRecentsTask = null;
+            mRecentsTaskId = -1;
+            mLeashMap = new ArrayMap<>();
             mTransition = transition;
-            mKeyguardLocked = keyguardLocked;
+            mKeyguardLocked = (info.getFlags() & TRANSIT_FLAG_KEYGUARD_LOCKED) != 0;
+
+            final ArrayList<RemoteAnimationTarget> apps = new ArrayList<>();
+            final ArrayList<RemoteAnimationTarget> wallpapers = new ArrayList<>();
+            RemoteAnimationTargetCompat.LeafTaskFilter leafTaskFilter =
+                    new RemoteAnimationTargetCompat.LeafTaskFilter();
+            // About layering: we divide up the "layer space" into 3 regions (each the size of
+            // the change count). This lets us categorize things into above/below/between
+            // while maintaining their relative ordering.
+            for (int i = 0; i < info.getChanges().size(); ++i) {
+                final TransitionInfo.Change change = info.getChanges().get(i);
+                final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
+                if (RemoteAnimationTargetCompat.isWallpaper(change)) {
+                    final RemoteAnimationTarget target = newTarget(change,
+                            // wallpapers go into the "below" layer space
+                            info.getChanges().size() - i, info, t, mLeashMap);
+                    wallpapers.add(target);
+                    // Make all the wallpapers opaque since we want them visible from the start
+                    t.setAlpha(target.leash, 1);
+                } else if (leafTaskFilter.test(change)) {
+                    // start by putting everything into the "below" layer space.
+                    final RemoteAnimationTarget target = newTarget(change,
+                            info.getChanges().size() - i, info, t, mLeashMap);
+                    apps.add(target);
+                    if (change.getMode() == TRANSIT_CLOSE || change.getMode() == TRANSIT_TO_BACK) {
+                        // raise closing (pausing) task to "above" layer so it isn't covered
+                        t.setLayer(target.leash, info.getChanges().size() * 3 - i);
+                        mPausingTasks.add(new TaskState(change, target.leash));
+                        if (taskInfo.pictureInPictureParams != null
+                                && taskInfo.pictureInPictureParams.isAutoEnterEnabled()) {
+                            mPipTask = taskInfo.token;
+                        }
+                    } else if (taskInfo != null
+                            && taskInfo.topActivityType == ACTIVITY_TYPE_RECENTS) {
+                        // There's a 3p launcher, so make sure recents goes above that.
+                        t.setLayer(target.leash, info.getChanges().size() * 3 - i);
+                        mRecentsTask = taskInfo.token;
+                        mRecentsTaskId = taskInfo.taskId;
+                    } else if (taskInfo != null && taskInfo.topActivityType == ACTIVITY_TYPE_HOME) {
+                        mRecentsTask = taskInfo.token;
+                        mRecentsTaskId = taskInfo.taskId;
+                    }
+                }
+            }
+            t.apply();
+            mListener.onAnimationStart(this, apps.toArray(new RemoteAnimationTarget[apps.size()]),
+                    wallpapers.toArray(new RemoteAnimationTarget[wallpapers.size()]),
+                    new Rect(0, 0, 0, 0), new Rect());
         }
 
         @SuppressLint("NewApi")
-        boolean merge(TransitionInfo info, SurfaceControl.Transaction t,
-                RecentsAnimationListener recents) {
+        boolean merge(TransitionInfo info, SurfaceControl.Transaction t) {
             SparseArray<TransitionInfo.Change> openingTasks = null;
             mAppearedTargets = null;
-            boolean cancelRecents = false;
-            boolean homeGoingAway = false;
+            boolean foundHomeOpening = false;
+            boolean foundRecentsClosing = false;
             boolean hasChangingApp = false;
             for (int i = info.getChanges().size() - 1; i >= 0; --i) {
                 final TransitionInfo.Change change = info.getChanges().get(i);
@@ -203,8 +200,8 @@
                     final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
                     if (taskInfo != null) {
                         if (taskInfo.topActivityType == ACTIVITY_TYPE_HOME) {
-                            // canceling recents animation
-                            cancelRecents = true;
+                            // This is usually a 3p launcher
+                            foundHomeOpening = true;
                         }
                         if (openingTasks == null) {
                             openingTasks = new SparseArray<>();
@@ -219,19 +216,18 @@
                 } else if (change.getMode() == TRANSIT_CLOSE
                         || change.getMode() == TRANSIT_TO_BACK) {
                     if (mRecentsTask.equals(change.getContainer())) {
-                        homeGoingAway = true;
+                        foundRecentsClosing = true;
                     }
                 } else if (change.getMode() == TRANSIT_CHANGE) {
                     hasChangingApp = true;
                 }
             }
-            if (hasChangingApp && homeGoingAway) {
+            if (hasChangingApp && foundRecentsClosing) {
                 // This happens when a visible app is expanding (usually PiP). In this case,
-                // The transition probably has a special-purpose animation, so finish recents
+                // that transition probably has a special-purpose animation, so finish recents
                 // now and let it do its animation (since recents is going to be occluded).
-                if (!recents.onSwitchToScreenshot(() -> {
-                    finish(true /* toHome */, false /* userLeaveHint */);
-                })) {
+                if (!mListener.onSwitchToScreenshot(
+                        () -> finish(true /* toHome */, false /* userLeaveHint */))) {
                     Log.w(TAG, "Recents callback doesn't support support switching to screenshot"
                             + ", there might be a flicker.");
                     finish(true /* toHome */, false /* userLeaveHint */);
@@ -240,9 +236,9 @@
             }
             if (openingTasks == null) return false;
             int pauseMatches = 0;
-            if (!cancelRecents) {
+            if (!foundHomeOpening) {
                 for (int i = 0; i < openingTasks.size(); ++i) {
-                    if (mPausingTasks.contains(openingTasks.valueAt(i).getContainer())) {
+                    if (TaskState.indexOf(mPausingTasks, openingTasks.valueAt(i)) >= 0) {
                         ++pauseMatches;
                     }
                 }
@@ -262,7 +258,7 @@
             }
             final int layer = mInfo.getChanges().size() * 3;
             mOpeningLeashes = new ArrayList<>();
-            mOpeningHome = cancelRecents;
+            mOpeningSeparateHome = foundHomeOpening;
             final RemoteAnimationTarget[] targets =
                     new RemoteAnimationTarget[openingTasks.size()];
             for (int i = 0; i < openingTasks.size(); ++i) {
@@ -280,9 +276,9 @@
             return true;
         }
 
-        private void commitTasksAppearedIfNeeded(RecentsAnimationListener recents) {
+        private void commitTasksAppearedIfNeeded() {
             if (mAppearedTargets != null) {
-                recents.onTasksAppeared(mAppearedTargets);
+                mListener.onTasksAppeared(mAppearedTargets);
                 mAppearedTargets = null;
             }
         }
@@ -346,27 +342,26 @@
                 // re-showing it's task).
                 for (int i = mPausingTasks.size() - 1; i >= 0; --i) {
                     // reverse order so that index 0 ends up on top
-                    wct.reorder(mPausingTasks.get(i), true /* onTop */);
-                    t.show(mInfo.getChange(mPausingTasks.get(i)).getLeash());
+                    wct.reorder(mPausingTasks.get(i).mToken, true /* onTop */);
+                    t.show(mPausingTasks.get(i).mTaskSurface);
                 }
                 if (!mKeyguardLocked && mRecentsTask != null) {
                     wct.restoreTransientOrder(mRecentsTask);
                 }
-            } else if (toHome && mOpeningHome && mPausingTasks != null) {
+            } else if (toHome && mOpeningSeparateHome && mPausingTasks != null) {
                 // Special situaition where 3p launcher was changed during recents (this happens
                 // during tapltests...). Here we get both "return to home" AND "home opening".
                 // This is basically going home, but we have to restore recents order and also
                 // treat the home "pausing" task properly.
                 for (int i = mPausingTasks.size() - 1; i >= 0; --i) {
-                    final TransitionInfo.Change change = mInfo.getChange(mPausingTasks.get(i));
-                    final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
-                    if (taskInfo.topActivityType == ACTIVITY_TYPE_HOME) {
+                    final TaskState state = mPausingTasks.get(i);
+                    if (state.mTaskInfo.topActivityType == ACTIVITY_TYPE_HOME) {
                         // Treat as opening (see above)
-                        wct.reorder(mPausingTasks.get(i), true /* onTop */);
-                        t.show(mInfo.getChange(mPausingTasks.get(i)).getLeash());
+                        wct.reorder(state.mToken, true /* onTop */);
+                        t.show(state.mTaskSurface);
                     } else {
                         // Treat as hiding (see below)
-                        t.hide(mInfo.getChange(mPausingTasks.get(i)).getLeash());
+                        t.hide(state.mTaskSurface);
                     }
                 }
                 if (!mKeyguardLocked && mRecentsTask != null) {
@@ -377,13 +372,13 @@
                     if (!sendUserLeaveHint) {
                         // This means recents is not *actually* finishing, so of course we gotta
                         // do special stuff in WMCore to accommodate.
-                        wct.setDoNotPip(mPausingTasks.get(i));
+                        wct.setDoNotPip(mPausingTasks.get(i).mToken);
                     }
                     // Since we will reparent out of the leashes, pre-emptively hide the child
                     // surface to match the leash. Otherwise, there will be a flicker before the
                     // visibility gets committed in Core when using split-screen (in splitscreen,
                     // the leaf-tasks are not "independent" so aren't hidden by normal setup).
-                    t.hide(mInfo.getChange(mPausingTasks.get(i)).getLeash());
+                    t.hide(mPausingTasks.get(i).mTaskSurface);
                 }
                 if (mPipTask != null && mPipTransaction != null && sendUserLeaveHint) {
                     t.show(mInfo.getChange(mPipTask).getLeash());
@@ -404,11 +399,13 @@
             mInfo.releaseAllSurfaces();
             // Reset all members.
             mWrapped = null;
+            mListener = null;
             mFinishCB = null;
             mPausingTasks = null;
+            mAppearedTargets = null;
             mInfo = null;
             mOpeningLeashes = null;
-            mOpeningHome = false;
+            mOpeningSeparateHome = false;
             mLeashMap = null;
             mTransition = null;
         }
@@ -450,4 +447,36 @@
         @Override public void animateNavigationBarToApp(long duration) {
         }
     }
+
+    /** Utility class to track the state of a task as-seen by recents. */
+    private static class TaskState {
+        WindowContainerToken mToken;
+        ActivityManager.RunningTaskInfo mTaskInfo;
+
+        /** The surface/leash of the task provided by Core. */
+        SurfaceControl mTaskSurface;
+
+        /** The (local) animation-leash created for this task. */
+        SurfaceControl mLeash;
+
+        TaskState(TransitionInfo.Change change, SurfaceControl leash) {
+            mToken = change.getContainer();
+            mTaskInfo = change.getTaskInfo();
+            mTaskSurface = change.getLeash();
+            mLeash = leash;
+        }
+
+        static int indexOf(ArrayList<TaskState> list, TransitionInfo.Change change) {
+            for (int i = list.size() - 1; i >= 0; --i) {
+                if (list.get(i).mToken.equals(change.getContainer())) {
+                    return i;
+                }
+            }
+            return -1;
+        }
+
+        public String toString() {
+            return "" + mToken + " : " + mLeash;
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index 559423b..94ce002 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -1416,6 +1416,7 @@
             @Override
             public void onAnimationCancel(@NonNull Animator animation) {
                 mInteractionJankMonitor.cancel(CUJ_VOLUME_CONTROL);
+                Log.d(TAG, "onAnimationCancel");
             }
 
             @Override
@@ -1506,6 +1507,7 @@
         mHandler.removeMessages(H.DISMISS);
         mHandler.removeMessages(H.SHOW);
         if (mIsAnimatingDismiss) {
+            Log.d(TAG, "dismissH: isAnimatingDismiss");
             return;
         }
         mIsAnimatingDismiss = true;
diff --git a/telephony/java/android/telephony/satellite/ISatelliteDatagramCallback.aidl b/telephony/java/android/telephony/satellite/ISatelliteDatagramCallback.aidl
index abf2b55..c15374a 100644
--- a/telephony/java/android/telephony/satellite/ISatelliteDatagramCallback.aidl
+++ b/telephony/java/android/telephony/satellite/ISatelliteDatagramCallback.aidl
@@ -25,10 +25,10 @@
  */
 oneway interface ISatelliteDatagramCallback {
     /**
-     * Called when datagrams are received from satellite.
+     * Called when there is an incoming datagram to be received from satellite.
      *
      * @param datagramId An id that uniquely identifies incoming datagram.
-     * @param datagram datagram received from satellite.
+     * @param datagram Datagram received from satellite.
      * @param pendingCount Number of datagrams yet to be received from satellite.
      * @param callback This callback will be used by datagram receiver app to send ack back to
      *                 Telephony. If the callback is not received within five minutes,
diff --git a/telephony/java/android/telephony/satellite/ISatellitePositionUpdateCallback.aidl b/telephony/java/android/telephony/satellite/ISatellitePositionUpdateCallback.aidl
index 4478d0a..d3f1091 100644
--- a/telephony/java/android/telephony/satellite/ISatellitePositionUpdateCallback.aidl
+++ b/telephony/java/android/telephony/satellite/ISatellitePositionUpdateCallback.aidl
@@ -24,20 +24,20 @@
  */
 oneway interface ISatellitePositionUpdateCallback {
     /**
-     * Called when satellite datagram transfer state changes.
+     * Called when satellite datagram transfer state changed.
      *
      * @param state The new datagram transfer state.
      * @param sendPendingCount The number of datagrams that are currently being sent.
      * @param receivePendingCount The number of datagrams that are currently being received.
      * @param errorCode If datagram transfer failed, the reason for failure.
      */
-    void onDatagramTransferStateUpdate(in int state, in int sendPendingCount,
+    void onDatagramTransferStateChanged(in int state, in int sendPendingCount,
             in int receivePendingCount, in int errorCode);
 
     /**
-     * Called when the satellite position changes.
+     * Called when the satellite position changed.
      *
      * @param pointingInfo The pointing info containing the satellite location.
      */
-    void onSatellitePositionUpdate(in PointingInfo pointingInfo);
+    void onSatellitePositionChanged(in PointingInfo pointingInfo);
 }
diff --git a/telephony/java/android/telephony/satellite/ISatelliteStateCallback.aidl b/telephony/java/android/telephony/satellite/ISatelliteStateCallback.aidl
index 8d1e3c2..98221c9 100644
--- a/telephony/java/android/telephony/satellite/ISatelliteStateCallback.aidl
+++ b/telephony/java/android/telephony/satellite/ISatelliteStateCallback.aidl
@@ -33,5 +33,5 @@
      *
      * @param state The current satellite modem state.
      */
-    void onSatelliteModemStateChange(in int state);
+    void onSatelliteModemStateChanged(in int state);
 }
diff --git a/telephony/java/android/telephony/satellite/PointingInfo.java b/telephony/java/android/telephony/satellite/PointingInfo.java
index d6dd57a..a3c3f19 100644
--- a/telephony/java/android/telephony/satellite/PointingInfo.java
+++ b/telephony/java/android/telephony/satellite/PointingInfo.java
@@ -48,10 +48,10 @@
     /**
      * @hide
      */
-    public PointingInfo(float satelliteAzimuthDegress, float satelliteElevationDegress,
+    public PointingInfo(float satelliteAzimuthDegrees, float satelliteElevationDegrees,
             float antennaAzimuthDegrees, float antennaPitchDegrees, float antennaRollDegrees) {
-        mSatelliteAzimuthDegrees = satelliteAzimuthDegress;
-        mSatelliteElevationDegrees = satelliteElevationDegress;
+        mSatelliteAzimuthDegrees = satelliteAzimuthDegrees;
+        mSatelliteElevationDegrees = satelliteElevationDegrees;
         mAntennaAzimuthDegrees = antennaAzimuthDegrees;
         mAntennaPitchDegrees = antennaPitchDegrees;
         mAntennaRollDegrees = antennaRollDegrees;
diff --git a/telephony/java/android/telephony/satellite/SatelliteCapabilities.java b/telephony/java/android/telephony/satellite/SatelliteCapabilities.java
index 74f6f57..889856b 100644
--- a/telephony/java/android/telephony/satellite/SatelliteCapabilities.java
+++ b/telephony/java/android/telephony/satellite/SatelliteCapabilities.java
@@ -30,7 +30,7 @@
     /**
      * List of technologies supported by the satellite modem.
      */
-    private Set<Integer> mSupportedRadioTechnologies;
+    @NonNull @SatelliteManager.NTRadioTechnology private Set<Integer> mSupportedRadioTechnologies;
 
     /**
      * Whether satellite modem is always on.
@@ -53,7 +53,8 @@
      */
     public SatelliteCapabilities(Set<Integer> supportedRadioTechnologies, boolean isAlwaysOn,
             boolean needsPointingToSatellite, boolean needsSeparateSimProfile) {
-        mSupportedRadioTechnologies = supportedRadioTechnologies;
+        mSupportedRadioTechnologies = supportedRadioTechnologies == null
+                ? new HashSet<>() : supportedRadioTechnologies;
         mIsAlwaysOn = isAlwaysOn;
         mNeedsPointingToSatellite = needsPointingToSatellite;
         mNeedsSeparateSimProfile = needsSeparateSimProfile;
@@ -126,7 +127,8 @@
     /**
      * @return The list of technologies supported by the satellite modem.
      */
-    @NonNull public Set<Integer> getSupportedRadioTechnologies() {
+    @NonNull @SatelliteManager.NTRadioTechnology public Set<Integer>
+            getSupportedRadioTechnologies() {
         return mSupportedRadioTechnologies;
     }
 
diff --git a/telephony/java/android/telephony/satellite/SatelliteDatagramCallback.java b/telephony/java/android/telephony/satellite/SatelliteDatagramCallback.java
index 2c3884c..8ccc993 100644
--- a/telephony/java/android/telephony/satellite/SatelliteDatagramCallback.java
+++ b/telephony/java/android/telephony/satellite/SatelliteDatagramCallback.java
@@ -55,9 +55,9 @@
     }
 
     /**
-     * Called when there are incoming datagrams to be received.
+     * Called when there is an incoming datagram to be received.
      * @param datagramId An id that uniquely identifies incoming datagram.
-     * @param datagram datagram to be received over satellite.
+     * @param datagram Datagram to be received over satellite.
      * @param pendingCount Number of datagrams yet to be received by the app.
      * @param callback This callback will be used by datagram receiver app to send ack back to
      *                 Telephony.
@@ -67,13 +67,13 @@
         // Base Implementation
     }
 
-    /**@hide*/
+    /** @hide */
     @NonNull
     public final ISatelliteDatagramCallback getBinder() {
         return mBinder;
     }
 
-    /**@hide*/
+    /** @hide */
     public void setExecutor(@NonNull Executor executor) {
         mBinder.setExecutor(executor);
     }
diff --git a/telephony/java/android/telephony/satellite/SatelliteManager.java b/telephony/java/android/telephony/satellite/SatelliteManager.java
index dbc0ed9..3009bec 100644
--- a/telephony/java/android/telephony/satellite/SatelliteManager.java
+++ b/telephony/java/android/telephony/satellite/SatelliteManager.java
@@ -116,6 +116,13 @@
 
     /**
      * Bundle key to get the response from
+     * {@link #requestIsSatelliteDemoModeEnabled(Executor, OutcomeReceiver)}.
+     * @hide
+     */
+    public static final String KEY_DEMO_MODE_ENABLED = "demo_mode_enabled";
+
+    /**
+     * Bundle key to get the response from
      * {@link #requestIsSatelliteSupported(Executor, OutcomeReceiver)}.
      * @hide
      */
@@ -284,6 +291,39 @@
     public @interface SatelliteError {}
 
     /**
+     * 3GPP NB-IoT (Narrowband Internet of Things) over Non-Terrestrial-Networks technology.
+     */
+    public static final int NT_RADIO_TECHNOLOGY_NB_IOT_NTN = 0;
+    /**
+     * 3GPP 5G NR over Non-Terrestrial-Networks technology.
+     */
+    public static final int NT_RADIO_TECHNOLOGY_NR_NTN = 1;
+    /**
+     * 3GPP eMTC (enhanced Machine-Type Communication) over Non-Terrestrial-Networks technology.
+     */
+    public static final int NT_RADIO_TECHNOLOGY_EMTC_NTN = 2;
+    /**
+     * Proprietary technology.
+     */
+    public static final int NT_RADIO_TECHNOLOGY_PROPRIETARY = 3;
+    /**
+     * Unknown Non-Terrestrial radio technology. This generic radio technology should be used
+     * only when the radio technology cannot be mapped to other specific radio technologies.
+     */
+    public static final int NT_RADIO_TECHNOLOGY_UNKNOWN = -1;
+
+    /** @hide */
+    @IntDef(prefix = "NT_RADIO_TECHNOLOGY_", value = {
+            NT_RADIO_TECHNOLOGY_NB_IOT_NTN,
+            NT_RADIO_TECHNOLOGY_NR_NTN,
+            NT_RADIO_TECHNOLOGY_EMTC_NTN,
+            NT_RADIO_TECHNOLOGY_PROPRIETARY,
+            NT_RADIO_TECHNOLOGY_UNKNOWN
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface NTRadioTechnology {}
+
+    /**
      * Request to enable or disable the satellite modem. If the satellite modem is enabled, this
      * will also disable the cellular modem, and if the satellite modem is disabled, this will also
      * re-enable the cellular modem.
@@ -377,6 +417,97 @@
     }
 
     /**
+     * Request to enable or disable the satellite service demo mode.
+     *
+     * @param enable {@code true} to enable the satellite demo mode and {@code false} to disable.
+     * @param executor The executor on which the error code listener will be called.
+     * @param errorCodeListener Listener for the {@link SatelliteError} result of the operation.
+     *
+     * @throws SecurityException if the caller doesn't have required permission.
+     * @throws IllegalStateException if the Telephony process is not currently available.
+     */
+    @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
+    public void requestSatelliteDemoModeEnabled(boolean enable,
+            @NonNull @CallbackExecutor Executor executor,
+            @NonNull Consumer<Integer> errorCodeListener) {
+        Objects.requireNonNull(executor);
+        Objects.requireNonNull(errorCodeListener);
+
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony != null) {
+                IIntegerConsumer errorCallback = new IIntegerConsumer.Stub() {
+                    @Override
+                    public void accept(int result) {
+                        executor.execute(() -> Binder.withCleanCallingIdentity(
+                                () -> errorCodeListener.accept(result)));
+                    }
+                };
+                telephony.requestSatelliteDemoModeEnabled(mSubId, enable, errorCallback);
+            } else {
+                throw new IllegalStateException("telephony service is null.");
+            }
+        } catch (RemoteException ex) {
+            Rlog.e(TAG, "requestSatelliteDemoModeEnabled() RemoteException: ", ex);
+            ex.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Request to get whether the satellite service demo mode is enabled.
+     *
+     * @param executor The executor on which the callback will be called.
+     * @param callback The callback object to which the result will be delivered.
+     *                 If the request is successful, {@link OutcomeReceiver#onResult(Object)}
+     *                 will return a {@code boolean} with value {@code true} if the satellite
+     *                 demo mode is enabled and {@code false} otherwise.
+     *                 If the request is not successful, {@link OutcomeReceiver#onError(Throwable)}
+     *                 will return a {@link SatelliteException} with the {@link SatelliteError}.
+     *
+     * @throws SecurityException if the caller doesn't have required permission.
+     * @throws IllegalStateException if the Telephony process is not currently available.
+     */
+    @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
+    public void requestIsSatelliteDemoModeEnabled(@NonNull @CallbackExecutor Executor executor,
+            @NonNull OutcomeReceiver<Boolean, SatelliteException> callback) {
+        Objects.requireNonNull(executor);
+        Objects.requireNonNull(callback);
+
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony != null) {
+                ResultReceiver receiver = new ResultReceiver(null) {
+                    @Override
+                    protected void onReceiveResult(int resultCode, Bundle resultData) {
+                        if (resultCode == SATELLITE_ERROR_NONE) {
+                            if (resultData.containsKey(KEY_DEMO_MODE_ENABLED)) {
+                                boolean isDemoModeEnabled =
+                                        resultData.getBoolean(KEY_DEMO_MODE_ENABLED);
+                                executor.execute(() -> Binder.withCleanCallingIdentity(() ->
+                                        callback.onResult(isDemoModeEnabled)));
+                            } else {
+                                loge("KEY_DEMO_MODE_ENABLED does not exist.");
+                                executor.execute(() -> Binder.withCleanCallingIdentity(() ->
+                                        callback.onError(
+                                                new SatelliteException(SATELLITE_REQUEST_FAILED))));
+                            }
+                        } else {
+                            executor.execute(() -> Binder.withCleanCallingIdentity(() ->
+                                    callback.onError(new SatelliteException(resultCode))));
+                        }
+                    }
+                };
+                telephony.requestIsSatelliteDemoModeEnabled(mSubId, receiver);
+            } else {
+                throw new IllegalStateException("telephony service is null.");
+            }
+        } catch (RemoteException ex) {
+            loge("requestIsSatelliteDemoModeEnabled() RemoteException: " + ex);
+            ex.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Request to get whether the satellite service is supported on the device.
      *
      * @param executor The executor on which the callback will be called.
@@ -513,6 +644,12 @@
      * must be sent before reporting any additional datagram transfer state changes.
      */
     public static final int SATELLITE_DATAGRAM_TRANSFER_STATE_FAILED = 5;
+    /**
+     * The datagram transfer state is unknown. This generic datagram transfer state should be used
+     * only when the datagram transfer state cannot be mapped to other specific datagram transfer
+     * states.
+     */
+    public static final int SATELLITE_DATAGRAM_TRANSFER_STATE_UNKNOWN = -1;
 
     /** @hide */
     @IntDef(prefix = {"SATELLITE_DATAGRAM_TRANSFER_STATE_"}, value = {
@@ -521,46 +658,70 @@
             SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING,
             SATELLITE_DATAGRAM_TRANSFER_STATE_RETRYING,
             SATELLITE_DATAGRAM_TRANSFER_STATE_SUCCESS,
-            SATELLITE_DATAGRAM_TRANSFER_STATE_FAILED
+            SATELLITE_DATAGRAM_TRANSFER_STATE_FAILED,
+            SATELLITE_DATAGRAM_TRANSFER_STATE_UNKNOWN
     })
+    @Retention(RetentionPolicy.SOURCE)
     public @interface SatelliteDatagramTransferState {}
 
-    /* Satellite modem is in idle state. */
+    /**
+     * Satellite modem is in idle state.
+     */
     public static final int SATELLITE_MODEM_STATE_IDLE = 0;
-
-    /* Satellite modem is listening for incoming datagrams. */
+    /**
+     * Satellite modem is listening for incoming datagrams.
+     */
     public static final int SATELLITE_MODEM_STATE_LISTENING = 1;
-
-    /* Satellite modem is sending and/or receiving datagrams. */
+    /**
+     * Satellite modem is sending and/or receiving datagrams.
+     */
     public static final int SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING = 2;
-
-    /* Satellite modem is powered off. */
-    public static final int SATELLITE_MODEM_STATE_OFF = 3;
+    /**
+     * Satellite modem is retrying to send and/or receive datagrams.
+     */
+    public static final int SATELLITE_MODEM_STATE_DATAGRAM_RETRYING = 3;
+    /**
+     * Satellite modem is powered off.
+     */
+    public static final int SATELLITE_MODEM_STATE_OFF = 4;
+    /**
+     * Satellite modem state is unknown. This generic modem state should be used only when the
+     * modem state cannot be mapped to other specific modem states.
+     */
+    public static final int SATELLITE_MODEM_STATE_UNKNOWN = -1;
 
     /** @hide */
-    @IntDef(prefix = {"SATELLITE_STATE_"},
-            value = {
-                    SATELLITE_MODEM_STATE_IDLE,
-                    SATELLITE_MODEM_STATE_LISTENING,
-                    SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING,
-                    SATELLITE_MODEM_STATE_OFF
-            })
+    @IntDef(prefix = {"SATELLITE_MODEM_STATE_"}, value = {
+            SATELLITE_MODEM_STATE_IDLE,
+            SATELLITE_MODEM_STATE_LISTENING,
+            SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING,
+            SATELLITE_MODEM_STATE_DATAGRAM_RETRYING,
+            SATELLITE_MODEM_STATE_OFF,
+            SATELLITE_MODEM_STATE_UNKNOWN
+    })
     @Retention(RetentionPolicy.SOURCE)
     public @interface SatelliteModemState {}
 
-    /** Datagram type indicating that the datagram to be sent or received is of type SOS message. */
+    /**
+     * Datagram type indicating that the datagram to be sent or received is of type SOS message.
+     */
     public static final int DATAGRAM_TYPE_SOS_MESSAGE = 0;
+    /**
+     * Datagram type indicating that the datagram to be sent or received is of type
+     * location sharing.
+     */
+    public static final int DATAGRAM_TYPE_LOCATION_SHARING = 1;
+    /**
+     * Datagram type is unknown. This generic datagram type should be used only when the
+     * datagram type cannot be mapped to other specific datagram types.
+     */
+    public static final int DATAGRAM_TYPE_UNKNOWN = -1;
 
-    /** Datagram type indicating that the datagram to be sent or received is of type
-     * location sharing. */
-    public static final int DATAGRAM_TYPE_LOCATION_SHARING = 3;
-
-    @IntDef(
-            prefix = "DATAGRAM_TYPE_",
-            value = {
-                    DATAGRAM_TYPE_SOS_MESSAGE,
-                    DATAGRAM_TYPE_LOCATION_SHARING,
-            })
+    @IntDef(prefix = "DATAGRAM_TYPE_", value = {
+            DATAGRAM_TYPE_SOS_MESSAGE,
+            DATAGRAM_TYPE_LOCATION_SHARING,
+            DATAGRAM_TYPE_UNKNOWN
+    })
     @Retention(RetentionPolicy.SOURCE)
     public @interface DatagramType {}
 
@@ -802,7 +963,7 @@
     }
 
     /**
-     * Register for the satellite provision state change.
+     * Registers for the satellite provision state changed.
      *
      * @param executor The executor on which the callback will be called.
      * @param callback The callback to handle the satellite provision state changed event.
@@ -836,7 +997,7 @@
     }
 
     /**
-     * Unregister for the satellite provision state change.
+     * Unregisters for the satellite provision state changed.
      * If callback was not registered before, the request will be ignored.
      *
      * @param callback The callback that was passed to
@@ -918,10 +1079,10 @@
     }
 
     /**
-     * Register for listening to satellite modem state changes.
+     * Registers for modem state changed from satellite modem.
      *
      * @param executor The executor on which the callback will be called.
-     * @param callback The callback to handle the satellite modem state change event.
+     * @param callback The callback to handle the satellite modem state changed event.
      *
      * @return The {@link SatelliteError} result of the operation.
      *
@@ -929,7 +1090,7 @@
      * @throws IllegalStateException if the Telephony process is not currently available.
      */
     @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
-    @SatelliteError public int registerForSatelliteModemStateChange(
+    @SatelliteError public int registerForSatelliteModemStateChanged(
             @NonNull @CallbackExecutor Executor executor,
             @NonNull SatelliteStateCallback callback) {
         Objects.requireNonNull(executor);
@@ -939,41 +1100,41 @@
             ITelephony telephony = getITelephony();
             if (telephony != null) {
                 callback.setExecutor(executor);
-                return telephony.registerForSatelliteModemStateChange(mSubId,
+                return telephony.registerForSatelliteModemStateChanged(mSubId,
                         callback.getBinder());
             } else {
                 throw new IllegalStateException("telephony service is null.");
             }
         } catch (RemoteException ex) {
-            loge("registerForSatelliteModemStateChange() RemoteException:" + ex);
+            loge("registerForSatelliteModemStateChanged() RemoteException:" + ex);
             ex.rethrowFromSystemServer();
         }
         return SATELLITE_REQUEST_FAILED;
     }
 
     /**
-     * Unregister to stop listening to satellite modem state changes.
+     * Unregisters for modem state changed from satellite modem.
      * If callback was not registered before, the request will be ignored.
      *
      * @param callback The callback that was passed to
-     * {@link #registerForSatelliteModemStateChange(Executor, SatelliteStateCallback)}.
+     * {@link #registerForSatelliteModemStateChanged(Executor, SatelliteStateCallback)}.
      *
      * @throws SecurityException if the caller doesn't have required permission.
      * @throws IllegalStateException if the Telephony process is not currently available.
      */
     @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
-    public void unregisterForSatelliteModemStateChange(@NonNull SatelliteStateCallback callback) {
+    public void unregisterForSatelliteModemStateChanged(@NonNull SatelliteStateCallback callback) {
         Objects.requireNonNull(callback);
 
         try {
             ITelephony telephony = getITelephony();
             if (telephony != null) {
-                telephony.unregisterForSatelliteModemStateChange(mSubId, callback.getBinder());
+                telephony.unregisterForSatelliteModemStateChanged(mSubId, callback.getBinder());
             } else {
                 throw new IllegalStateException("telephony service is null.");
             }
         } catch (RemoteException ex) {
-            loge("unregisterForSatelliteModemStateChange() RemoteException:" + ex);
+            loge("unregisterForSatelliteModemStateChanged() RemoteException:" + ex);
             ex.rethrowFromSystemServer();
         }
     }
diff --git a/telephony/java/android/telephony/satellite/SatellitePositionUpdateCallback.java b/telephony/java/android/telephony/satellite/SatellitePositionUpdateCallback.java
index cda7a75..e3e4171 100644
--- a/telephony/java/android/telephony/satellite/SatellitePositionUpdateCallback.java
+++ b/telephony/java/android/telephony/satellite/SatellitePositionUpdateCallback.java
@@ -39,24 +39,24 @@
         }
 
         @Override
-        public void onSatellitePositionUpdate(@NonNull PointingInfo pointingInfo) {
+        public void onSatellitePositionChanged(@NonNull PointingInfo pointingInfo) {
             final long callingIdentity = Binder.clearCallingIdentity();
             try {
                 mExecutor.execute(() ->
-                        mLocalCallback.onSatellitePositionUpdate(pointingInfo));
+                        mLocalCallback.onSatellitePositionChanged(pointingInfo));
             } finally {
                 restoreCallingIdentity(callingIdentity);
             }
         }
 
         @Override
-        public void onDatagramTransferStateUpdate(
+        public void onDatagramTransferStateChanged(
                 @SatelliteManager.SatelliteDatagramTransferState int state, int sendPendingCount,
                 int receivePendingCount, @SatelliteManager.SatelliteError int errorCode) {
             final long callingIdentity = Binder.clearCallingIdentity();
             try {
                 mExecutor.execute(() ->
-                        mLocalCallback.onDatagramTransferStateUpdate(
+                        mLocalCallback.onDatagramTransferStateChanged(
                                 state, sendPendingCount, receivePendingCount, errorCode));
             } finally {
                 restoreCallingIdentity(callingIdentity);
@@ -69,23 +69,23 @@
     }
 
     /**
-     * Called when the satellite position changes.
+     * Called when the satellite position changed.
      *
      * @param pointingInfo The pointing info containing the satellite location.
      */
-    public void onSatellitePositionUpdate(@NonNull PointingInfo pointingInfo) {
+    public void onSatellitePositionChanged(@NonNull PointingInfo pointingInfo) {
         // Base Implementation
     }
 
     /**
-     * Called when satellite datagram transfer state changes.
+     * Called when satellite datagram transfer state changed.
      *
      * @param state The new datagram transfer state.
      * @param sendPendingCount The number of datagrams that are currently being sent.
      * @param receivePendingCount The number of datagrams that are currently being received.
      * @param errorCode If datagram transfer failed, the reason for failure.
      */
-    public void onDatagramTransferStateUpdate(
+    public void onDatagramTransferStateChanged(
             @SatelliteManager.SatelliteDatagramTransferState int state, int sendPendingCount,
             int receivePendingCount, @SatelliteManager.SatelliteError int errorCode) {
         // Base Implementation
diff --git a/telephony/java/android/telephony/satellite/SatelliteStateCallback.java b/telephony/java/android/telephony/satellite/SatelliteStateCallback.java
index 81701a2..d24bee6 100644
--- a/telephony/java/android/telephony/satellite/SatelliteStateCallback.java
+++ b/telephony/java/android/telephony/satellite/SatelliteStateCallback.java
@@ -38,11 +38,11 @@
         }
 
         @Override
-        public void onSatelliteModemStateChange(@SatelliteManager.SatelliteModemState int state) {
+        public void onSatelliteModemStateChanged(@SatelliteManager.SatelliteModemState int state) {
             final long callingIdentity = Binder.clearCallingIdentity();
             try {
                 mExecutor.execute(() ->
-                        mLocalCallback.onSatelliteModemStateChange(state));
+                        mLocalCallback.onSatelliteModemStateChanged(state));
             } finally {
                 restoreCallingIdentity(callingIdentity);
             }
@@ -68,7 +68,7 @@
      * Called when satellite modem state changes.
      * @param state The new satellite modem state.
      */
-    public void onSatelliteModemStateChange(@SatelliteManager.SatelliteModemState int state) {
+    public void onSatelliteModemStateChanged(@SatelliteManager.SatelliteModemState int state) {
         // Base Implementation
     }
 
diff --git a/telephony/java/android/telephony/satellite/stub/ISatellite.aidl b/telephony/java/android/telephony/satellite/stub/ISatellite.aidl
index e0c31ed..5dc1a65 100644
--- a/telephony/java/android/telephony/satellite/stub/ISatellite.aidl
+++ b/telephony/java/android/telephony/satellite/stub/ISatellite.aidl
@@ -46,10 +46,11 @@
     void setSatelliteListener(in ISatelliteListener listener, in IIntegerConsumer errorCallback);
 
     /**
-     * Enable or disable the satellite service listening mode.
+     * Request to enable or disable the satellite service listening mode.
      * Listening mode allows the satellite service to listen for incoming pages.
      *
      * @param enable True to enable satellite listening mode and false to disable.
+     * @param isDemoMode Whether demo mode is enabled.
      * @param errorCallback The callback to receive the error code result of the operation.
      *
      * Valid error codes returned:
@@ -62,7 +63,8 @@
      *   SatelliteError:REQUEST_NOT_SUPPORTED
      *   SatelliteError:NO_RESOURCES
      */
-    void setSatelliteListeningEnabled(in boolean enable, in IIntegerConsumer errorCallback);
+    void requestSatelliteListeningEnabled(in boolean enable, in boolean isDemoMode,
+            in IIntegerConsumer errorCallback);
 
     /**
      * Request to enable or disable the satellite modem. If the satellite modem is enabled,
@@ -149,7 +151,7 @@
     /**
      * User started pointing to the satellite.
      * The satellite service should report the satellite pointing info via
-     * ISatelliteListener#onSatellitePointingInfoChanged as the user device/satellite moves.
+     * ISatelliteListener#onSatellitePositionChanged as the user device/satellite moves.
      *
      * @param errorCallback The callback to receive the error code result of the operation.
      *
@@ -275,7 +277,7 @@
     /**
      * Poll the pending datagrams to be received over satellite.
      * The satellite service should check if there are any pending datagrams to be received over
-     * satellitea and report them via ISatelliteListener#onNewDatagrams.
+     * satellite and report them via ISatelliteListener#onSatelliteDatagramsReceived.
      *
      * @param errorCallback The callback to receive the error code result of the operation.
      *
@@ -298,10 +300,9 @@
 
     /**
      * Send datagram over satellite.
-     * Once sent, the satellite service should report whether the operation was successful via
-     * SatelliteListener#onDatagramsDelivered.
      *
      * @param datagram Datagram to send in byte format.
+     * @param isDemoMode Whether demo mode is enabled.
      * @param isEmergency Whether this is an emergency datagram.
      * @param errorCallback The callback to receive the error code result of the operation.
      *
@@ -321,8 +322,8 @@
      *   SatelliteError:SATELLITE_NOT_REACHABLE
      *   SatelliteError:NOT_AUTHORIZED
      */
-    void sendSatelliteDatagram(in SatelliteDatagram datagram, in boolean isEmergency,
-            in IIntegerConsumer errorCallback);
+    void sendSatelliteDatagram(in SatelliteDatagram datagram, in boolean isDemoMode,
+            in boolean isEmergency, in IIntegerConsumer errorCallback);
 
     /**
      * Request the current satellite modem state.
diff --git a/telephony/java/android/telephony/satellite/stub/ISatelliteListener.aidl b/telephony/java/android/telephony/satellite/stub/ISatelliteListener.aidl
index 5ecd442..e24e892e 100644
--- a/telephony/java/android/telephony/satellite/stub/ISatelliteListener.aidl
+++ b/telephony/java/android/telephony/satellite/stub/ISatelliteListener.aidl
@@ -19,6 +19,7 @@
 import android.telephony.satellite.stub.NTRadioTechnology;
 import android.telephony.satellite.stub.PointingInfo;
 import android.telephony.satellite.stub.SatelliteDatagram;
+import android.telephony.satellite.stub.SatelliteError;
 import android.telephony.satellite.stub.SatelliteModemState;
 
 /**
@@ -35,10 +36,10 @@
     /**
      * Indicates that new datagrams have been received on the device.
      *
-     * @param datagrams New datagrams received.
+     * @param datagrams Array of new datagrams received.
      * @param pendingCount The number of datagrams that are pending.
      */
-    void onNewDatagrams(in SatelliteDatagram[] datagrams, in int pendingCount);
+    void onSatelliteDatagramsReceived(in SatelliteDatagram[] datagrams, in int pendingCount);
 
     /**
      * Indicates that the satellite has pending datagrams for the device to be pulled.
@@ -52,27 +53,19 @@
      *
      * @param pointingInfo The current pointing info.
      */
-    void onSatellitePointingInfoChanged(in PointingInfo pointingInfo);
+    void onSatellitePositionChanged(in PointingInfo pointingInfo);
 
     /**
      * Indicates that the satellite modem state has changed.
      *
-     * @param mode The current satellite modem state.
+     * @param state The current satellite modem state.
      */
-    void onSatelliteModemStateChanged(in SatelliteModemState mode);
+    void onSatelliteModemStateChanged(in SatelliteModemState state);
 
     /**
      * Indicates that the satellite radio technology has changed.
      *
-     * @param technology The current satellite service mode.
+     * @param technology The current satellite radio technology.
      */
     void onSatelliteRadioTechnologyChanged(in NTRadioTechnology technology);
-
-    /**
-     * Indicates that datagram transfer is complete and all datagrams have been delivered.
-     *
-     * @param delivered True means all datagrams have been delivered and false means there was an
-     *                  error in delivering all datagrams.
-     */
-    void onDatagramsDelivered(in boolean delivered);
 }
diff --git a/telephony/java/android/telephony/satellite/stub/NTRadioTechnology.aidl b/telephony/java/android/telephony/satellite/stub/NTRadioTechnology.aidl
index 64cfa85..3316408 100644
--- a/telephony/java/android/telephony/satellite/stub/NTRadioTechnology.aidl
+++ b/telephony/java/android/telephony/satellite/stub/NTRadioTechnology.aidl
@@ -21,12 +21,25 @@
  */
 @Backing(type="int")
 enum NTRadioTechnology {
-    /* 3GPP NB-IoT (Narrowband Internet of Things) over Non-Terrestrial-Networks technology. */
-    NB_IOT_NTN,
-    /* 3GPP 5G NR over Non-Terrestrial-Networks technology. */
-    NR_NTN,
-    /* 3GPP eMTC (enhanced Machine-Type Communication) over Non-Terrestrial-Networks technology. */
-    EMTC_NTN,
-    /* Proprietary technology. */
-    PROPRIETARY,
+    /**
+     * 3GPP NB-IoT (Narrowband Internet of Things) over Non-Terrestrial-Networks technology.
+     */
+    NB_IOT_NTN = 0,
+    /*
+     * 3GPP 5G NR over Non-Terrestrial-Networks technology.
+     */
+    NR_NTN = 1,
+    /**
+     * 3GPP eMTC (enhanced Machine-Type Communication) over Non-Terrestrial-Networks technology.
+     */
+    EMTC_NTN = 2,
+    /**
+     * Proprietary technology.
+     */
+    PROPRIETARY = 3,
+    /**
+     * Unknown Non-Terrestrial radio technology. This generic radio technology should be used
+     * only when the radio technology cannot be mapped to other specific radio technologies.
+     */
+    UNKNOWN = -1,
 }
diff --git a/telephony/java/android/telephony/satellite/stub/PointingInfo.aidl b/telephony/java/android/telephony/satellite/stub/PointingInfo.aidl
index b515b3e..83392dd 100644
--- a/telephony/java/android/telephony/satellite/stub/PointingInfo.aidl
+++ b/telephony/java/android/telephony/satellite/stub/PointingInfo.aidl
@@ -30,18 +30,20 @@
      */
     float satelliteElevation;
 
-    /** Antenna azimuth in degrees */
-    float mAntennaAzimuthDegrees;
+    /**
+     * Antenna azimuth in degrees.
+     */
+    float antennaAzimuth;
 
     /**
      * Angle of rotation about the x axis. This value represents the angle between a plane
      * parallel to the device's screen and a plane parallel to the ground.
      */
-    float mAntennaPitchDegrees;
+    float antennaPitch;
 
     /**
      * Angle of rotation about the y axis. This value represents the angle between a plane
      * perpendicular to the device's screen and a plane parallel to the ground.
      */
-    float mAntennaRollDegrees;
+    float antennaRoll;
 }
diff --git a/telephony/java/android/telephony/satellite/stub/SatelliteImplBase.java b/telephony/java/android/telephony/satellite/stub/SatelliteImplBase.java
index 4140939..df51432 100644
--- a/telephony/java/android/telephony/satellite/stub/SatelliteImplBase.java
+++ b/telephony/java/android/telephony/satellite/stub/SatelliteImplBase.java
@@ -16,7 +16,6 @@
 
 package android.telephony.satellite.stub;
 
-import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.os.IBinder;
 import android.os.RemoteException;
@@ -26,8 +25,6 @@
 import com.android.internal.telephony.IIntegerConsumer;
 import com.android.internal.telephony.util.TelephonyUtils;
 
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
 import java.util.concurrent.CancellationException;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.CompletionException;
@@ -42,53 +39,6 @@
 public class SatelliteImplBase extends SatelliteService {
     private static final String TAG = "SatelliteImplBase";
 
-    /** @hide */
-    @IntDef(prefix = "NT_RADIO_TECHNOLOGY_", value = {
-            NT_RADIO_TECHNOLOGY_NB_IOT_NTN,
-            NT_RADIO_TECHNOLOGY_NR_NTN,
-            NT_RADIO_TECHNOLOGY_EMTC_NTN,
-            NT_RADIO_TECHNOLOGY_PROPRIETARY
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface NTRadioTechnology {}
-
-    /** 3GPP NB-IoT (Narrowband Internet of Things) over Non-Terrestrial-Networks technology. */
-    public static final int NT_RADIO_TECHNOLOGY_NB_IOT_NTN =
-            android.telephony.satellite.stub.NTRadioTechnology.NB_IOT_NTN;
-    /** 3GPP 5G NR over Non-Terrestrial-Networks technology. */
-    public static final int NT_RADIO_TECHNOLOGY_NR_NTN =
-            android.telephony.satellite.stub.NTRadioTechnology.NR_NTN;
-    /** 3GPP eMTC (enhanced Machine-Type Communication) over Non-Terrestrial-Networks technology. */
-    public static final int NT_RADIO_TECHNOLOGY_EMTC_NTN =
-            android.telephony.satellite.stub.NTRadioTechnology.EMTC_NTN;
-    /** Proprietary technology. */
-    public static final int NT_RADIO_TECHNOLOGY_PROPRIETARY =
-            android.telephony.satellite.stub.NTRadioTechnology.PROPRIETARY;
-
-    /** @hide */
-    @IntDef(prefix = "SATELLITE_MODEM_STATE_", value = {
-            SATELLITE_MODEM_STATE_IDLE,
-            SATELLITE_MODEM_STATE_LISTENING,
-            SATELLITE_MODEM_STATE_MESSAGE_TRANSFERRING,
-            SATELLITE_MODEM_STATE_OFF
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface SatelliteModemState {}
-
-    /** Satellite modem is in idle state. */
-    public static final int SATELLITE_MODEM_STATE_IDLE =
-            android.telephony.satellite.stub.SatelliteModemState.SATELLITE_MODEM_STATE_IDLE;
-    /** Satellite modem is listening for incoming messages. */
-    public static final int SATELLITE_MODEM_STATE_LISTENING =
-            android.telephony.satellite.stub.SatelliteModemState.SATELLITE_MODEM_STATE_LISTENING;
-    /** Satellite modem is sending and/or receiving messages. */
-    public static final int SATELLITE_MODEM_STATE_MESSAGE_TRANSFERRING =
-            android.telephony.satellite.stub.SatelliteModemState
-                    .SATELLITE_MODEM_STATE_MESSAGE_TRANSFERRING;
-    /** Satellite modem is powered off. */
-    public static final int SATELLITE_MODEM_STATE_OFF =
-            android.telephony.satellite.stub.SatelliteModemState.SATELLITE_MODEM_STATE_OFF;
-
     protected final Executor mExecutor;
 
     /**
@@ -121,12 +71,12 @@
         }
 
         @Override
-        public void setSatelliteListeningEnabled(boolean enable, IIntegerConsumer errorCallback)
-                throws RemoteException {
+        public void requestSatelliteListeningEnabled(boolean enable, boolean isDemoMode,
+                IIntegerConsumer errorCallback) throws RemoteException {
             executeMethodAsync(
                     () -> SatelliteImplBase.this
-                            .setSatelliteListeningEnabled(enable, errorCallback),
-                    "setSatelliteListeningEnabled");
+                            .requestSatelliteListeningEnabled(enable, isDemoMode, errorCallback),
+                    "requestSatelliteListeningEnabled");
         }
 
         @Override
@@ -223,11 +173,12 @@
         }
 
         @Override
-        public void sendSatelliteDatagram(SatelliteDatagram datagram, boolean isEmergency,
-                IIntegerConsumer errorCallback) throws RemoteException {
+        public void sendSatelliteDatagram(SatelliteDatagram datagram, boolean isDemoMode,
+                boolean isEmergency, IIntegerConsumer errorCallback) throws RemoteException {
             executeMethodAsync(
                     () -> SatelliteImplBase.this
-                            .sendSatelliteDatagram(datagram, isEmergency, errorCallback),
+                            .sendSatelliteDatagram(
+                                    datagram, isDemoMode, isEmergency, errorCallback),
                     "sendSatelliteDatagram");
         }
 
@@ -296,10 +247,11 @@
     }
 
     /**
-     * Enable or disable the satellite service listening mode.
+     * Request to enable or disable the satellite service listening mode.
      * Listening mode allows the satellite service to listen for incoming pages.
      *
      * @param enable True to enable satellite listening mode and false to disable.
+     * @param isDemoMode Whether demo mode is enabled.
      * @param errorCallback The callback to receive the error code result of the operation.
      *
      * Valid error codes returned:
@@ -312,7 +264,7 @@
      *   SatelliteError:REQUEST_NOT_SUPPORTED
      *   SatelliteError:NO_RESOURCES
      */
-    public void setSatelliteListeningEnabled(boolean enable,
+    public void requestSatelliteListeningEnabled(boolean enable, boolean isDemoMode,
             @NonNull IIntegerConsumer errorCallback) {
         // stub implementation
     }
@@ -411,7 +363,7 @@
     /**
      * User started pointing to the satellite.
      * The satellite service should report the satellite pointing info via
-     * ISatelliteListener#onSatellitePointingInfoChanged as the user device/satellite moves.
+     * ISatelliteListener#onSatellitePositionChanged as the user device/satellite moves.
      *
      * @param errorCallback The callback to receive the error code result of the operation.
      *
@@ -549,8 +501,9 @@
     }
 
     /**
-     * Poll the pending datagrams.
-     * The satellite service should report the new datagrams via ISatelliteListener#onNewDatagrams.
+     * Poll the pending datagrams to be received over satellite.
+     * The satellite service should check if there are any pending datagrams to be received over
+     * satellite and report them via ISatelliteListener#onSatelliteDatagramsReceived.
      *
      * @param errorCallback The callback to receive the error code result of the operation.
      *
@@ -575,10 +528,9 @@
 
     /**
      * Send datagram over satellite.
-     * Once sent, the satellite service should report whether the operation was successful via
-     * SatelliteListener#onDatagramsDelivered.
      *
      * @param datagram Datagram to send in byte format.
+     * @param isDemoMode Whether demo mode is enabled.
      * @param isEmergency Whether this is an emergency datagram.
      * @param errorCallback The callback to receive the error code result of the operation.
      *
@@ -598,8 +550,8 @@
      *   SatelliteError:SATELLITE_NOT_REACHABLE
      *   SatelliteError:NOT_AUTHORIZED
      */
-    public void sendSatelliteDatagram(@NonNull SatelliteDatagram datagram, boolean isEmergency,
-            @NonNull IIntegerConsumer errorCallback) {
+    public void sendSatelliteDatagram(@NonNull SatelliteDatagram datagram, boolean isDemoMode,
+            boolean isEmergency, @NonNull IIntegerConsumer errorCallback) {
         // stub implementation
     }
 
diff --git a/telephony/java/android/telephony/satellite/stub/SatelliteModemState.aidl b/telephony/java/android/telephony/satellite/stub/SatelliteModemState.aidl
index 3f5ee56..5ee7f9a 100644
--- a/telephony/java/android/telephony/satellite/stub/SatelliteModemState.aidl
+++ b/telephony/java/android/telephony/satellite/stub/SatelliteModemState.aidl
@@ -21,12 +21,29 @@
  */
 @Backing(type="int")
 enum SatelliteModemState {
-    /* Satellite modem is in idle state. */
+    /**
+     * Satellite modem is in idle state.
+     */
     SATELLITE_MODEM_STATE_IDLE = 0,
-    /* Satellite modem is listening for incoming messages. */
+    /**
+     * Satellite modem is listening for incoming datagrams.
+     */
     SATELLITE_MODEM_STATE_LISTENING = 1,
-    /* Satellite modem is sending and/or receiving messages. */
-    SATELLITE_MODEM_STATE_MESSAGE_TRANSFERRING = 2,
-    /* Satellite modem is powered off. */
-    SATELLITE_MODEM_STATE_OFF = 3,
+    /**
+     * Satellite modem is sending and/or receiving datagrams.
+     */
+    SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING = 2,
+    /**
+     * Satellite modem is retrying to send and/or receive datagrams.
+     */
+    SATELLITE_MODEM_STATE_DATAGRAM_RETRYING = 3,
+    /**
+     * Satellite modem is powered off.
+     */
+    SATELLITE_MODEM_STATE_OFF = 4,
+    /**
+     * Satellite modem state is unknown. This generic modem state should be used only when the
+     * modem state cannot be mapped to other specific modem states.
+     */
+    SATELLITE_MODEM_STATE_UNKNOWN = -1,
 }
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 5bf55ef..f4801c2 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -2728,6 +2728,29 @@
     void requestIsSatelliteEnabled(int subId, in ResultReceiver receiver);
 
     /**
+     * Request to enable or disable the satellite service demo mode.
+     *
+     * @param subId The subId of the subscription to enable or disable the satellite demo mode for.
+     * @param enable True to enable the satellite demo mode and false to disable.
+     * @param callback The callback to get the error code of the request.
+     */
+    @JavaPassthrough(annotation="@android.annotation.RequiresPermission("
+            + "android.Manifest.permission.SATELLITE_COMMUNICATION)")
+    void requestSatelliteDemoModeEnabled(int subId, boolean enable, in IIntegerConsumer callback);
+
+    /**
+     * Request to get whether the satellite service demo mode is enabled.
+     *
+     * @param subId The subId of the subscription to request whether the satellite demo mode is
+     *              enabled for.
+     * @param receiver Result receiver to get the error code of the request and whether the
+     *                 satellite demo mode is enabled.
+     */
+    @JavaPassthrough(annotation="@android.annotation.RequiresPermission("
+            + "android.Manifest.permission.SATELLITE_COMMUNICATION)")
+    void requestIsSatelliteDemoModeEnabled(int subId, in ResultReceiver receiver);
+
+    /**
      * Request to get whether the satellite service is supported on the device.
      *
      * @param subId The subId of the subscription to check whether satellite is supported for.
@@ -2815,9 +2838,9 @@
 
 
     /**
-     * Register for the satellite provision state change.
+     * Registers for provision state changed from satellite modem.
      *
-     * @param subId The subId of the subscription to register for provision state changes.
+     * @param subId The subId of the subscription to register for provision state changed.
      * @param callback The callback to handle the satellite provision state changed event.
      *
      * @return The {@link SatelliteError} result of the operation.
@@ -2828,10 +2851,10 @@
             in ISatelliteProvisionStateCallback callback);
 
     /**
-     * Unregister for the satellite provision state change.
+     * Unregisters for provision state changed from satellite modem.
      * If callback was not registered before, the request will be ignored.
      *
-     * @param subId The subId of the subscription to unregister for provision state changes.
+     * @param subId The subId of the subscription to unregister for provision state changed.
      * @param callback The callback that was passed to registerForSatelliteProvisionStateChanged.
      */
     @JavaPassthrough(annotation="@android.annotation.RequiresPermission("
@@ -2851,27 +2874,27 @@
     void requestIsSatelliteProvisioned(int subId, in ResultReceiver receiver);
 
     /**
-     * Register for listening to satellite modem state changes.
+     * Registers for modem state changed from satellite modem.
      *
-     * @param subId The subId of the subscription to register for satellite modem state changes.
+     * @param subId The subId of the subscription to register for satellite modem state changed.
      * @param callback The callback to handle the satellite modem state changed event.
      *
      * @return The {@link SatelliteError} result of the operation.
      */
     @JavaPassthrough(annotation="@android.annotation.RequiresPermission("
             + "android.Manifest.permission.SATELLITE_COMMUNICATION)")
-    int registerForSatelliteModemStateChange(int subId, ISatelliteStateCallback callback);
+    int registerForSatelliteModemStateChanged(int subId, ISatelliteStateCallback callback);
 
     /**
-     * Unregister to stop listening to satellite modem state changes.
+     * Unregisters for modem state changed from satellite modem.
      * If callback was not registered before, the request will be ignored.
      *
-     * @param subId The subId of the subscription to unregister for satellite modem state changes.
-     * @param callback The callback that was passed to registerForSatelliteStateChange.
+     * @param subId The subId of the subscription to unregister for satellite modem state changed.
+     * @param callback The callback that was passed to registerForSatelliteStateChanged.
      */
     @JavaPassthrough(annotation="@android.annotation.RequiresPermission("
             + "android.Manifest.permission.SATELLITE_COMMUNICATION)")
-    void unregisterForSatelliteModemStateChange(int subId, ISatelliteStateCallback callback);
+    void unregisterForSatelliteModemStateChanged(int subId, ISatelliteStateCallback callback);
 
    /**
      * Register to receive incoming datagrams over satellite.