Merge "dynsystem: Fix memory leak"
diff --git a/Android.bp b/Android.bp
index 8c5a855..ceb35bd 100644
--- a/Android.bp
+++ b/Android.bp
@@ -65,7 +65,6 @@
         // Java/AIDL sources under frameworks/base
         ":framework-annotations",
         ":framework-blobstore-sources",
-        ":framework-connectivity-tiramisu-sources",
         ":framework-core-sources",
         ":framework-drm-sources",
         ":framework-graphics-nonupdatable-sources",
diff --git a/apct-tests/perftests/core/src/android/libcore/AdditionPerfTest.java b/apct-tests/perftests/core/src/android/libcore/AdditionPerfTest.java
new file mode 100644
index 0000000..aa47e0a
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/libcore/AdditionPerfTest.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.libcore;
+
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.test.suitebuilder.annotation.LargeTest;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * What do various kinds of addition cost?
+ */
+@RunWith(AndroidJUnit4.class)
+@LargeTest
+public class AdditionPerfTest {
+
+    @Rule
+    public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+    @Test
+    public void timeAddConstantToLocalInt() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        int result = 0;
+        while (state.keepRunning()) {
+            result += 123;
+        }
+    }
+    @Test
+    public void timeAddTwoLocalInts() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        int result = 0;
+        int constant = 123;
+        while (state.keepRunning()) {
+            result += constant;
+        }
+    }
+    @Test
+    public void timeAddConstantToLocalLong() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        long result = 0;
+        while (state.keepRunning()) {
+            result += 123L;
+        }
+    }
+    @Test
+    public void timeAddTwoLocalLongs() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        long result = 0;
+        long constant = 123L;
+        while (state.keepRunning()) {
+            result += constant;
+        }
+    }
+    @Test
+    public void timeAddConstantToLocalFloat() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        float result = 0.0f;
+        while (state.keepRunning()) {
+            result += 123.0f;
+        }
+    }
+    @Test
+    public void timeAddTwoLocalFloats() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        float result = 0.0f;
+        float constant = 123.0f;
+        while (state.keepRunning()) {
+            result += constant;
+        }
+    }
+    @Test
+    public void timeAddConstantToLocalDouble() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        double result = 0.0;
+        while (state.keepRunning()) {
+            result += 123.0;
+        }
+    }
+    @Test
+    public void timeAddTwoLocalDoubles() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        double result = 0.0;
+        double constant = 123.0;
+        while (state.keepRunning()) {
+            result += constant;
+        }
+    }
+}
diff --git a/apct-tests/perftests/core/src/android/libcore/ArrayCopyPerfTest.java b/apct-tests/perftests/core/src/android/libcore/ArrayCopyPerfTest.java
new file mode 100644
index 0000000..97ab6c7
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/libcore/ArrayCopyPerfTest.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.libcore;
+
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.test.suitebuilder.annotation.LargeTest;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Arrays;
+
+@RunWith(AndroidJUnit4.class)
+@LargeTest
+public class ArrayCopyPerfTest {
+
+    @Rule
+    public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+    @Test
+    public void timeManualArrayCopy() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        char[] src = new char[8192];
+        while (state.keepRunning()) {
+            char[] dst = new char[8192];
+            for (int i = 0; i < 8192; ++i) {
+                dst[i] = src[i];
+            }
+        }
+    }
+
+    @Test
+    public void time_System_arrayCopy() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        char[] src = new char[8192];
+        while (state.keepRunning()) {
+            char[] dst = new char[8192];
+            System.arraycopy(src, 0, dst, 0, 8192);
+        }
+    }
+
+    @Test
+    public void time_Arrays_copyOf() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        char[] src = new char[8192];
+        while (state.keepRunning()) {
+            char[] dst = Arrays.copyOf(src, 8192);
+        }
+    }
+
+    @Test
+    public void time_Arrays_copyOfRange() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        char[] src = new char[8192];
+        while (state.keepRunning()) {
+            char[] dst = Arrays.copyOfRange(src, 0, 8192);
+        }
+    }
+}
diff --git a/apct-tests/perftests/core/src/android/libcore/ArrayIterationPerfTest.java b/apct-tests/perftests/core/src/android/libcore/ArrayIterationPerfTest.java
new file mode 100644
index 0000000..bb452d3
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/libcore/ArrayIterationPerfTest.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.libcore;
+
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.test.suitebuilder.annotation.LargeTest;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * How do various ways of iterating through an array compare?
+ */
+@RunWith(AndroidJUnit4.class)
+@LargeTest
+public class ArrayIterationPerfTest {
+
+    public class Foo {
+        int mSplat;
+    }
+
+    @Rule
+    public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+    Foo[] mArray = new Foo[27];
+    {
+        for (int i = 0; i < mArray.length; ++i) mArray[i] = new Foo();
+    }
+    @Test
+    public void timeArrayIteration() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            int sum = 0;
+            for (int i = 0; i < mArray.length; i++) {
+                sum += mArray[i].mSplat;
+            }
+        }
+    }
+    @Test
+    public void timeArrayIterationCached() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            int sum = 0;
+            Foo[] localArray = mArray;
+            int len = localArray.length;
+
+            for (int i = 0; i < len; i++) {
+                sum += localArray[i].mSplat;
+            }
+        }
+    }
+    @Test
+    public void timeArrayIterationForEach() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            int sum = 0;
+            for (Foo a: mArray) {
+                sum += a.mSplat;
+            }
+        }
+    }
+}
diff --git a/apct-tests/perftests/core/src/android/libcore/ArrayListIterationPerfTest.java b/apct-tests/perftests/core/src/android/libcore/ArrayListIterationPerfTest.java
new file mode 100644
index 0000000..ff6d46f
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/libcore/ArrayListIterationPerfTest.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.libcore;
+
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.test.suitebuilder.annotation.LargeTest;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+
+/**
+ * Is a hand-coded counted loop through an ArrayList cheaper than enhanced for?
+ */
+@RunWith(AndroidJUnit4.class)
+@LargeTest
+public class ArrayListIterationPerfTest {
+
+    public class Foo {
+        int mSplat;
+    }
+    @Rule
+    public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+    ArrayList<Foo> mList = new ArrayList<Foo>();
+    {
+        for (int i = 0; i < 27; ++i) mList.add(new Foo());
+    }
+    @Test
+    public void timeArrayListIterationIndexed() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            int sum = 0;
+            ArrayList<Foo> list = mList;
+            int len = list.size();
+            for (int i = 0; i < len; ++i) {
+                sum += list.get(i).mSplat;
+            }
+        }
+    }
+    @Test
+    public void timeArrayListIterationForEach() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            int sum = 0;
+            for (Foo a : mList) {
+                sum += a.mSplat;
+            }
+        }
+    }
+}
diff --git a/apct-tests/perftests/core/src/android/libcore/OWNERS b/apct-tests/perftests/core/src/android/libcore/OWNERS
new file mode 100644
index 0000000..2d36574
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/libcore/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 24949
+include platform/libcore:/OWNERS
diff --git a/api/api.go b/api/api.go
index 5e5f60e..9cd0132 100644
--- a/api/api.go
+++ b/api/api.go
@@ -27,6 +27,7 @@
 const art = "art.module.public.api"
 const conscrypt = "conscrypt.module.public.api"
 const i18n = "i18n.module.public.api"
+
 var core_libraries_modules = []string{art, conscrypt, i18n}
 
 // The intention behind this soong plugin is to generate a number of "merged"
@@ -92,6 +93,8 @@
 type MergedTxtDefinition struct {
 	// "current.txt" or "removed.txt"
 	TxtFilename string
+	// Filename in the new dist dir. "android.txt" or "android-removed.txt"
+	DistFilename string
 	// The module for the non-updatable / non-module part of the api.
 	BaseTxt string
 	// The list of modules that are relevant for this merged txt.
@@ -112,7 +115,6 @@
 	if txt.Scope != "public" {
 		filename = txt.Scope + "-" + filename
 	}
-
 	props := genruleProps{}
 	props.Name = proptools.StringPtr(ctx.ModuleName() + "-" + filename)
 	props.Tools = []string{"metalava"}
@@ -126,9 +128,9 @@
 			Dest:    proptools.StringPtr(filename),
 		},
 		{
-			Targets: []string{"sdk"},
+			Targets: []string{"api_txt", "sdk"},
 			Dir:     proptools.StringPtr("apistubs/android/" + txt.Scope + "/api"),
-			Dest:    proptools.StringPtr(txt.TxtFilename),
+			Dest:    proptools.StringPtr(txt.DistFilename),
 		},
 	}
 	props.Visibility = []string{"//visibility:public"}
@@ -242,34 +244,39 @@
 	var textFiles []MergedTxtDefinition
 
 	tagSuffix := []string{".api.txt}", ".removed-api.txt}"}
+	distFilename := []string{"android.txt", "android-removed.txt"}
 	for i, f := range []string{"current.txt", "removed.txt"} {
 		textFiles = append(textFiles, MergedTxtDefinition{
-			TxtFilename: f,
-			BaseTxt:     ":non-updatable-" + f,
-			Modules:     bootclasspath,
-			ModuleTag:   "{.public" + tagSuffix[i],
-			Scope:       "public",
+			TxtFilename:  f,
+			DistFilename: distFilename[i],
+			BaseTxt:      ":non-updatable-" + f,
+			Modules:      bootclasspath,
+			ModuleTag:    "{.public" + tagSuffix[i],
+			Scope:        "public",
 		})
 		textFiles = append(textFiles, MergedTxtDefinition{
-			TxtFilename: f,
-			BaseTxt:     ":non-updatable-system-" + f,
-			Modules:     bootclasspath,
-			ModuleTag:   "{.system" + tagSuffix[i],
-			Scope:       "system",
+			TxtFilename:  f,
+			DistFilename: distFilename[i],
+			BaseTxt:      ":non-updatable-system-" + f,
+			Modules:      bootclasspath,
+			ModuleTag:    "{.system" + tagSuffix[i],
+			Scope:        "system",
 		})
 		textFiles = append(textFiles, MergedTxtDefinition{
-			TxtFilename: f,
-			BaseTxt:     ":non-updatable-module-lib-" + f,
-			Modules:     bootclasspath,
-			ModuleTag:   "{.module-lib" + tagSuffix[i],
-			Scope:       "module-lib",
+			TxtFilename:  f,
+			DistFilename: distFilename[i],
+			BaseTxt:      ":non-updatable-module-lib-" + f,
+			Modules:      bootclasspath,
+			ModuleTag:    "{.module-lib" + tagSuffix[i],
+			Scope:        "module-lib",
 		})
 		textFiles = append(textFiles, MergedTxtDefinition{
-			TxtFilename: f,
-			BaseTxt:     ":non-updatable-system-server-" + f,
-			Modules:     system_server_classpath,
-			ModuleTag:   "{.system-server" + tagSuffix[i],
-			Scope:       "system-server",
+			TxtFilename:  f,
+			DistFilename: distFilename[i],
+			BaseTxt:      ":non-updatable-system-server-" + f,
+			Modules:      system_server_classpath,
+			ModuleTag:    "{.system-server" + tagSuffix[i],
+			Scope:        "system-server",
 		})
 	}
 	for _, txt := range textFiles {
diff --git a/cmds/telecom/src/com/android/commands/telecom/Telecom.java b/cmds/telecom/src/com/android/commands/telecom/Telecom.java
index 9c044b5..8b9ab4c 100644
--- a/cmds/telecom/src/com/android/commands/telecom/Telecom.java
+++ b/cmds/telecom/src/com/android/commands/telecom/Telecom.java
@@ -37,6 +37,8 @@
 import com.android.internal.telecom.ITelecomService;
 
 import java.io.PrintStream;
+import java.util.Arrays;
+import java.util.stream.Collectors;
 
 public final class Telecom extends BaseCommand {
 
@@ -88,6 +90,10 @@
     private static final String COMMAND_GET_MAX_PHONES = "get-max-phones";
     private static final String COMMAND_SET_TEST_EMERGENCY_PHONE_ACCOUNT_PACKAGE_FILTER =
             "set-test-emergency-phone-account-package-filter";
+    /**
+     * Command used to emit a distinct "mark" in the logs.
+     */
+    private static final String COMMAND_LOG_MARK = "log-mark";
 
     private ComponentName mComponent;
     private String mAccountId;
@@ -156,6 +162,8 @@
                         + " package name that will be used for test emergency calls. To clear,"
                         + " send an empty package name. Real emergency calls will still be placed"
                         + " over Telephony.\n"
+                + "telecom log-mark <MESSAGE>: emits a message into the telecom logs.  Useful for "
+                        + "testers to indicate where in the logs various test steps take place.\n"
         );
     }
 
@@ -257,6 +265,9 @@
             case COMMAND_SET_TEST_EMERGENCY_PHONE_ACCOUNT_PACKAGE_FILTER:
                 runSetEmergencyPhoneAccountPackageFilter();
                 break;
+            case COMMAND_LOG_MARK:
+                runLogMark();
+                break;
             default:
                 Log.w(this, "onRun: unknown command: %s", command);
                 throw new IllegalArgumentException ("unknown command '" + command + "'");
@@ -429,6 +440,11 @@
 
     }
 
+    private void runLogMark() throws RemoteException {
+        String message = Arrays.stream(mArgs.peekRemainingArgs()).collect(Collectors.joining(" "));
+        mTelecomService.requestLogMark(message);
+    }
+
     private PhoneAccountHandle getPhoneAccountHandleFromArgs() throws RemoteException {
         if (TextUtils.isEmpty(mArgs.peekNextArg())) {
             return null;
diff --git a/core/api/current.txt b/core/api/current.txt
index 8f74ae1..641b1a3 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -36138,10 +36138,12 @@
 
   public class KeyStoreException extends java.lang.Exception {
     method public int getNumericErrorCode();
+    method public int getRetryPolicy();
     method public boolean isSystemError();
     method public boolean isTransientFailure();
     method public boolean requiresUserAuthentication();
     field public static final int ERROR_ATTESTATION_CHALLENGE_TOO_LARGE = 9; // 0x9
+    field public static final int ERROR_ATTESTATION_KEYS_UNAVAILABLE = 16; // 0x10
     field public static final int ERROR_ID_ATTESTATION_FAILURE = 8; // 0x8
     field public static final int ERROR_INCORRECT_USAGE = 13; // 0xd
     field public static final int ERROR_INTERNAL_SYSTEM_ERROR = 4; // 0x4
@@ -36156,6 +36158,9 @@
     field public static final int ERROR_PERMISSION_DENIED = 5; // 0x5
     field public static final int ERROR_UNIMPLEMENTED = 12; // 0xc
     field public static final int ERROR_USER_AUTHENTICATION_REQUIRED = 2; // 0x2
+    field public static final int RETRY_NEVER = 1; // 0x1
+    field public static final int RETRY_WHEN_CONNECTIVITY_AVAILABLE = 3; // 0x3
+    field public static final int RETRY_WITH_EXPONENTIAL_BACKOFF = 2; // 0x2
   }
 
   @Deprecated public final class KeyStoreParameter implements java.security.KeyStore.ProtectionParameter {
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 6b588f9..d7c7bb1 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -34,6 +34,7 @@
     field public static final String READ_PRIVILEGED_PHONE_STATE = "android.permission.READ_PRIVILEGED_PHONE_STATE";
     field public static final String RECORD_BACKGROUND_AUDIO = "android.permission.RECORD_BACKGROUND_AUDIO";
     field public static final String REMOVE_TASKS = "android.permission.REMOVE_TASKS";
+    field public static final String REQUEST_UNIQUE_ID_ATTESTATION = "android.permission.REQUEST_UNIQUE_ID_ATTESTATION";
     field public static final String RESET_APP_ERRORS = "android.permission.RESET_APP_ERRORS";
     field public static final String SET_AND_VERIFY_LOCKSCREEN_CREDENTIALS = "android.permission.SET_AND_VERIFY_LOCKSCREEN_CREDENTIALS";
     field public static final String START_TASKS_FROM_RECENTS = "android.permission.START_TASKS_FROM_RECENTS";
@@ -682,6 +683,7 @@
     ctor public AttributionSource(int, @Nullable String, @Nullable String);
     ctor public AttributionSource(int, @Nullable String, @Nullable String, @NonNull android.os.IBinder);
     ctor public AttributionSource(int, @Nullable String, @Nullable String, @Nullable java.util.Set<java.lang.String>, @Nullable android.content.AttributionSource);
+    method public void enforceCallingPid();
   }
 
   public final class AutofillOptions implements android.os.Parcelable {
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 2c02be7..c3be18e 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -622,6 +622,9 @@
      * Bit to be bitwise-ored into the {@link #flags} field that should be
      * set if you would only like the sound, vibrate and ticker to be played
      * if the notification was not already showing.
+     *
+     * Note that using this flag will stop any ongoing alerting behaviour such
+     * as sound, vibration or blinking notification LED.
      */
     public static final int FLAG_ONLY_ALERT_ONCE    = 0x00000008;
 
@@ -4601,6 +4604,9 @@
          * Set this flag if you would only like the sound, vibrate
          * and ticker to be played if the notification is not already showing.
          *
+         * Note that using this flag will stop any ongoing alerting behaviour such
+         * as sound, vibration or blinking notification LED.
+         *
          * @see Notification#FLAG_ONLY_ALERT_ONCE
          */
         @NonNull
diff --git a/core/java/android/content/AttributionSource.java b/core/java/android/content/AttributionSource.java
index 157e709..3f2fa21 100644
--- a/core/java/android/content/AttributionSource.java
+++ b/core/java/android/content/AttributionSource.java
@@ -155,8 +155,8 @@
         this(AttributionSourceState.CREATOR.createFromParcel(in));
 
         // Since we just unpacked this object as part of it transiting a Binder
-        // call, this is the perfect time to enforce that its UID can be trusted
-        enforceCallingUid();
+        // call, this is the perfect time to enforce that its UID and PID can be trusted
+        enforceCallingUidAndPid();
     }
 
     /** @hide */
@@ -259,13 +259,24 @@
     }
 
     /**
+     * If you are handling an IPC and you don't trust the caller you need to validate whether the
+     * attribution source is one for the calling app to prevent the caller to pass you a source from
+     * another app without including themselves in the attribution chain.
+     *
+     * @throws SecurityException if the attribution source cannot be trusted to be from the caller.
+     */
+    private void enforceCallingUidAndPid() {
+        enforceCallingUid();
+        enforceCallingPid();
+    }
+
+    /**
      * If you are handling an IPC and you don't trust the caller you need to validate
      * whether the attribution source is one for the calling app to prevent the caller
      * to pass you a source from another app without including themselves in the
      * attribution chain.
      *
-     * @throws SecurityException if the attribution source cannot be trusted to be
-     * from the caller.
+     * @throws SecurityException if the attribution source cannot be trusted to be from the caller.
      */
     public void enforceCallingUid() {
         if (!checkCallingUid()) {
@@ -294,6 +305,33 @@
         return true;
     }
 
+    /**
+     * Validate that the pid being claimed for the calling app is not spoofed
+     *
+     * @throws SecurityException if the attribution source cannot be trusted to be from the caller.
+     * @hide
+     */
+    @TestApi
+    public void enforceCallingPid() {
+        if (!checkCallingPid()) {
+            throw new SecurityException("Calling pid: " + Binder.getCallingPid()
+                    + " doesn't match source pid: " + mAttributionSourceState.pid);
+        }
+    }
+
+    /**
+     * Validate that the pid being claimed for the calling app is not spoofed
+     *
+     * @return if the attribution source cannot be trusted to be from the caller.
+     */
+    private boolean checkCallingPid() {
+        final int callingPid = Binder.getCallingPid();
+        if (mAttributionSourceState.pid != -1 && callingPid != mAttributionSourceState.pid) {
+            return false;
+        }
+        return true;
+    }
+
     @Override
     public String toString() {
         if (Build.IS_DEBUGGABLE) {
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index a8a5837..0f9acad 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -739,7 +739,7 @@
      * {@link #startMainActivity(ComponentName, UserHandle, Rect, Bundle)}.
      *
      * @param component The ComponentName of the activity to launch
-     * @param startActivityOptions Options to pass to startActivity
+     * @param startActivityOptions This parameter is no longer supported
      * @param user The UserHandle of the profile
      * @hide
      */
@@ -751,7 +751,8 @@
             Log.i(TAG, "GetMainActivityLaunchIntent " + component + " " + user);
         }
         try {
-            return mService.getActivityLaunchIntent(component, startActivityOptions, user);
+            // due to b/209607104, startActivityOptions will be ignored
+            return mService.getActivityLaunchIntent(component, null /* opts */, user);
         } catch (RemoteException re) {
             throw re.rethrowFromSystemServer();
         }
@@ -846,7 +847,7 @@
      *
      * @param packageName The packageName of the shortcut
      * @param shortcutId The id of the shortcut
-     * @param opts Options to pass to the PendingIntent
+     * @param opts This parameter is no longer supported
      * @param user The UserHandle of the profile
      */
     @Nullable
@@ -858,8 +859,9 @@
             Log.i(TAG, "GetShortcutIntent " + packageName + "/" + shortcutId + " " + user);
         }
         try {
+            // due to b/209607104, opts will be ignored
             return mService.getShortcutIntent(
-                    mContext.getPackageName(), packageName, shortcutId, opts, user);
+                    mContext.getPackageName(), packageName, shortcutId, null /* opts */, user);
         } catch (RemoteException re) {
             throw re.rethrowFromSystemServer();
         }
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index 755114e..bd6fcd8 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -751,11 +751,25 @@
     public static final int SCREEN_WIDTH_DP_UNDEFINED = 0;
 
     /**
-     * The current width of the available screen space, in dp units,
-     * corresponding to
-     * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenWidthQualifier">screen
-     * width</a> resource qualifier.  Set to
+     * The current width of the available screen space in dp units, excluding
+     * the area occupied by screen decorations at the edges of the display.
+     * Corresponds to the
+     * <a href="{@docRoot}guide/topics/resources/providing-resources.html#AvailableWidthHeightQualifier">
+     * available width</a> resource qualifier. Defaults to
      * {@link #SCREEN_WIDTH_DP_UNDEFINED} if no width is specified.
+     *
+     * <p>In multi-window mode, equals the width of the available display area
+     * of the app window, not the available display area of the device screen
+     * (for example, when apps are displayed side by side in split-screen mode
+     * in landscape orientation).
+     *
+     * <p>Differs from {@link android.view.WindowMetrics} by not including
+     * screen decorations in the width measurement and by expressing the
+     * measurement in dp rather than px. Use {@code screenWidthDp} to obtain the
+     * horizontal display area available to the app, excluding the area occupied
+     * by screen decorations. Use {@link android.view.WindowMetrics#getBounds()}
+     * to obtain the width of the display area available to the app, including
+     * the area occupied by screen decorations.
      */
     public int screenWidthDp;
 
@@ -766,11 +780,26 @@
     public static final int SCREEN_HEIGHT_DP_UNDEFINED = 0;
 
     /**
-     * The current height of the available screen space, in dp units,
-     * corresponding to
-     * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenHeightQualifier">screen
-     * height</a> resource qualifier.  Set to
+     * The current height of the available screen space in dp units, excluding
+     * the area occupied by screen decorations at the edges of the display (such
+     * as the status bar, navigation bar, and cutouts). Corresponds to the
+     * <a href="{@docRoot}guide/topics/resources/providing-resources.html#AvailableWidthHeightQualifier">
+     * available height</a> resource qualifier. Defaults to
      * {@link #SCREEN_HEIGHT_DP_UNDEFINED} if no height is specified.
+     *
+     * <p>In multi-window mode, equals the height of the available display area
+     * of the app window, not the available display area of the device screen
+     * (for example, when apps are displayed one above another in split-screen
+     * mode in portrait orientation).
+     *
+     * <p>Differs from {@link android.view.WindowMetrics} by not including
+     * screen decorations in the height measurement and by expressing the
+     * measurement in dp rather than px. Use {@code screenHeightDp} to obtain
+     * the vertical display area available to the app, excluding the area
+     * occupied by screen decorations. Use
+     * {@link android.view.WindowMetrics#getBounds()} to obtain the height of
+     * the display area available to the app, including the area occupied by
+     * screen decorations.
      */
     public int screenHeightDp;
 
diff --git a/core/java/android/debug/AdbManager.java b/core/java/android/debug/AdbManager.java
index 7714dd8..243f801 100644
--- a/core/java/android/debug/AdbManager.java
+++ b/core/java/android/debug/AdbManager.java
@@ -38,6 +38,7 @@
      *
      * @hide
      */
+    @RequiresPermission(android.Manifest.permission.MANAGE_DEBUGGING)
     public static final String WIRELESS_DEBUG_STATE_CHANGED_ACTION =
             "com.android.server.adb.WIRELESS_DEBUG_STATUS";
 
@@ -46,6 +47,7 @@
      *
      * @hide
      */
+    @RequiresPermission(android.Manifest.permission.MANAGE_DEBUGGING)
     public static final String WIRELESS_DEBUG_PAIRED_DEVICES_ACTION =
             "com.android.server.adb.WIRELESS_DEBUG_PAIRED_DEVICES";
 
@@ -59,6 +61,7 @@
      *
      * @hide
      */
+    @RequiresPermission(android.Manifest.permission.MANAGE_DEBUGGING)
     public static final String WIRELESS_DEBUG_PAIRING_RESULT_ACTION =
             "com.android.server.adb.WIRELESS_DEBUG_PAIRING_RESULT";
 
diff --git a/core/java/android/hardware/hdmi/IHdmiDeviceEventListener.aidl b/core/java/android/hardware/hdmi/IHdmiDeviceEventListener.aidl
index 69f2911..b2ddef9 100644
--- a/core/java/android/hardware/hdmi/IHdmiDeviceEventListener.aidl
+++ b/core/java/android/hardware/hdmi/IHdmiDeviceEventListener.aidl
@@ -22,6 +22,8 @@
  * Callback interface definition for HDMI client to get informed of
  * the CEC logical device status change event.
  *
+ * Only to be used on TV panel and Audio System devices (b/226317598).
+ *
  * @hide
  */
 oneway interface IHdmiDeviceEventListener {
diff --git a/core/java/android/net/Ikev2VpnProfile.java b/core/java/android/net/Ikev2VpnProfile.java
index 3abe83b..ba0546a 100644
--- a/core/java/android/net/Ikev2VpnProfile.java
+++ b/core/java/android/net/Ikev2VpnProfile.java
@@ -25,12 +25,6 @@
 import static android.net.IpSecAlgorithm.AUTH_HMAC_SHA512;
 import static android.net.IpSecAlgorithm.CRYPT_AES_CBC;
 import static android.net.IpSecAlgorithm.CRYPT_AES_CTR;
-import static android.net.eap.EapSessionConfig.EapMsChapV2Config;
-import static android.net.ipsec.ike.IkeSessionParams.IkeAuthConfig;
-import static android.net.ipsec.ike.IkeSessionParams.IkeAuthDigitalSignLocalConfig;
-import static android.net.ipsec.ike.IkeSessionParams.IkeAuthDigitalSignRemoteConfig;
-import static android.net.ipsec.ike.IkeSessionParams.IkeAuthEapConfig;
-import static android.net.ipsec.ike.IkeSessionParams.IkeAuthPskConfig;
 
 import static com.android.internal.annotations.VisibleForTesting.Visibility;
 import static com.android.internal.util.Preconditions.checkStringNotEmpty;
@@ -40,6 +34,7 @@
 import android.annotation.Nullable;
 import android.annotation.RequiresFeature;
 import android.content.pm.PackageManager;
+import android.net.ipsec.ike.IkeDerAsn1DnIdentification;
 import android.net.ipsec.ike.IkeFqdnIdentification;
 import android.net.ipsec.ike.IkeIdentification;
 import android.net.ipsec.ike.IkeIpv4AddrIdentification;
@@ -119,8 +114,8 @@
         DEFAULT_ALGORITHMS = Collections.unmodifiableList(algorithms);
     }
 
-    @NonNull private final String mServerAddr;
-    @NonNull private final String mUserIdentity;
+    @Nullable private final String mServerAddr;
+    @Nullable private final String mUserIdentity;
 
     // PSK authentication
     @Nullable private final byte[] mPresharedKey;
@@ -146,8 +141,8 @@
 
     private Ikev2VpnProfile(
             int type,
-            @NonNull String serverAddr,
-            @NonNull String userIdentity,
+            @Nullable String serverAddr,
+            @Nullable String userIdentity,
             @Nullable byte[] presharedKey,
             @Nullable X509Certificate serverRootCaCert,
             @Nullable String username,
@@ -165,8 +160,6 @@
             @Nullable IkeTunnelConnectionParams ikeTunConnParams) {
         super(type, excludeLocalRoutes, requiresInternetValidation);
 
-        checkNotNull(serverAddr, MISSING_PARAM_MSG_TMPL, "Server address");
-        checkNotNull(userIdentity, MISSING_PARAM_MSG_TMPL, "User Identity");
         checkNotNull(allowedAlgorithms, MISSING_PARAM_MSG_TMPL, "Allowed Algorithms");
 
         mServerAddr = serverAddr;
@@ -191,18 +184,12 @@
         mIsMetered = isMetered;
         mMaxMtu = maxMtu;
         mIsRestrictedToTestNetworks = restrictToTestNetworks;
-
         mIkeTunConnParams = ikeTunConnParams;
 
         validate();
     }
 
     private void validate() {
-        // Server Address not validated except to check an address was provided. This allows for
-        // dual-stack servers and hostname based addresses.
-        checkStringNotEmpty(mServerAddr, MISSING_PARAM_MSG_TMPL, "Server Address");
-        checkStringNotEmpty(mUserIdentity, MISSING_PARAM_MSG_TMPL, "User Identity");
-
         // IPv6 MTU is greater; since profiles may be started by the system on IPv4 and IPv6
         // networks, the VPN must provide a link fulfilling the stricter of the two conditions
         // (at least that of the IPv6 MTU).
@@ -210,6 +197,15 @@
             throw new IllegalArgumentException("Max MTU must be at least" + IPV6_MIN_MTU);
         }
 
+        // Skip validating the other fields if mIkeTunConnParams is set because the required
+        // information should all come from the mIkeTunConnParams.
+        if (mIkeTunConnParams != null) return;
+
+        // Server Address not validated except to check an address was provided. This allows for
+        // dual-stack servers and hostname based addresses.
+        checkStringNotEmpty(mServerAddr, MISSING_PARAM_MSG_TMPL, "Server Address");
+        checkStringNotEmpty(mUserIdentity, MISSING_PARAM_MSG_TMPL, "User Identity");
+
         switch (mType) {
             case TYPE_IKEV2_IPSEC_USER_PASS:
                 checkNotNull(mUsername, MISSING_PARAM_MSG_TMPL, "Username");
@@ -286,22 +282,31 @@
     /** Retrieves the server address string. */
     @NonNull
     public String getServerAddr() {
-        return mServerAddr;
+        if (mIkeTunConnParams == null) return mServerAddr;
+
+        final IkeSessionParams ikeSessionParams = mIkeTunConnParams.getIkeSessionParams();
+        return ikeSessionParams.getServerHostname();
     }
 
     /** Retrieves the user identity. */
     @NonNull
     public String getUserIdentity() {
-        return mUserIdentity;
+        if (mIkeTunConnParams == null) return mUserIdentity;
+
+        final IkeSessionParams ikeSessionParams = mIkeTunConnParams.getIkeSessionParams();
+        return getUserIdentityFromIkeSession(ikeSessionParams);
     }
 
     /**
      * Retrieves the pre-shared key.
      *
-     * <p>May be null if the profile is not using Pre-shared key authentication.
+     * <p>May be null if the profile is not using Pre-shared key authentication, or the profile is
+     * built from an {@link IkeTunnelConnectionParams}.
      */
     @Nullable
     public byte[] getPresharedKey() {
+        if (mIkeTunConnParams != null) return null;
+
         return mPresharedKey == null ? null : Arrays.copyOf(mPresharedKey, mPresharedKey.length);
     }
 
@@ -309,46 +314,62 @@
      * Retrieves the certificate for the server's root CA.
      *
      * <p>May be null if the profile is not using RSA Digital Signature Authentication or
-     * Username/Password authentication
+     * Username/Password authentication, or the profile is built from an
+     * {@link IkeTunnelConnectionParams}.
      */
     @Nullable
     public X509Certificate getServerRootCaCert() {
+        if (mIkeTunConnParams != null) return null;
+
         return mServerRootCaCert;
     }
-
     /**
      * Retrieves the username.
      *
-     * <p>May be null if the profile is not using Username/Password authentication
+     * <p>May be null if the profile is not using Username/Password authentication, or the profile
+     * is built from an {@link IkeTunnelConnectionParams}.
      */
     @Nullable
     public String getUsername() {
+        if (mIkeTunConnParams != null) return null;
+
         return mUsername;
     }
 
     /**
      * Retrieves the password.
      *
-     * <p>May be null if the profile is not using Username/Password authentication
+     * <p>May be null if the profile is not using Username/Password authentication, or the profile
+     * is built from an {@link IkeTunnelConnectionParams}.
      */
     @Nullable
     public String getPassword() {
+        if (mIkeTunConnParams != null) return null;
+
         return mPassword;
     }
 
     /**
      * Retrieves the RSA private key.
      *
-     * <p>May be null if the profile is not using RSA Digital Signature authentication
+     * <p>May be null if the profile is not using RSA Digital Signature authentication, or the
+     * profile is built from an {@link IkeTunnelConnectionParams}.
      */
     @Nullable
     public PrivateKey getRsaPrivateKey() {
+        if (mIkeTunConnParams != null) return null;
+
         return mRsaPrivateKey;
     }
 
-    /** Retrieves the user certificate, if any was set. */
+    /** Retrieves the user certificate, if any was set.
+     *
+     * <p>May be null if the profile is built from an {@link IkeTunnelConnectionParams}.
+     */
     @Nullable
     public X509Certificate getUserCert() {
+        if (mIkeTunConnParams != null) return null;
+
         return mUserCert;
     }
 
@@ -358,9 +379,14 @@
         return mProxyInfo;
     }
 
-    /** Returns all the algorithms allowed by this VPN profile. */
+    /** Returns all the algorithms allowed by this VPN profile.
+     *
+     *  <p>May be an empty list if the profile is built from an {@link IkeTunnelConnectionParams}.
+     */
     @NonNull
     public List<String> getAllowedAlgorithms() {
+        if (mIkeTunConnParams != null) return new ArrayList<>();
+
         return mAllowedAlgorithms;
     }
 
@@ -455,18 +481,25 @@
     @NonNull
     public VpnProfile toVpnProfile() throws IOException, GeneralSecurityException {
         final VpnProfile profile = new VpnProfile("" /* Key; value unused by IKEv2VpnProfile(s) */,
-                mIsRestrictedToTestNetworks, mExcludeLocalRoutes, mRequiresInternetValidation);
-        profile.type = mType;
-        profile.server = mServerAddr;
-        profile.ipsecIdentifier = mUserIdentity;
+                mIsRestrictedToTestNetworks, mExcludeLocalRoutes, mRequiresInternetValidation,
+                mIkeTunConnParams);
+
+        profile.server = getServerAddr();
+        profile.ipsecIdentifier = getUserIdentity();
         profile.proxy = mProxyInfo;
-        profile.setAllowedAlgorithms(mAllowedAlgorithms);
         profile.isBypassable = mIsBypassable;
         profile.isMetered = mIsMetered;
         profile.maxMtu = mMaxMtu;
         profile.areAuthParamsInline = true;
         profile.saveLogin = true;
+        // The other fields should come from mIkeTunConnParams if it's available.
+        if (mIkeTunConnParams != null) {
+            profile.type = VpnProfile.TYPE_IKEV2_FROM_IKE_TUN_CONN_PARAMS;
+            return profile;
+        }
 
+        profile.type = mType;
+        profile.setAllowedAlgorithms(mAllowedAlgorithms);
         switch (mType) {
             case TYPE_IKEV2_IPSEC_USER_PASS:
                 profile.username = mUsername;
@@ -516,10 +549,47 @@
     @NonNull
     public static Ikev2VpnProfile fromVpnProfile(@NonNull VpnProfile profile)
             throws GeneralSecurityException {
-        // TODO: Build the VpnProfile from mIkeTunConnParams if it exists.
-        final Builder builder = new Builder(profile.server, profile.ipsecIdentifier);
+        final Builder builder;
+        if (profile.ikeTunConnParams == null) {
+            builder = new Builder(profile.server, profile.ipsecIdentifier);
+            builder.setAllowedAlgorithms(profile.getAllowedAlgorithms());
+
+            switch (profile.type) {
+                case TYPE_IKEV2_IPSEC_USER_PASS:
+                    builder.setAuthUsernamePassword(
+                            profile.username,
+                            profile.password,
+                            certificateFromPemString(profile.ipsecCaCert));
+                    break;
+                case TYPE_IKEV2_IPSEC_PSK:
+                    builder.setAuthPsk(decodeFromIpsecSecret(profile.ipsecSecret));
+                    break;
+                case TYPE_IKEV2_IPSEC_RSA:
+                    final PrivateKey key;
+                    if (profile.ipsecSecret.startsWith(PREFIX_KEYSTORE_ALIAS)) {
+                        final String alias =
+                                profile.ipsecSecret.substring(PREFIX_KEYSTORE_ALIAS.length());
+                        key = getPrivateKeyFromAndroidKeystore(alias);
+                    } else if (profile.ipsecSecret.startsWith(PREFIX_INLINE)) {
+                        key = getPrivateKey(profile.ipsecSecret.substring(PREFIX_INLINE.length()));
+                    } else {
+                        throw new IllegalArgumentException("Invalid RSA private key prefix");
+                    }
+
+                    final X509Certificate userCert =
+                            certificateFromPemString(profile.ipsecUserCert);
+                    final X509Certificate serverRootCa =
+                            certificateFromPemString(profile.ipsecCaCert);
+                    builder.setAuthDigitalSignature(userCert, key, serverRootCa);
+                    break;
+                default:
+                    throw new IllegalArgumentException("Invalid auth method set");
+            }
+        } else {
+            builder = new Builder(profile.ikeTunConnParams);
+        }
+
         builder.setProxy(profile.proxy);
-        builder.setAllowedAlgorithms(profile.getAllowedAlgorithms());
         builder.setBypassable(profile.isBypassable);
         builder.setMetered(profile.isMetered);
         builder.setMaxMtu(profile.maxMtu);
@@ -527,36 +597,6 @@
             builder.restrictToTestNetworks();
         }
 
-        switch (profile.type) {
-            case TYPE_IKEV2_IPSEC_USER_PASS:
-                builder.setAuthUsernamePassword(
-                        profile.username,
-                        profile.password,
-                        certificateFromPemString(profile.ipsecCaCert));
-                break;
-            case TYPE_IKEV2_IPSEC_PSK:
-                builder.setAuthPsk(decodeFromIpsecSecret(profile.ipsecSecret));
-                break;
-            case TYPE_IKEV2_IPSEC_RSA:
-                final PrivateKey key;
-                if (profile.ipsecSecret.startsWith(PREFIX_KEYSTORE_ALIAS)) {
-                    final String alias =
-                            profile.ipsecSecret.substring(PREFIX_KEYSTORE_ALIAS.length());
-                    key = getPrivateKeyFromAndroidKeystore(alias);
-                } else if (profile.ipsecSecret.startsWith(PREFIX_INLINE)) {
-                    key = getPrivateKey(profile.ipsecSecret.substring(PREFIX_INLINE.length()));
-                } else {
-                    throw new IllegalArgumentException("Invalid RSA private key prefix");
-                }
-
-                final X509Certificate userCert = certificateFromPemString(profile.ipsecUserCert);
-                final X509Certificate serverRootCa = certificateFromPemString(profile.ipsecCaCert);
-                builder.setAuthDigitalSignature(userCert, key, serverRootCa);
-                break;
-            default:
-                throw new IllegalArgumentException("Invalid auth method set");
-        }
-
         if (profile.excludeLocalRoutes && !profile.isBypassable) {
             Log.w(TAG, "ExcludeLocalRoutes should only be set in the bypassable VPN");
         }
@@ -678,82 +718,13 @@
     }
 
     private static void checkBuilderSetter(boolean constructedFromIkeTunConParams,
-            @NonNull String message) {
+            @NonNull String field) {
         if (constructedFromIkeTunConParams) {
-            throw new IllegalArgumentException("Constructed using IkeTunnelConnectionParams "
-                    + "should not set " + message);
+            throw new IllegalArgumentException(
+                    field + " can't be set with IkeTunnelConnectionParams builder");
         }
     }
 
-    private static int getTypeFromIkeSession(@NonNull IkeSessionParams params) {
-        final IkeAuthConfig config = params.getLocalAuthConfig();
-        if (config instanceof IkeAuthDigitalSignLocalConfig) {
-            return TYPE_IKEV2_IPSEC_RSA;
-        } else if (config instanceof IkeAuthEapConfig) {
-            return TYPE_IKEV2_IPSEC_USER_PASS;
-        } else if (config instanceof IkeAuthPskConfig) {
-            return TYPE_IKEV2_IPSEC_PSK;
-        } else {
-            throw new IllegalStateException("Invalid local IkeAuthConfig");
-        }
-    }
-
-    @Nullable
-    private static String getPasswordFromIkeSession(@NonNull IkeSessionParams params) {
-        if (!(params.getLocalAuthConfig() instanceof IkeAuthEapConfig)) return null;
-
-        final IkeAuthEapConfig ikeAuthEapConfig = (IkeAuthEapConfig) params.getLocalAuthConfig();
-        final EapMsChapV2Config eapMsChapV2Config =
-                ikeAuthEapConfig.getEapConfig().getEapMsChapV2Config();
-        return (eapMsChapV2Config != null) ? eapMsChapV2Config.getPassword() : null;
-    }
-
-    @Nullable
-    private static String getUsernameFromIkeSession(@NonNull IkeSessionParams params) {
-        if (!(params.getLocalAuthConfig() instanceof IkeAuthEapConfig)) return null;
-
-        final IkeAuthEapConfig ikeAuthEapConfig = (IkeAuthEapConfig) params.getLocalAuthConfig();
-        final EapMsChapV2Config eapMsChapV2Config =
-                ikeAuthEapConfig.getEapConfig().getEapMsChapV2Config();
-        return (eapMsChapV2Config != null) ? eapMsChapV2Config.getUsername() : null;
-    }
-
-    @Nullable
-    private static X509Certificate getUserCertFromIkeSession(@NonNull IkeSessionParams params) {
-        if (!(params.getLocalAuthConfig() instanceof IkeAuthDigitalSignLocalConfig)) return null;
-
-        final IkeAuthDigitalSignLocalConfig config =
-                (IkeAuthDigitalSignLocalConfig) params.getLocalAuthConfig();
-        return config.getClientEndCertificate();
-    }
-
-    @Nullable
-    private static X509Certificate getServerRootCaCertFromIkeSession(
-            @NonNull IkeSessionParams params) {
-        if (!(params.getRemoteAuthConfig() instanceof IkeAuthDigitalSignRemoteConfig)) return null;
-
-        final IkeAuthDigitalSignRemoteConfig config =
-                (IkeAuthDigitalSignRemoteConfig) params.getRemoteAuthConfig();
-        return config.getRemoteCaCert();
-    }
-
-    @Nullable
-    private static PrivateKey getRsaPrivateKeyFromIkeSession(@NonNull IkeSessionParams params) {
-        if (!(params.getLocalAuthConfig() instanceof IkeAuthDigitalSignLocalConfig)) return null;
-
-        final IkeAuthDigitalSignLocalConfig config =
-                (IkeAuthDigitalSignLocalConfig) params.getLocalAuthConfig();
-        return config.getPrivateKey();
-    }
-
-    @Nullable
-    private static byte[] getPresharedKeyFromIkeSession(@NonNull IkeSessionParams params) {
-        if (!(params.getLocalAuthConfig() instanceof IkeAuthPskConfig)) return null;
-
-        final IkeAuthPskConfig config = (IkeAuthPskConfig) params.getLocalAuthConfig();
-        return config.getPsk();
-    }
-
     @NonNull
     private static String getUserIdentityFromIkeSession(@NonNull IkeSessionParams params) {
         final IkeIdentification ident = params.getLocalIdentification();
@@ -768,6 +739,8 @@
             return ((IkeIpv4AddrIdentification) ident).ipv4Address.getHostAddress();
         } else if (ident instanceof IkeIpv6AddrIdentification) {
             return ((IkeIpv6AddrIdentification) ident).ipv6Address.getHostAddress();
+        } else if (ident instanceof IkeDerAsn1DnIdentification) {
+            throw new IllegalArgumentException("Unspported ASN.1 encoded identities");
         } else {
             throw new IllegalArgumentException("Unknown IkeIdentification to get user identity");
         }
@@ -776,8 +749,8 @@
     /** A incremental builder for IKEv2 VPN profiles */
     public static final class Builder {
         private int mType = -1;
-        @NonNull private final String mServerAddr;
-        @NonNull private final String mUserIdentity;
+        @Nullable private final String mServerAddr;
+        @Nullable private final String mUserIdentity;
 
         // PSK authentication
         @Nullable private byte[] mPresharedKey;
@@ -831,19 +804,8 @@
             checkNotNull(ikeTunConnParams, MISSING_PARAM_MSG_TMPL, "ikeTunConnParams");
 
             mIkeTunConnParams = ikeTunConnParams;
-
-            final IkeSessionParams ikeSessionParams = mIkeTunConnParams.getIkeSessionParams();
-            mServerAddr = ikeSessionParams.getServerHostname();
-
-            mType = getTypeFromIkeSession(ikeSessionParams);
-            mUserCert = getUserCertFromIkeSession(ikeSessionParams);
-            mServerRootCaCert = getServerRootCaCertFromIkeSession(ikeSessionParams);
-            mRsaPrivateKey = getRsaPrivateKeyFromIkeSession(ikeSessionParams);
-            mServerRootCaCert = getServerRootCaCertFromIkeSession(ikeSessionParams);
-            mUsername = getUsernameFromIkeSession(ikeSessionParams);
-            mPassword = getPasswordFromIkeSession(ikeSessionParams);
-            mPresharedKey = getPresharedKeyFromIkeSession(ikeSessionParams);
-            mUserIdentity = getUserIdentityFromIkeSession(ikeSessionParams);
+            mServerAddr = null;
+            mUserIdentity = null;
         }
 
         private void resetAuthParams() {
@@ -862,6 +824,10 @@
          * authentication method may be set. This method will overwrite any previously set
          * authentication method.
          *
+         * <p>If this {@link Builder} is constructed with an {@link IkeTunnelConnectionParams},
+         * authentication details should be configured there, and calling this method will result
+         * in an exception being thrown.
+         *
          * @param user the username to be used for EAP-MSCHAPv2 authentication
          * @param pass the password to be used for EAP-MSCHAPv2 authentication
          * @param serverRootCa the root certificate to be used for verifying the identity of the
@@ -898,6 +864,10 @@
          * Only one authentication method may be set. This method will overwrite any previously set
          * authentication method.
          *
+         * <p>If this {@link Builder} is constructed with an {@link IkeTunnelConnectionParams},
+         * authentication details should be configured there, and calling this method will result in
+         * an exception being thrown.
+         *
          * @param userCert the username to be used for RSA Digital signiture authentication
          * @param key the PrivateKey instance associated with the user ceritificate, used for
          *     constructing the signature
@@ -936,6 +906,10 @@
          * authentication method may be set. This method will overwrite any previously set
          * authentication method.
          *
+         * <p>If this {@link Builder} is constructed with an {@link IkeTunnelConnectionParams},
+         * authentication details should be configured there, and calling this method will result in
+         * an exception being thrown.
+         *
          * @param psk the key to be used for Pre-Shared Key authentication
          * @return this {@link Builder} object to facilitate chaining of method calls
          */
@@ -1068,6 +1042,10 @@
          * Authentication, and one that provides Encryption. Authenticated Encryption with
          * Associated Data (AEAD) algorithms provide both Authentication and Encryption.
          *
+         * <p>If this {@link Builder} is constructed with an {@link IkeTunnelConnectionParams},
+         * authentication details should be configured there, and calling this method will result in
+         * an exception being thrown.
+         *
          * <p>By default, this profile will use any algorithm defined in {@link IpSecAlgorithm},
          * with the exception of those considered insecure (as described above).
          *
@@ -1079,6 +1057,7 @@
         @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS)
         public Builder setAllowedAlgorithms(@NonNull List<String> algorithmNames) {
             checkNotNull(algorithmNames, MISSING_PARAM_MSG_TMPL, "algorithmNames");
+            checkBuilderSetter(mIkeTunConnParams != null, "algorithmNames");
             validateAllowedAlgorithms(algorithmNames);
 
             mAllowedAlgorithms = algorithmNames;
diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java
index 43ae4fc..2c2a703 100644
--- a/core/java/android/net/NetworkPolicyManager.java
+++ b/core/java/android/net/NetworkPolicyManager.java
@@ -176,6 +176,9 @@
     public static final int FOREGROUND_THRESHOLD_STATE =
             ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
 
+    /** @hide */
+    public static final int TOP_THRESHOLD_STATE = ActivityManager.PROCESS_STATE_BOUND_TOP;
+
     /**
      * {@link Intent} extra that indicates which {@link NetworkTemplate} rule it
      * applies to.
@@ -247,6 +250,20 @@
      */
     public static final int ALLOWED_REASON_RESTRICTED_MODE_PERMISSIONS = 1 << 4;
     /**
+     * Flag to indicate that app is exempt from certain network restrictions because of it being
+     * in the bound top or top procstate.
+     *
+     * @hide
+     */
+    public static final int ALLOWED_REASON_TOP = 1 << 5;
+    /**
+     * Flag to indicate that app is exempt from low power standby restrictions because of it being
+     * allowlisted.
+     *
+     * @hide
+     */
+    public static final int ALLOWED_REASON_LOW_POWER_STANDBY_ALLOWLIST = 1 << 6;
+    /**
      * Flag to indicate that app is exempt from certain metered network restrictions because user
      * explicitly exempted it.
      *
@@ -770,6 +787,14 @@
                 || (capability & ActivityManager.PROCESS_CAPABILITY_NETWORK) != 0;
     }
 
+    /** @hide */
+    public static boolean isProcStateAllowedWhileInLowPowerStandby(@Nullable UidState uidState) {
+        if (uidState == null) {
+            return false;
+        }
+        return uidState.procState <= TOP_THRESHOLD_STATE;
+    }
+
     /**
      * Returns true if {@param procState} is considered foreground and as such will be allowed
      * to access network when the device is in data saver mode. Otherwise, false.
diff --git a/core/java/android/net/TEST_MAPPING b/core/java/android/net/TEST_MAPPING
index a379c33..3df5616 100644
--- a/core/java/android/net/TEST_MAPPING
+++ b/core/java/android/net/TEST_MAPPING
@@ -17,7 +17,7 @@
       "path": "frameworks/opt/net/wifi"
     }
   ],
-  "postsubmit": [
+  "presubmit": [
     {
       "name": "FrameworksCoreTests",
       "options": [
diff --git a/core/java/android/net/vcn/VcnCellUnderlyingNetworkTemplate.java b/core/java/android/net/vcn/VcnCellUnderlyingNetworkTemplate.java
index 69e6313..2d1a3fe 100644
--- a/core/java/android/net/vcn/VcnCellUnderlyingNetworkTemplate.java
+++ b/core/java/android/net/vcn/VcnCellUnderlyingNetworkTemplate.java
@@ -57,9 +57,11 @@
     @NonNull private final Set<Integer> mAllowedSpecificCarrierIds;
 
     private static final String ROAMING_MATCH_KEY = "mRoamingMatchCriteria";
+    private static final int DEFAULT_ROAMING_MATCH_CRITERIA = MATCH_ANY;
     private final int mRoamingMatchCriteria;
 
     private static final String OPPORTUNISTIC_MATCH_KEY = "mOpportunisticMatchCriteria";
+    private static final int DEFAULT_OPPORTUNISTIC_MATCH_CRITERIA = MATCH_ANY;
     private final int mOpportunisticMatchCriteria;
 
     private VcnCellUnderlyingNetworkTemplate(
@@ -253,23 +255,31 @@
     /** @hide */
     @Override
     void dumpTransportSpecificFields(IndentingPrintWriter pw) {
-        pw.println("mAllowedNetworkPlmnIds: " + mAllowedNetworkPlmnIds.toString());
-        pw.println("mAllowedSpecificCarrierIds: " + mAllowedSpecificCarrierIds.toString());
-        pw.println("mRoamingMatchCriteria: " + getMatchCriteriaString(mRoamingMatchCriteria));
-        pw.println(
-                "mOpportunisticMatchCriteria: "
-                        + getMatchCriteriaString(mOpportunisticMatchCriteria));
+        if (!mAllowedNetworkPlmnIds.isEmpty()) {
+            pw.println("mAllowedNetworkPlmnIds: " + mAllowedNetworkPlmnIds);
+        }
+        if (!mAllowedNetworkPlmnIds.isEmpty()) {
+            pw.println("mAllowedSpecificCarrierIds: " + mAllowedSpecificCarrierIds);
+        }
+        if (mRoamingMatchCriteria != DEFAULT_ROAMING_MATCH_CRITERIA) {
+            pw.println("mRoamingMatchCriteria: " + getMatchCriteriaString(mRoamingMatchCriteria));
+        }
+        if (mOpportunisticMatchCriteria != DEFAULT_OPPORTUNISTIC_MATCH_CRITERIA) {
+            pw.println(
+                    "mOpportunisticMatchCriteria: "
+                            + getMatchCriteriaString(mOpportunisticMatchCriteria));
+        }
     }
 
     /** This class is used to incrementally build VcnCellUnderlyingNetworkTemplate objects. */
     public static final class Builder {
-        private int mMeteredMatchCriteria = MATCH_ANY;
+        private int mMeteredMatchCriteria = DEFAULT_METERED_MATCH_CRITERIA;
 
         @NonNull private final Set<String> mAllowedNetworkPlmnIds = new ArraySet<>();
         @NonNull private final Set<Integer> mAllowedSpecificCarrierIds = new ArraySet<>();
 
-        private int mRoamingMatchCriteria = MATCH_ANY;
-        private int mOpportunisticMatchCriteria = MATCH_ANY;
+        private int mRoamingMatchCriteria = DEFAULT_ROAMING_MATCH_CRITERIA;
+        private int mOpportunisticMatchCriteria = DEFAULT_OPPORTUNISTIC_MATCH_CRITERIA;
 
         private int mMinEntryUpstreamBandwidthKbps = DEFAULT_MIN_BANDWIDTH_KBPS;
         private int mMinExitUpstreamBandwidthKbps = DEFAULT_MIN_BANDWIDTH_KBPS;
diff --git a/core/java/android/net/vcn/VcnUnderlyingNetworkTemplate.java b/core/java/android/net/vcn/VcnUnderlyingNetworkTemplate.java
index 3a9ca3e..9235d09 100644
--- a/core/java/android/net/vcn/VcnUnderlyingNetworkTemplate.java
+++ b/core/java/android/net/vcn/VcnUnderlyingNetworkTemplate.java
@@ -15,8 +15,6 @@
  */
 package android.net.vcn;
 
-import static android.net.vcn.VcnUnderlyingNetworkTemplate.MATCH_ANY;
-
 import static com.android.internal.annotations.VisibleForTesting.Visibility;
 
 import android.annotation.IntDef;
@@ -88,6 +86,9 @@
     /** @hide */
     static final String METERED_MATCH_KEY = "mMeteredMatchCriteria";
 
+    /** @hide */
+    static final int DEFAULT_METERED_MATCH_CRITERIA = MATCH_ANY;
+
     private final int mMeteredMatchCriteria;
 
     /** @hide */
@@ -237,11 +238,21 @@
         pw.println(this.getClass().getSimpleName() + ":");
         pw.increaseIndent();
 
-        pw.println("mMeteredMatchCriteria: " + getMatchCriteriaString(mMeteredMatchCriteria));
-        pw.println("mMinEntryUpstreamBandwidthKbps: " + mMinEntryUpstreamBandwidthKbps);
-        pw.println("mMinExitUpstreamBandwidthKbps: " + mMinExitUpstreamBandwidthKbps);
-        pw.println("mMinEntryDownstreamBandwidthKbps: " + mMinEntryDownstreamBandwidthKbps);
-        pw.println("mMinExitDownstreamBandwidthKbps: " + mMinExitDownstreamBandwidthKbps);
+        if (mMeteredMatchCriteria != DEFAULT_METERED_MATCH_CRITERIA) {
+            pw.println("mMeteredMatchCriteria: " + getMatchCriteriaString(mMeteredMatchCriteria));
+        }
+        if (mMinEntryUpstreamBandwidthKbps != DEFAULT_MIN_BANDWIDTH_KBPS) {
+            pw.println("mMinEntryUpstreamBandwidthKbps: " + mMinEntryUpstreamBandwidthKbps);
+        }
+        if (mMinExitUpstreamBandwidthKbps != DEFAULT_MIN_BANDWIDTH_KBPS) {
+            pw.println("mMinExitUpstreamBandwidthKbps: " + mMinExitUpstreamBandwidthKbps);
+        }
+        if (mMinEntryDownstreamBandwidthKbps != DEFAULT_MIN_BANDWIDTH_KBPS) {
+            pw.println("mMinEntryDownstreamBandwidthKbps: " + mMinEntryDownstreamBandwidthKbps);
+        }
+        if (mMinExitDownstreamBandwidthKbps != DEFAULT_MIN_BANDWIDTH_KBPS) {
+            pw.println("mMinExitDownstreamBandwidthKbps: " + mMinExitDownstreamBandwidthKbps);
+        }
         dumpTransportSpecificFields(pw);
 
         pw.decreaseIndent();
diff --git a/core/java/android/net/vcn/VcnWifiUnderlyingNetworkTemplate.java b/core/java/android/net/vcn/VcnWifiUnderlyingNetworkTemplate.java
index 23a07ab..2544a6d 100644
--- a/core/java/android/net/vcn/VcnWifiUnderlyingNetworkTemplate.java
+++ b/core/java/android/net/vcn/VcnWifiUnderlyingNetworkTemplate.java
@@ -147,7 +147,9 @@
     /** @hide */
     @Override
     void dumpTransportSpecificFields(IndentingPrintWriter pw) {
-        pw.println("mSsids: " + mSsids);
+        if (!mSsids.isEmpty()) {
+            pw.println("mSsids: " + mSsids);
+        }
     }
 
     /**
diff --git a/core/java/android/os/SystemProperties.java b/core/java/android/os/SystemProperties.java
index 82d4443..aa283a2 100644
--- a/core/java/android/os/SystemProperties.java
+++ b/core/java/android/os/SystemProperties.java
@@ -226,9 +226,10 @@
      */
     @UnsupportedAppUsage
     public static void set(@NonNull String key, @Nullable String val) {
-        if (val != null && !key.startsWith("ro.") && val.length() > PROP_VALUE_MAX) {
+        if (val != null && !key.startsWith("ro.") && val.getBytes(StandardCharsets.UTF_8).length
+                > PROP_VALUE_MAX) {
             throw new IllegalArgumentException("value of system property '" + key
-                    + "' is longer than " + PROP_VALUE_MAX + " characters: " + val);
+                    + "' is longer than " + PROP_VALUE_MAX + " bytes: " + val);
         }
         if (TRACK_KEY_ACCESS) onKeyAccess(key);
         native_set(key, val);
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index 134cfa1..e1542a8 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -1578,18 +1578,13 @@
     }
 
     /** {@hide}
-     * Is this device encryptable or already encrypted?
-     * @return true for encryptable or encrypted
-     *         false not encrypted and not encryptable
-     */
-    public static boolean isEncryptable() {
-        return RoSystemProperties.CRYPTO_ENCRYPTABLE;
-    }
-
-    /** {@hide}
-     * Is this device already encrypted?
-     * @return true for encrypted. (Implies isEncryptable() == true)
-     *         false not encrypted
+     * Is this device encrypted?
+     * <p>
+     * Note: all devices launching with Android 10 (API level 29) or later are
+     * required to be encrypted.  This should only ever return false for
+     * in-development devices on which encryption has not yet been configured.
+     *
+     * @return true if encrypted, false if not encrypted
      */
     public static boolean isEncrypted() {
         return RoSystemProperties.CRYPTO_ENCRYPTED;
@@ -1598,7 +1593,7 @@
     /** {@hide}
      * Is this device file encrypted?
      * @return true for file encrypted. (Implies isEncrypted() == true)
-     *         false not encrypted or block encrypted
+     *         false not encrypted or using "managed" encryption
      */
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
     public static boolean isFileEncryptedNativeOnly() {
@@ -1608,54 +1603,6 @@
         return RoSystemProperties.CRYPTO_FILE_ENCRYPTED;
     }
 
-    /** {@hide}
-     * Is this device block encrypted?
-     * @return true for block encrypted. (Implies isEncrypted() == true)
-     *         false not encrypted or file encrypted
-     */
-    public static boolean isBlockEncrypted() {
-        return false;
-    }
-
-    /** {@hide}
-     * Is this device block encrypted with credentials?
-     * @return true for crediential block encrypted.
-     *         (Implies isBlockEncrypted() == true)
-     *         false not encrypted, file encrypted or default block encrypted
-     */
-    public static boolean isNonDefaultBlockEncrypted() {
-        return false;
-    }
-
-    /** {@hide}
-     * Is this device in the process of being block encrypted?
-     * @return true for encrypting.
-     *         false otherwise
-     * Whether device isEncrypted at this point is undefined
-     * Note that only system services and CryptKeeper will ever see this return
-     * true - no app will ever be launched in this state.
-     * Also note that this state will not change without a teardown of the
-     * framework, so no service needs to check for changes during their lifespan
-     */
-    public static boolean isBlockEncrypting() {
-        return false;
-    }
-
-    /** {@hide}
-     * Is this device non default block encrypted and in the process of
-     * prompting for credentials?
-     * @return true for prompting for credentials.
-     *         (Implies isNonDefaultBlockEncrypted() == true)
-     *         false otherwise
-     * Note that only system services and CryptKeeper will ever see this return
-     * true - no app will ever be launched in this state.
-     * Also note that this state will not change without a teardown of the
-     * framework, so no service needs to check for changes during their lifespan
-     */
-    public static boolean inCryptKeeperBounce() {
-        return false;
-    }
-
     /** {@hide} */
     public static boolean isFileEncryptedEmulatedOnly() {
         return SystemProperties.getBoolean(StorageManager.PROP_EMULATE_FBE, false);
diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java
index 93c1c20..4c1cc97 100644
--- a/core/java/android/provider/DeviceConfig.java
+++ b/core/java/android/provider/DeviceConfig.java
@@ -829,7 +829,8 @@
      * @param name        The name of the property to create or update.
      * @param value       The value to store for the property.
      * @param makeDefault Whether to make the new value the default one.
-     * @return True if the value was set, false if the storage implementation throws errors.
+     * @return {@code true} if the value was set, {@code false} if the storage implementation throws
+     * errors.
      * @hide
      * @see #resetToDefaults(int, String).
      */
@@ -853,7 +854,7 @@
      *
      * @param properties the complete set of properties to set for a specific namespace.
      * @throws BadConfigException if the provided properties are banned by RescueParty.
-     * @return True if the values were set, false otherwise.
+     * @return {@code true} if the values were set, {@code false} otherwise.
      * @hide
      */
     @SystemApi
@@ -867,10 +868,10 @@
     /**
      * Delete a property with the provided name and value in the provided namespace
      *
-     * @param namespace   The namespace containing the property to create or update.
-     * @param name        The name of the property to create or update.
-     * @return True if the property was deleted or it did not exist in the first place.
-     * False if the storage implementation throws errors.
+     * @param namespace   The namespace containing the property to delete.
+     * @param name        The name of the property to delete.
+     * @return {@code true} if the property was deleted or it did not exist in the first place.
+     * Return {@code false} if the storage implementation throws errors.
      * @hide
      */
     @SystemApi
diff --git a/core/java/android/service/carrier/OWNERS b/core/java/android/service/carrier/OWNERS
index d768ef4..447cd51 100644
--- a/core/java/android/service/carrier/OWNERS
+++ b/core/java/android/service/carrier/OWNERS
@@ -1,5 +1,3 @@
-# Bug component: 20868
+set noparent
 
-rgreenwalt@google.com
-tgunn@google.com
-fionaxu@google.com
+file:platform/frameworks/base:/telephony/OWNERS
diff --git a/core/java/android/text/TextUtils.java b/core/java/android/text/TextUtils.java
index d0fd2b3..509f4d9 100644
--- a/core/java/android/text/TextUtils.java
+++ b/core/java/android/text/TextUtils.java
@@ -350,6 +350,53 @@
         return ret;
     }
 
+
+    /**
+     * Returns the longest prefix of a string for which the UTF-8 encoding fits into the given
+     * number of bytes, with the additional guarantee that the string is not truncated in the middle
+     * of a valid surrogate pair.
+     *
+     * <p>Unpaired surrogates are counted as taking 3 bytes of storage. However, a subsequent
+     * attempt to actually encode a string containing unpaired surrogates is likely to be rejected
+     * by the UTF-8 implementation.
+     *
+     * (copied from google/thirdparty)
+     *
+     * @param str a string
+     * @param maxbytes the maximum number of UTF-8 encoded bytes
+     * @return the beginning of the string, so that it uses at most maxbytes bytes in UTF-8
+     * @throws IndexOutOfBoundsException if maxbytes is negative
+     *
+     * @hide
+     */
+    public static String truncateStringForUtf8Storage(String str, int maxbytes) {
+        if (maxbytes < 0) {
+            throw new IndexOutOfBoundsException();
+        }
+
+        int bytes = 0;
+        for (int i = 0, len = str.length(); i < len; i++) {
+            char c = str.charAt(i);
+            if (c < 0x80) {
+                bytes += 1;
+            } else if (c < 0x800) {
+                bytes += 2;
+            } else if (c < Character.MIN_SURROGATE
+                    || c > Character.MAX_SURROGATE
+                    || str.codePointAt(i) < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
+                bytes += 3;
+            } else {
+                bytes += 4;
+                i += (bytes > maxbytes) ? 0 : 1;
+            }
+            if (bytes > maxbytes) {
+                return str.substring(0, i);
+            }
+        }
+        return str;
+    }
+
+
     /**
      * Returns a string containing the tokens joined by delimiters.
      *
diff --git a/core/java/android/util/NtpTrustedTime.java b/core/java/android/util/NtpTrustedTime.java
index 01a037a..4e7b3a5 100644
--- a/core/java/android/util/NtpTrustedTime.java
+++ b/core/java/android/util/NtpTrustedTime.java
@@ -193,6 +193,16 @@
             }
             final Network network = connectivityManager.getActiveNetwork();
             final NetworkInfo ni = connectivityManager.getNetworkInfo(network);
+
+            // This connectivity check is to avoid performing a DNS lookup for the time server on a
+            // unconnected network. There are races to obtain time in Android when connectivity
+            // changes, which means that forceRefresh() can be called by various components before
+            // the network is actually available. This led in the past to DNS lookup failures being
+            // cached (~2 seconds) thereby preventing the device successfully making an NTP request
+            // when connectivity had actually been established.
+            // A side effect of check is that tests that run a fake NTP server on the device itself
+            // will only be able to use it if the active network is connected, even though loopback
+            // addresses are actually reachable.
             if (ni == null || !ni.isConnected()) {
                 if (LOGD) Log.d(TAG, "forceRefresh: no connectivity");
                 return false;
diff --git a/core/java/android/view/InsetsState.java b/core/java/android/view/InsetsState.java
index 75b69cb..d15d7c7 100644
--- a/core/java/android/view/InsetsState.java
+++ b/core/java/android/view/InsetsState.java
@@ -391,6 +391,17 @@
             processSourceAsPublicType(source, typeInsetsMap, typeSideMap, typeVisibilityMap,
                     insets, Type.SYSTEM_GESTURES);
         }
+        if (type == Type.CAPTION_BAR) {
+            // Caption should also be gesture and tappable elements. This should not be needed when
+            // the caption is added from the shell, as the shell can add other types at the same
+            // time.
+            processSourceAsPublicType(source, typeInsetsMap, typeSideMap, typeVisibilityMap,
+                    insets, Type.SYSTEM_GESTURES);
+            processSourceAsPublicType(source, typeInsetsMap, typeSideMap, typeVisibilityMap,
+                    insets, Type.MANDATORY_SYSTEM_GESTURES);
+            processSourceAsPublicType(source, typeInsetsMap, typeSideMap, typeVisibilityMap,
+                    insets, Type.TAPPABLE_ELEMENT);
+        }
     }
 
     private void processSourceAsPublicType(InsetsSource source, Insets[] typeInsetsMap,
diff --git a/core/java/com/android/internal/accessibility/dialog/AccessibilityTargetHelper.java b/core/java/com/android/internal/accessibility/dialog/AccessibilityTargetHelper.java
index 4a20ad0..fc2c8cc 100644
--- a/core/java/com/android/internal/accessibility/dialog/AccessibilityTargetHelper.java
+++ b/core/java/com/android/internal/accessibility/dialog/AccessibilityTargetHelper.java
@@ -33,7 +33,6 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.os.Build;
-import android.os.storage.StorageManager;
 import android.provider.Settings;
 import android.text.BidiFormatter;
 import android.view.LayoutInflater;
@@ -282,19 +281,7 @@
                 Context.LAYOUT_INFLATER_SERVICE);
 
         final View content = inflater.inflate(
-                R.layout.accessibility_enable_service_encryption_warning, /* root= */ null);
-
-        final TextView encryptionWarningView = (TextView) content.findViewById(
-                R.id.accessibility_encryption_warning);
-        if (StorageManager.isNonDefaultBlockEncrypted()) {
-            final String text = context.getString(
-                    R.string.accessibility_enable_service_encryption_warning,
-                    getServiceName(context, target.getLabel()));
-            encryptionWarningView.setText(text);
-            encryptionWarningView.setVisibility(View.VISIBLE);
-        } else {
-            encryptionWarningView.setVisibility(View.GONE);
-        }
+                R.layout.accessibility_enable_service_warning, /* root= */ null);
 
         final ImageView dialogIcon = content.findViewById(
                 R.id.accessibility_permissionDialog_icon);
diff --git a/core/java/com/android/internal/app/HarmfulAppWarningActivity.java b/core/java/com/android/internal/app/HarmfulAppWarningActivity.java
index ce2d229..33209e1 100644
--- a/core/java/com/android/internal/app/HarmfulAppWarningActivity.java
+++ b/core/java/com/android/internal/app/HarmfulAppWarningActivity.java
@@ -16,6 +16,8 @@
 
 package com.android.internal.app;
 
+import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
+
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.Intent;
@@ -27,6 +29,7 @@
 import android.util.Log;
 import android.view.View;
 import android.widget.TextView;
+
 import com.android.internal.R;
 
 /**
@@ -48,6 +51,7 @@
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
 
+        getWindow().addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
         final Intent intent = getIntent();
         mPackageName = intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME);
         mTarget = intent.getParcelableExtra(Intent.EXTRA_INTENT);
diff --git a/core/java/com/android/internal/net/VpnProfile.java b/core/java/com/android/internal/net/VpnProfile.java
index bd3e898..8797381 100644
--- a/core/java/com/android/internal/net/VpnProfile.java
+++ b/core/java/com/android/internal/net/VpnProfile.java
@@ -22,12 +22,17 @@
 import android.net.PlatformVpnProfile;
 import android.net.ProxyInfo;
 import android.net.Uri;
+import android.net.ipsec.ike.IkeTunnelConnectionParams;
+import android.net.vcn.persistablebundleutils.TunnelConnectionParamsUtils;
 import android.os.Build;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.os.PersistableBundle;
 import android.text.TextUtils;
+import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.HexDump;
 import com.android.net.module.util.ProxyUtils;
 
 import java.io.UnsupportedEncodingException;
@@ -69,7 +74,8 @@
     public static final int TYPE_IKEV2_IPSEC_USER_PASS = 6;
     public static final int TYPE_IKEV2_IPSEC_PSK = 7;
     public static final int TYPE_IKEV2_IPSEC_RSA = 8;
-    public static final int TYPE_MAX = 8;
+    public static final int TYPE_IKEV2_FROM_IKE_TUN_CONN_PARAMS = 9;
+    public static final int TYPE_MAX = 9;
 
     // Match these constants with R.array.vpn_proxy_settings.
     public static final int PROXY_NONE = 0;
@@ -145,25 +151,27 @@
 
     public final boolean excludeLocalRoutes;                     // 25
     public final boolean requiresInternetValidation;             // 26
+    public final IkeTunnelConnectionParams ikeTunConnParams;     // 27
 
     // Helper fields.
     @UnsupportedAppUsage
     public transient boolean saveLogin = false;
 
     public VpnProfile(String key) {
-        this(key, false, false, false);
+        this(key, false, false, false, null);
     }
 
     public VpnProfile(String key, boolean isRestrictedToTestNetworks) {
-        this(key, isRestrictedToTestNetworks, false, false);
+        this(key, isRestrictedToTestNetworks, false, false, null);
     }
 
     public VpnProfile(String key, boolean isRestrictedToTestNetworks, boolean excludeLocalRoutes,
-            boolean requiresInternetValidation) {
+            boolean requiresInternetValidation, IkeTunnelConnectionParams ikeTunConnParams) {
         this.key = key;
         this.isRestrictedToTestNetworks = isRestrictedToTestNetworks;
         this.excludeLocalRoutes = excludeLocalRoutes;
         this.requiresInternetValidation = requiresInternetValidation;
+        this.ikeTunConnParams = ikeTunConnParams;
     }
 
     @UnsupportedAppUsage
@@ -195,6 +203,10 @@
         isRestrictedToTestNetworks = in.readBoolean();
         excludeLocalRoutes = in.readBoolean();
         requiresInternetValidation = in.readBoolean();
+        final PersistableBundle bundle =
+                in.readParcelable(PersistableBundle.class.getClassLoader());
+        ikeTunConnParams = (bundle == null) ? null
+                : TunnelConnectionParamsUtils.fromPersistableBundle(bundle);
     }
 
     /**
@@ -244,6 +256,8 @@
         out.writeBoolean(isRestrictedToTestNetworks);
         out.writeBoolean(excludeLocalRoutes);
         out.writeBoolean(requiresInternetValidation);
+        out.writeParcelable(ikeTunConnParams == null ? null
+                : TunnelConnectionParamsUtils.toPersistableBundle(ikeTunConnParams), flags);
     }
 
     /**
@@ -259,15 +273,17 @@
             }
 
             String[] values = new String(value, StandardCharsets.UTF_8).split(VALUE_DELIMITER, -1);
+
             // Acceptable numbers of values are:
             // 14-19: Standard profile, with option for serverCert, proxy
             // 24: Standard profile with serverCert, proxy and platform-VPN parameters
             // 25: Standard profile with platform-VPN parameters and isRestrictedToTestNetworks
             // 26:                                            ...and excludeLocalRoutes
-            //     (26 can only be found on dogfood devices)
             // 27:                                            ...and requiresInternetValidation
+            //     (26,27 can only be found on dogfood devices)
+            // 28:                                            ...and ikeTunConnParams
             if ((values.length < 14 || (values.length > 19 && values.length < 24)
-                    || values.length > 27)) {
+                    || values.length > 28)) {
                 return null;
             }
 
@@ -292,8 +308,22 @@
                 requiresInternetValidation = false;
             }
 
+            final IkeTunnelConnectionParams tempIkeTunConnParams;
+            // Assign null directly if the ikeTunConParams field is empty.
+            if (values.length >= 28 && values[27].length() != 0) {
+                final Parcel parcel = Parcel.obtain();
+                final byte[] bytes = HexDump.hexStringToByteArray(values[27]);
+                parcel.unmarshall(bytes, 0, bytes.length);
+                parcel.setDataPosition(0);
+                final PersistableBundle bundle = (PersistableBundle) parcel.readValue(
+                        PersistableBundle.class.getClassLoader());
+                tempIkeTunConnParams = TunnelConnectionParamsUtils.fromPersistableBundle(bundle);
+            } else {
+                tempIkeTunConnParams = null;
+            }
+
             VpnProfile profile = new VpnProfile(key, isRestrictedToTestNetworks,
-                    excludeLocalRoutes, requiresInternetValidation);
+                    excludeLocalRoutes, requiresInternetValidation, tempIkeTunConnParams);
             profile.name = values[0];
             profile.type = Integer.parseInt(values[1]);
             if (profile.type < 0 || profile.type > TYPE_MAX) {
@@ -345,6 +375,7 @@
             profile.saveLogin = !profile.username.isEmpty() || !profile.password.isEmpty();
             return profile;
         } catch (Exception e) {
+            Log.d(TAG, "Got exception in decode.", e);
             // ignore
         }
         return null;
@@ -406,6 +437,17 @@
         builder.append(VALUE_DELIMITER).append(excludeLocalRoutes);
         builder.append(VALUE_DELIMITER).append(requiresInternetValidation);
 
+        if (ikeTunConnParams != null) {
+            final PersistableBundle bundle =
+                    TunnelConnectionParamsUtils.toPersistableBundle(ikeTunConnParams);
+            final Parcel parcel = Parcel.obtain();
+            parcel.writeValue(bundle);
+            final byte[] bytes = parcel.marshall();
+            builder.append(VALUE_DELIMITER).append(HexDump.toHexString(bytes));
+        } else {
+            builder.append(VALUE_DELIMITER).append("");
+        }
+
         return builder.toString().getBytes(StandardCharsets.UTF_8);
     }
 
@@ -486,7 +528,8 @@
             key, type, server, username, password, dnsServers, searchDomains, routes, mppe,
             l2tpSecret, ipsecIdentifier, ipsecSecret, ipsecUserCert, ipsecCaCert, ipsecServerCert,
             proxy, mAllowedAlgorithms, isBypassable, isMetered, maxMtu, areAuthParamsInline,
-            isRestrictedToTestNetworks, excludeLocalRoutes, requiresInternetValidation);
+            isRestrictedToTestNetworks, excludeLocalRoutes, requiresInternetValidation,
+            ikeTunConnParams);
     }
 
     /** Checks VPN profiles for interior equality. */
@@ -521,7 +564,8 @@
                 && areAuthParamsInline == other.areAuthParamsInline
                 && isRestrictedToTestNetworks == other.isRestrictedToTestNetworks
                 && excludeLocalRoutes == other.excludeLocalRoutes
-                && requiresInternetValidation == other.requiresInternetValidation;
+                && requiresInternetValidation == other.requiresInternetValidation
+                && Objects.equals(ikeTunConnParams, other.ikeTunConnParams);
     }
 
     @NonNull
diff --git a/core/java/com/android/internal/os/RoSystemProperties.java b/core/java/com/android/internal/os/RoSystemProperties.java
index 8b659f9..98d81c9 100644
--- a/core/java/com/android/internal/os/RoSystemProperties.java
+++ b/core/java/com/android/internal/os/RoSystemProperties.java
@@ -60,14 +60,10 @@
     public static final CryptoProperties.type_values CRYPTO_TYPE =
             CryptoProperties.type().orElse(CryptoProperties.type_values.NONE);
     // These are pseudo-properties
-    public static final boolean CRYPTO_ENCRYPTABLE =
-            CRYPTO_STATE != CryptoProperties.state_values.UNSUPPORTED;
     public static final boolean CRYPTO_ENCRYPTED =
             CRYPTO_STATE == CryptoProperties.state_values.ENCRYPTED;
     public static final boolean CRYPTO_FILE_ENCRYPTED =
             CRYPTO_TYPE == CryptoProperties.type_values.FILE;
-    public static final boolean CRYPTO_BLOCK_ENCRYPTED =
-            CRYPTO_TYPE == CryptoProperties.type_values.BLOCK;
 
     public static final boolean CONTROL_PRIVAPP_PERMISSIONS_LOG =
             "log".equalsIgnoreCase(CONTROL_PRIVAPP_PERMISSIONS);
diff --git a/core/java/com/android/internal/security/OWNERS b/core/java/com/android/internal/security/OWNERS
index 41d1d66..b702df8 100644
--- a/core/java/com/android/internal/security/OWNERS
+++ b/core/java/com/android/internal/security/OWNERS
@@ -1,3 +1,3 @@
 # Bug component: 36824
 
-per-file VerityUtils.java = victorhsieh@google.com
+per-file VerityUtils.java = file:platform/system/security:/fsverity/OWNERS
diff --git a/core/jni/OWNERS b/core/jni/OWNERS
index 626a212..4072687 100644
--- a/core/jni/OWNERS
+++ b/core/jni/OWNERS
@@ -81,7 +81,7 @@
 per-file LayoutlibLoader.cpp = diegoperez@google.com, jgaillard@google.com
 
 # Verity
-per-file com_android_internal_security_Verity* = ebiggers@google.com, victorhsieh@google.com
+per-file com_android_internal_security_Verity* = file:platform/system/security:/fsverity/OWNERS
 
 # VINTF
 per-file android_os_VintfObject* = file:platform/system/libvintf:/OWNERS
diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp
index 4d8d4db..71b51ff 100644
--- a/core/jni/android_util_Process.cpp
+++ b/core/jni/android_util_Process.cpp
@@ -991,7 +991,7 @@
             end = i;
             i++;
         } else if ((mode&PROC_QUOTES) != 0) {
-            while (buffer[i] != '"' && i < endIndex) {
+            while (i < endIndex && buffer[i] != '"') {
                 i++;
             }
             end = i;
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index b87befb..f81ac3d 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -3409,6 +3409,12 @@
     <permission android:name="android.permission.UPDATE_FONTS"
         android:protectionLevel="signature|privileged" />
 
+    <!-- Allows the caller to generate keymint keys with the INCLUDE_UNIQUE_ID tag, which
+         uniquely identifies the device via the attestation certificate.
+         @hide @TestApi -->
+    <permission android:name="android.permission.REQUEST_UNIQUE_ID_ATTESTATION"
+         android:protectionLevel="signature" />
+
     <!-- ========================================= -->
     <!-- Permissions for special development tools -->
     <!-- ========================================= -->
diff --git a/core/res/res/layout/accessibility_enable_service_encryption_warning.xml b/core/res/res/layout/accessibility_enable_service_warning.xml
similarity index 94%
rename from core/res/res/layout/accessibility_enable_service_encryption_warning.xml
rename to core/res/res/layout/accessibility_enable_service_warning.xml
index 4000516..01ef101 100644
--- a/core/res/res/layout/accessibility_enable_service_encryption_warning.xml
+++ b/core/res/res/layout/accessibility_enable_service_warning.xml
@@ -54,14 +54,6 @@
                 android:fontFamily="google-sans-medium"/>
 
             <TextView
-                android:id="@+id/accessibility_encryption_warning"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:padding="10dip"
-                android:textAlignment="viewStart"
-                android:textAppearance="?android:attr/textAppearanceMedium"/>
-
-            <TextView
                 android:id="@+id/accessibility_permissionDialog_description"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 236fad2..c5d50fb 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2599,6 +2599,9 @@
          Values are bandwidth_estimator, carrier_config and modem. -->
     <string name="config_bandwidthEstimateSource">bandwidth_estimator</string>
 
+    <!-- Whether force to enable telephony new data stack or not -->
+    <bool name="config_force_enable_telephony_new_data_stack">false</bool>
+
     <!-- Whether WiFi display is supported by this device.
          There are many prerequisites for this feature to work correctly.
          Here are a few of them:
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 7663192..db0cc27 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -4687,13 +4687,6 @@
         <xliff:g id="service" example="TalkBack">%1$s</xliff:g> to have full control of your
         device?</string>
 
-    <!-- Warning that the device data will not be encrypted with password or PIN if
-    enabling an accessibility service and there is a secure lock setup. [CHAR LIMIT=NONE] -->
-    <string name="accessibility_enable_service_encryption_warning">If you turn on
-        <xliff:g id="service" example="TalkBack">%1$s</xliff:g>, your device won’t use your screen
-        lock to enhance data encryption.
-    </string>
-
     <!-- Warning description that explains that it's appropriate for accessibility
      services to have full control to help users with accessibility needs. [CHAR LIMIT=NONE] -->
     <string name="accessibility_service_warning_description">Full control is appropriate for apps
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index bacd25d..6e0fd91 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -468,6 +468,7 @@
   <java-symbol type="array"   name="config_mobile_tcp_buffers" />
   <java-symbol type="array"   name="config_network_type_tcp_buffers" />
   <java-symbol type="string"  name="config_tcp_buffers" />
+  <java-symbol type="bool" name="config_force_enable_telephony_new_data_stack" />
   <java-symbol type="integer" name="config_volte_replacement_rat"/>
   <java-symbol type="integer" name="config_valid_wappush_index" />
   <java-symbol type="integer" name="config_overrideHasPermanentMenuKey" />
@@ -3414,14 +3415,12 @@
   <java-symbol type="string" name="accessibility_edit_shortcut_menu_volume_title" />
   <java-symbol type="string" name="accessibility_uncheck_legacy_item_warning" />
 
-  <java-symbol type="layout" name="accessibility_enable_service_encryption_warning" />
+  <java-symbol type="layout" name="accessibility_enable_service_warning" />
   <java-symbol type="id" name="accessibility_permissionDialog_icon" />
   <java-symbol type="id" name="accessibility_permissionDialog_title" />
-  <java-symbol type="id" name="accessibility_encryption_warning" />
   <java-symbol type="id" name="accessibility_permission_enable_allow_button" />
   <java-symbol type="id" name="accessibility_permission_enable_deny_button" />
   <java-symbol type="string" name="accessibility_enable_service_title" />
-  <java-symbol type="string" name="accessibility_enable_service_encryption_warning" />
 
   <java-symbol type="layout" name="accessibility_shortcut_chooser_item" />
   <java-symbol type="id" name="accessibility_shortcut_target_checkbox" />
diff --git a/core/tests/coretests/src/android/net/OWNERS b/core/tests/coretests/src/android/net/OWNERS
index 4e5136f..a779c00 100644
--- a/core/tests/coretests/src/android/net/OWNERS
+++ b/core/tests/coretests/src/android/net/OWNERS
@@ -1,3 +1,4 @@
 include /services/core/java/com/android/server/net/OWNERS
 
+per-file SSL*,Uri*,Url* = prb@google.com,oth@google.com,narayan@google.com,ngeoffray@google.com
 per-file SntpClient* = file:/services/core/java/com/android/server/timedetector/OWNERS
diff --git a/core/tests/coretests/src/android/text/TextUtilsTest.java b/core/tests/coretests/src/android/text/TextUtilsTest.java
index a0fc349..c4bcfd4 100644
--- a/core/tests/coretests/src/android/text/TextUtilsTest.java
+++ b/core/tests/coretests/src/android/text/TextUtilsTest.java
@@ -43,6 +43,7 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Locale;
@@ -782,6 +783,81 @@
     }
 
     @Test
+    public void truncateStringForUtf8Storage() {
+        assertEquals("", TextUtils.truncateStringForUtf8Storage("abc", 0));
+
+        //================ long normal case ================
+        StringBuilder builder = new StringBuilder();
+
+        int n = 50;
+        for (int i = 0; i < 2 * n; i++) {
+            builder.append("哈");
+        }
+        String initial = builder.toString();
+        String result = TextUtils.truncateStringForUtf8Storage(initial, n);
+
+        // Result should be the beginning of initial
+        assertTrue(initial.startsWith(result));
+
+        // Result should take less than n bytes in UTF-8
+        assertTrue(result.getBytes(StandardCharsets.UTF_8).length <= n);
+
+        // result + the next codePoint should take strictly more than
+        // n bytes in UTF-8
+        assertTrue(initial.substring(0, initial.offsetByCodePoints(result.length(), 1))
+                .getBytes(StandardCharsets.UTF_8).length > n);
+
+        // =================== short normal case =====================
+        String s = "sf\u20ACgk\u00E9ls\u00E9fg";
+        result = TextUtils.truncateStringForUtf8Storage(s, 100);
+        assertEquals(s, result);
+    }
+
+    @Test
+    public void testTruncateInMiddleOfSurrogate() {
+        StringBuilder builder = new StringBuilder();
+        String beginning = "a";
+        builder.append(beginning);
+        builder.append(Character.toChars(0x1D11E));
+
+        String result = TextUtils.truncateStringForUtf8Storage(builder.toString(), 3);
+
+        // \u1D11E is a surrogate and needs 4 bytes in UTF-8. beginning == "a" uses
+        // only 1 bytes in UTF8
+        // As we allow only 3 bytes for the whole string, so just 2 for this
+        // codePoint, there is not enough place and the string will be truncated
+        // just before it
+        assertEquals(beginning, result);
+    }
+
+    @Test
+    public void testTruncateInMiddleOfChar() {
+        StringBuilder builder = new StringBuilder();
+        String beginning = "a";
+        builder.append(beginning);
+        builder.append(Character.toChars(0x20AC));
+
+        String result = TextUtils.truncateStringForUtf8Storage(builder.toString(), 3);
+
+        // Like above, \u20AC uses 3 bytes in UTF-8, with "beginning", that makes
+        // 4 bytes so it is too big and should be truncated
+        assertEquals(beginning, result);
+    }
+
+    @Test
+    public void testTruncateSubString() {
+        String test = "sdgkl;hjsl;gjhdgkljdfhglkdj";
+        String sub = test.substring(10, 20);
+        String res = TextUtils.truncateStringForUtf8Storage(sub, 255);
+        assertEquals(sub, res);
+    }
+
+    @Test(expected = IndexOutOfBoundsException.class)
+    public void truncateStringForUtf8StorageThrowsExceptionForNegativeSize() {
+        TextUtils.truncateStringForUtf8Storage("abc", -1);
+    }
+
+    @Test
     public void length() {
         assertEquals(0, TextUtils.length(null));
         assertEquals(0, TextUtils.length(""));
diff --git a/data/keyboards/Vendor_0e6f_Product_f501.kl b/data/keyboards/Vendor_0e6f_Product_f501.kl
new file mode 100644
index 0000000..b46c005
--- /dev/null
+++ b/data/keyboards/Vendor_0e6f_Product_f501.kl
@@ -0,0 +1,55 @@
+# Copyright (C) 2022 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.
+
+#
+# XBox-compatible USB Controller
+#
+
+key 304   BUTTON_A
+key 305   BUTTON_B
+key 307   BUTTON_X
+key 308   BUTTON_Y
+key 310   BUTTON_L1
+key 311   BUTTON_R1
+
+key 317   BUTTON_THUMBL
+key 318   BUTTON_THUMBR
+
+# Left and right stick.
+# The reported value for flat is 128 out of a range from -32767 to 32768, which is absurd.
+# This confuses applications that rely on the flat value because the joystick actually
+# settles in a flat range of +/- 4096 or so.
+axis 0x00 X flat 4096
+axis 0x01 Y flat 4096
+axis 0x03 Z flat 4096
+axis 0x04 RZ flat 4096
+
+# Triggers.
+axis 0x02 LTRIGGER
+axis 0x05 RTRIGGER
+
+# Hat.
+axis 0x10 HAT_X
+axis 0x11 HAT_Y
+
+# Mapping according to https://www.kernel.org/doc/Documentation/input/gamepad.txt
+
+# Button labeled as "BACK" (left-pointing triangle)
+key 314   BUTTON_SELECT
+
+# The branded "X" button in the center of the controller
+key 316   BUTTON_MODE
+
+# Button labeled as "START" (right-pointing triangle)
+key 315   BUTTON_START
diff --git a/keystore/java/android/security/KeyStoreException.java b/keystore/java/android/security/KeyStoreException.java
index 54184db..1a81dda 100644
--- a/keystore/java/android/security/KeyStoreException.java
+++ b/keystore/java/android/security/KeyStoreException.java
@@ -21,6 +21,7 @@
 import android.annotation.TestApi;
 import android.security.keymaster.KeymasterDefs;
 import android.system.keystore2.ResponseCode;
+import android.util.Log;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -36,6 +37,8 @@
  * is likely to succeed.
  */
 public class KeyStoreException extends Exception {
+    private static final String TAG = "KeyStoreException";
+
     /**
      * This error code is for mapping errors that the caller will not know about. If the caller is
      * targeting an API level earlier than the one the error was introduced in, then the error will
@@ -114,6 +117,27 @@
      * The caller should re-create the crypto object and try again.
      */
     public static final int ERROR_KEY_OPERATION_EXPIRED = 15;
+    /**
+     * There are no keys available for attestation.
+     * This error is returned only on devices that rely solely on remotely-provisioned keys (see
+     * <a href=
+     * "https://android-developers.googleblog.com/2022/03/upgrading-android-attestation-remote.html"
+     * >Remote Key Provisioning</a>).
+     *
+     * <p>On such a device, if the caller requests key generation and includes an attestation
+     * challenge (indicating key attestation is required), the error will be returned in one of
+     * the following cases:
+     * <ul>
+     *     <li>The pool of remotely-provisioned keys has been exhausted.</li>
+     *     <li>The device is not registered with the key provisioning server.</li>
+     * </ul>
+     * </p>
+     *
+     * <p>This error is a transient one if the pool of remotely-provisioned keys has been
+     * exhausted. However, if the device is not registered with the server, or the key
+     * provisioning server refuses key issuance, this is a permanent error.</p>
+     */
+    public static final int ERROR_ATTESTATION_KEYS_UNAVAILABLE = 16;
 
     /** @hide */
     @Retention(RetentionPolicy.SOURCE)
@@ -132,11 +156,68 @@
             ERROR_UNIMPLEMENTED,
             ERROR_INCORRECT_USAGE,
             ERROR_KEY_NOT_TEMPORALLY_VALID,
-            ERROR_KEY_OPERATION_EXPIRED
+            ERROR_KEY_OPERATION_EXPIRED,
+            ERROR_ATTESTATION_KEYS_UNAVAILABLE
     })
     public @interface PublicErrorCode {
     }
 
+    /**
+     * Never re-try the operation that led to this error, since it's a permanent error.
+     *
+     * This value is always returned when {@link #isTransientFailure()} is {@code false}.
+     */
+    public static final int RETRY_NEVER = 1;
+    /**
+     * Re-try the operation that led to this error with an exponential back-off delay.
+     * The first delay should be between 5 to 30 seconds, and each subsequent re-try should double
+     * the delay time.
+     *
+     * This value is returned when {@link #isTransientFailure()} is {@code true}.
+     */
+    public static final int RETRY_WITH_EXPONENTIAL_BACKOFF = 2;
+    /**
+     * Re-try the operation that led to this error when the device regains connectivity.
+     * Remote provisioning of keys requires reaching the remote server, and the device is
+     * currently unable to due that due to lack of network connectivity.
+     *
+     * This value is returned when {@link #isTransientFailure()} is {@code true}.
+     */
+    public static final int RETRY_WHEN_CONNECTIVITY_AVAILABLE = 3;
+
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(flag = true, prefix = {"RETRY_"}, value = {
+            RETRY_NEVER,
+            RETRY_WITH_EXPONENTIAL_BACKOFF,
+            RETRY_WHEN_CONNECTIVITY_AVAILABLE,
+    })
+    public @interface RetryPolicy {
+    }
+
+    // RKP-specific error information.
+    /**
+     * Remote provisioning of attestation keys has completed successfully.
+     * @hide */
+    public static final int RKP_SUCCESS = 0;
+    /**
+     * Remotely-provisioned keys are temporarily unavailable. This could be because of RPC
+     * error when talking to the remote provisioner or keys are being currently fetched and will
+     * be available soon.
+     * @hide */
+    public static final int RKP_TEMPORARILY_UNAVAILABLE = 1;
+    /**
+     * Permanent failure: The RKP server has declined issuance of keys to this device. Either
+     * because the device is not registered with the server or the server considers the device
+     * not to be trustworthy.
+     * @hide */
+    public static final int RKP_SERVER_REFUSED_ISSUANCE = 2;
+    /**
+     * The RKP server is unavailable due to lack of connectivity. The caller should re-try
+     * when the device has connectivity again.
+     * @hide */
+    public static final int RKP_FETCHING_PENDING_CONNECTIVITY = 3;
+
     // Constants for encoding information about the error encountered:
     // Whether the error relates to the system state/implementation as a whole, or a specific key.
     private static final int IS_SYSTEM_ERROR = 1 << 1;
@@ -148,6 +229,21 @@
     // The internal error code. NOT to be returned directly to callers or made part of the
     // public API.
     private final int mErrorCode;
+    // The Remote Key Provisioning status. Applicable if and only if {@link #mErrorCode} is equal
+    // to {@link ResponseCode.OUT_OF_KEYS}.
+    private final int mRkpStatus;
+
+    private static int initializeRkpStatusForRegularErrors(int errorCode) {
+        // Check if the system code mistakenly called a constructor of KeyStoreException with
+        // the OUT_OF_KEYS error code but without RKP status.
+        if (errorCode == ResponseCode.OUT_OF_KEYS) {
+            Log.e(TAG, "RKP error code without RKP status");
+            // Set RKP status to RKP_SERVER_REFUSED_ISSUANCE so that the caller never retries.
+            return RKP_SERVER_REFUSED_ISSUANCE;
+        } else {
+            return RKP_SUCCESS;
+        }
+    }
 
     /**
      * @hide
@@ -155,6 +251,7 @@
     public KeyStoreException(int errorCode, @Nullable String message) {
         super(message);
         mErrorCode = errorCode;
+        mRkpStatus = initializeRkpStatusForRegularErrors(errorCode);
     }
 
     /**
@@ -165,6 +262,19 @@
         super(message + " (internal Keystore code: " + errorCode + " message: "
                 + keystoreErrorMessage + ")");
         mErrorCode = errorCode;
+        mRkpStatus = initializeRkpStatusForRegularErrors(errorCode);
+    }
+
+    /**
+     * @hide
+     */
+    public KeyStoreException(int errorCode, @Nullable String message, int rkpStatus) {
+        super(message);
+        mErrorCode = errorCode;
+        mRkpStatus = rkpStatus;
+        if (mErrorCode != ResponseCode.OUT_OF_KEYS) {
+            Log.e(TAG, "Providing RKP status for error code " + errorCode + " has no effect.");
+        }
     }
 
     /**
@@ -198,6 +308,17 @@
      */
     public boolean isTransientFailure() {
         PublicErrorInformation failureInfo = getErrorInformation(mErrorCode);
+        // Special-case handling for RKP failures:
+        if (mRkpStatus != RKP_SUCCESS && mErrorCode == ResponseCode.OUT_OF_KEYS) {
+            switch (mRkpStatus) {
+                case RKP_TEMPORARILY_UNAVAILABLE:
+                case RKP_FETCHING_PENDING_CONNECTIVITY:
+                    return true;
+                case RKP_SERVER_REFUSED_ISSUANCE:
+                default:
+                    return false;
+            }
+        }
         return (failureInfo.indicators & IS_TRANSIENT_ERROR) != 0;
     }
 
@@ -225,6 +346,34 @@
         return (failureInfo.indicators & IS_SYSTEM_ERROR) != 0;
     }
 
+    /**
+     * Returns the re-try policy for transient failures. Valid only if
+     * {@link #isTransientFailure()} returns {@code True}.
+     */
+    @RetryPolicy
+    public int getRetryPolicy() {
+        PublicErrorInformation failureInfo = getErrorInformation(mErrorCode);
+        // Special-case handling for RKP failures:
+        if (mRkpStatus != RKP_SUCCESS) {
+            switch (mRkpStatus) {
+                case RKP_TEMPORARILY_UNAVAILABLE:
+                    return RETRY_WITH_EXPONENTIAL_BACKOFF;
+                case RKP_FETCHING_PENDING_CONNECTIVITY:
+                    return RETRY_WHEN_CONNECTIVITY_AVAILABLE;
+                case RKP_SERVER_REFUSED_ISSUANCE:
+                    return RETRY_NEVER;
+                default:
+                    return (failureInfo.indicators & IS_TRANSIENT_ERROR) != 0
+                            ? RETRY_WITH_EXPONENTIAL_BACKOFF : RETRY_NEVER;
+            }
+        }
+        if ((failureInfo.indicators & IS_TRANSIENT_ERROR) != 0) {
+            return RETRY_WITH_EXPONENTIAL_BACKOFF;
+        } else {
+            return RETRY_NEVER;
+        }
+    }
+
     @Override
     public String toString() {
         String errorCodes = String.format(" (public error code: %d internal Keystore code: %d)",
@@ -469,5 +618,7 @@
                 new PublicErrorInformation(0, ERROR_KEY_CORRUPTED));
         sErrorCodeToFailureInfo.put(ResponseCode.KEY_PERMANENTLY_INVALIDATED,
                 new PublicErrorInformation(0, ERROR_KEY_DOES_NOT_EXIST));
+        sErrorCodeToFailureInfo.put(ResponseCode.OUT_OF_KEYS,
+                new PublicErrorInformation(IS_SYSTEM_ERROR, ERROR_ATTESTATION_KEYS_UNAVAILABLE));
     }
 }
diff --git a/keystore/java/android/security/keystore/KeyGenParameterSpec.java b/keystore/java/android/security/keystore/KeyGenParameterSpec.java
index 54bab4a..ffd041f6 100644
--- a/keystore/java/android/security/keystore/KeyGenParameterSpec.java
+++ b/keystore/java/android/security/keystore/KeyGenParameterSpec.java
@@ -1637,8 +1637,8 @@
          * Sets whether the keystore requires the screen to be unlocked before allowing decryption
          * using this key. If this is set to {@code true}, any attempt to decrypt or sign using this
          * key while the screen is locked will fail. A locked device requires a PIN, password,
-         * biometric, or other trusted factor to access. While the screen is locked, the key can
-         * still be used for encryption or signature verification.
+         * biometric, or other trusted factor to access. While the screen is locked, any associated
+         * public key can still be used (e.g for signature verification).
          */
         @NonNull
         public Builder setUnlockedDeviceRequired(boolean unlockedDeviceRequired) {
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java
index e7961c9..5950b5b 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java
@@ -28,7 +28,6 @@
 import android.os.Build;
 import android.os.RemoteException;
 import android.security.GenerateRkpKey;
-import android.security.GenerateRkpKeyException;
 import android.security.KeyPairGeneratorSpec;
 import android.security.KeyStore2;
 import android.security.KeyStoreException;
@@ -618,18 +617,44 @@
 
     @Override
     public KeyPair generateKeyPair() {
-        try {
-            return generateKeyPairHelper();
-        } catch (GenerateRkpKeyException e) {
-            try {
-                return generateKeyPairHelper();
-            } catch (GenerateRkpKeyException f) {
-                throw new ProviderException("Failed to provision new attestation keys.");
+        GenerateKeyPairHelperResult result = new GenerateKeyPairHelperResult(0, null);
+        for (int i = 0; i < 2; i++) {
+            /**
+             * NOTE: There is no need to delay between re-tries because the call to
+             * GenerateRkpKey.notifyEmpty() will delay for a while before returning.
+             */
+            result = generateKeyPairHelper();
+            if (result.rkpStatus == KeyStoreException.RKP_SUCCESS) {
+                return result.keyPair;
             }
         }
+
+        // RKP failure
+        if (result.rkpStatus != KeyStoreException.RKP_SUCCESS) {
+            KeyStoreException ksException = new KeyStoreException(ResponseCode.OUT_OF_KEYS,
+                    "Could not get RKP keys", result.rkpStatus);
+            throw new ProviderException("Failed to provision new attestation keys.", ksException);
+        }
+
+        return result.keyPair;
+    }
+
+    private static class GenerateKeyPairHelperResult {
+        // Zero indicates success, non-zero indicates failure. Values should be
+        // {@link android.security.KeyStoreException#RKP_TEMPORARILY_UNAVAILABLE},
+        // {@link android.security.KeyStoreException#RKP_SERVER_REFUSED_ISSUANCE},
+        // {@link android.security.KeyStoreException#RKP_FETCHING_PENDING_CONNECTIVITY}
+        public final int rkpStatus;
+        @Nullable
+        public final KeyPair keyPair;
+
+        private GenerateKeyPairHelperResult(int rkpStatus, KeyPair keyPair) {
+            this.rkpStatus = rkpStatus;
+            this.keyPair = keyPair;
+        }
     }
 
-    private KeyPair generateKeyPairHelper() throws GenerateRkpKeyException {
+    private GenerateKeyPairHelperResult generateKeyPairHelper() {
         if (mKeyStore == null || mSpec == null) {
             throw new IllegalStateException("Not initialized");
         }
@@ -679,7 +704,8 @@
                 Log.d(TAG, "Couldn't connect to the RemoteProvisioner backend.", e);
             }
             success = true;
-            return new KeyPair(publicKey, publicKey.getPrivateKey());
+            KeyPair kp = new KeyPair(publicKey, publicKey.getPrivateKey());
+            return new GenerateKeyPairHelperResult(0, kp);
         } catch (android.security.KeyStoreException e) {
             switch (e.getErrorCode()) {
                 case KeymasterDefs.KM_ERROR_HARDWARE_TYPE_UNAVAILABLE:
@@ -688,11 +714,19 @@
                     GenerateRkpKey keyGen = new GenerateRkpKey(ActivityThread
                             .currentApplication());
                     try {
+                        //TODO: When detailed error information is available from the remote
+                        //provisioner, propagate it up.
                         keyGen.notifyEmpty(securityLevel);
                     } catch (RemoteException f) {
-                        throw new ProviderException("Failed to talk to RemoteProvisioner", f);
+                        KeyStoreException ksException = new KeyStoreException(
+                                ResponseCode.OUT_OF_KEYS,
+                                "Remote exception: " + f.getMessage(),
+                                KeyStoreException.RKP_TEMPORARILY_UNAVAILABLE);
+                        throw new ProviderException("Failed to talk to RemoteProvisioner",
+                                ksException);
                     }
-                    throw new GenerateRkpKeyException();
+                    return new GenerateKeyPairHelperResult(
+                            KeyStoreException.RKP_TEMPORARILY_UNAVAILABLE, null);
                 default:
                     ProviderException p = new ProviderException("Failed to generate key pair.", e);
                     if ((mSpec.getPurposes() & KeyProperties.PURPOSE_WRAP_KEY) != 0) {
diff --git a/libs/WindowManager/Jetpack/tests/OWNERS b/libs/WindowManager/Jetpack/tests/OWNERS
index f2c3388..ac522b2 100644
--- a/libs/WindowManager/Jetpack/tests/OWNERS
+++ b/libs/WindowManager/Jetpack/tests/OWNERS
@@ -1,4 +1,4 @@
-# Bug component: 909476
+# Bug component: 1157642
 # includes OWNERS from parent directories
 charlesccchen@google.com
 diegovela@google.com
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
index f0b2716..a201616 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
@@ -825,6 +825,10 @@
     }
 
     private void fadeExistingPip(boolean show) {
+        if (mLeash == null || !mLeash.isValid()) {
+            Log.w(TAG, "Invalid leash on fadeExistingPip: " + mLeash);
+            return;
+        }
         final float alphaStart = show ? 0 : 1;
         final float alphaEnd = show ? 1 : 0;
         mPipAnimationController
diff --git a/libs/WindowManager/Shell/tests/OWNERS b/libs/WindowManager/Shell/tests/OWNERS
index f49e80a..c877250 100644
--- a/libs/WindowManager/Shell/tests/OWNERS
+++ b/libs/WindowManager/Shell/tests/OWNERS
@@ -1,4 +1,4 @@
-# Bug component: 909476
+# Bug component: 1157642
 # includes OWNERS from parent directories
 natanieljr@google.com
 pablogamito@google.com
diff --git a/libs/hwui/jni/Bitmap.cpp b/libs/hwui/jni/Bitmap.cpp
index 05278f2..4003f0b 100755
--- a/libs/hwui/jni/Bitmap.cpp
+++ b/libs/hwui/jni/Bitmap.cpp
@@ -686,16 +686,14 @@
                                           }
                                           return data->ptr != nullptr;
                                       }));
-        inPlaceCallback(std::move(data.ptr), data.size);
-        return STATUS_OK;
+        return inPlaceCallback(std::move(data.ptr), data.size);
     } else if (type == BlobType::ASHMEM) {
         int rawFd = -1;
         int32_t size = 0;
         ON_ERROR_RETURN(AParcel_readInt32(parcel, &size));
         ON_ERROR_RETURN(AParcel_readParcelFileDescriptor(parcel, &rawFd));
         android::base::unique_fd fd(rawFd);
-        ashmemCallback(std::move(fd), size);
-        return STATUS_OK;
+        return ashmemCallback(std::move(fd), size);
     } else {
         // Although the above if/else was "exhaustive" guard against unknown types
         return STATUS_UNKNOWN_ERROR;
@@ -768,7 +766,7 @@
 // framework, we may need to update this maximum size.
 static constexpr size_t kMaxColorSpaceSerializedBytes = 80;
 
-static constexpr auto RuntimeException = "java/lang/RuntimeException";
+static constexpr auto BadParcelableException = "android/os/BadParcelableException";
 
 static bool validateImageInfo(const SkImageInfo& info, int32_t rowBytes) {
     // TODO: Can we avoid making a SkBitmap for this?
@@ -809,7 +807,7 @@
             kRGB_565_SkColorType != colorType &&
             kARGB_4444_SkColorType != colorType &&
             kAlpha_8_SkColorType != colorType) {
-        jniThrowExceptionFmt(env, RuntimeException,
+        jniThrowExceptionFmt(env, BadParcelableException,
                              "Bitmap_createFromParcel unknown colortype: %d\n", colorType);
         return NULL;
     }
@@ -821,7 +819,7 @@
         return NULL;
     }
     if (!Bitmap::computeAllocationSize(rowBytes, height, &allocationSize)) {
-        jniThrowExceptionFmt(env, RuntimeException,
+        jniThrowExceptionFmt(env, BadParcelableException,
                              "Received bad bitmap size: width=%d, height=%d, rowBytes=%d", width,
                              height, rowBytes);
         return NULL;
@@ -831,13 +829,23 @@
             p.get(),
             // In place callback
             [&](std::unique_ptr<int8_t[]> buffer, int32_t size) {
+                if (allocationSize > size) {
+                    android_errorWriteLog(0x534e4554, "213169612");
+                    return STATUS_BAD_VALUE;
+                }
                 nativeBitmap = Bitmap::allocateHeapBitmap(allocationSize, imageInfo, rowBytes);
                 if (nativeBitmap) {
-                    memcpy(nativeBitmap->pixels(), buffer.get(), size);
+                    memcpy(nativeBitmap->pixels(), buffer.get(), allocationSize);
+                    return STATUS_OK;
                 }
+                return STATUS_NO_MEMORY;
             },
             // Ashmem callback
             [&](android::base::unique_fd fd, int32_t size) {
+                if (allocationSize > size) {
+                    android_errorWriteLog(0x534e4554, "213169612");
+                    return STATUS_BAD_VALUE;
+                }
                 int flags = PROT_READ;
                 if (isMutable) {
                     flags |= PROT_WRITE;
@@ -846,18 +854,21 @@
                 if (addr == MAP_FAILED) {
                     const int err = errno;
                     ALOGW("mmap failed, error %d (%s)", err, strerror(err));
-                    return;
+                    return STATUS_NO_MEMORY;
                 }
                 nativeBitmap =
                         Bitmap::createFrom(imageInfo, rowBytes, fd.release(), addr, size, !isMutable);
+                return STATUS_OK;
             });
-    if (error != STATUS_OK) {
+
+    if (error != STATUS_OK && error != STATUS_NO_MEMORY) {
         // TODO: Stringify the error, see signalExceptionForError in android_util_Binder.cpp
-        jniThrowExceptionFmt(env, RuntimeException, "Failed to read from Parcel, error=%d", error);
+        jniThrowExceptionFmt(env, BadParcelableException, "Failed to read from Parcel, error=%d",
+                             error);
         return nullptr;
     }
-    if (!nativeBitmap) {
-        jniThrowRuntimeException(env, "Could not allocate java pixel ref.");
+    if (error == STATUS_NO_MEMORY || !nativeBitmap) {
+        jniThrowRuntimeException(env, "Could not allocate bitmap data.");
         return nullptr;
     }
 
diff --git a/media/TEST_MAPPING b/media/TEST_MAPPING
index a7ed091..4385a80 100644
--- a/media/TEST_MAPPING
+++ b/media/TEST_MAPPING
@@ -1,6 +1,14 @@
 {
   "presubmit": [
     {
+      "name": "CtsCameraTestCases",
+      "options" : [
+        {
+          "include-filter": "android.hardware.camera2.cts.ImageReaderTest#testP010"
+        }
+      ]
+    },
+    {
       "name": "GtsMediaTestCases",
       "options" : [
         {
diff --git a/media/jni/android_media_ImageReader.cpp b/media/jni/android_media_ImageReader.cpp
index 5174c0c..f8066fe 100644
--- a/media/jni/android_media_ImageReader.cpp
+++ b/media/jni/android_media_ImageReader.cpp
@@ -589,6 +589,12 @@
                 // (HAL_PIXEL_FORMAT_YCbCr_420_888) as HAL_PIXEL_FORMAT_YCbCr_420_888.
                 ALOGV("%s: Treat buffer format to 0x%x as HAL_PIXEL_FORMAT_YCbCr_420_888",
                         __FUNCTION__, bufferFormat);
+            } else if (imgReaderFmt == HAL_PIXEL_FORMAT_YCBCR_P010 &&
+                    isPossibly10BitYUV(bufferFormat)) {
+                // Treat formats that are compatible with flexible 10-bit YUV
+                // (HAL_PIXEL_FORMAT_YCBCR_P010) as HAL_PIXEL_FORMAT_YCBCR_P010.
+                ALOGV("%s: Treat buffer format to 0x%x as HAL_PIXEL_FORMAT_YCBCR_P010",
+                        __FUNCTION__, bufferFormat);
             } else if (imgReaderFmt == HAL_PIXEL_FORMAT_BLOB &&
                     bufferFormat == HAL_PIXEL_FORMAT_RGBA_8888) {
                 // Using HAL_PIXEL_FORMAT_RGBA_8888 Gralloc buffers containing JPEGs to get around
diff --git a/media/jni/android_media_Utils.cpp b/media/jni/android_media_Utils.cpp
index 39b560b..f4a39b3 100644
--- a/media/jni/android_media_Utils.cpp
+++ b/media/jni/android_media_Utils.cpp
@@ -17,7 +17,10 @@
 // #define LOG_NDEBUG 0
 #define LOG_TAG "AndroidMediaUtils"
 
+#include <aidl/android/hardware/graphics/common/PlaneLayoutComponentType.h>
 #include <hardware/camera3.h>
+#include <ui/GraphicBufferMapper.h>
+#include <ui/GraphicTypes.h>
 #include <utils/Log.h>
 #include "android_media_Utils.h"
 
@@ -81,6 +84,32 @@
     }
 }
 
+bool isPossibly10BitYUV(PixelFormat format) {
+    switch (static_cast<int>(format)) {
+        case HAL_PIXEL_FORMAT_RGBA_8888:
+        case HAL_PIXEL_FORMAT_RGBX_8888:
+        case HAL_PIXEL_FORMAT_RGB_888:
+        case HAL_PIXEL_FORMAT_RGB_565:
+        case HAL_PIXEL_FORMAT_BGRA_8888:
+        case HAL_PIXEL_FORMAT_Y8:
+        case HAL_PIXEL_FORMAT_Y16:
+        case HAL_PIXEL_FORMAT_RAW16:
+        case HAL_PIXEL_FORMAT_RAW12:
+        case HAL_PIXEL_FORMAT_RAW10:
+        case HAL_PIXEL_FORMAT_RAW_OPAQUE:
+        case HAL_PIXEL_FORMAT_BLOB:
+        case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
+        case HAL_PIXEL_FORMAT_YV12:
+        case HAL_PIXEL_FORMAT_YCbCr_420_888:
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+            return false;
+
+        case HAL_PIXEL_FORMAT_YCBCR_P010:
+        default:
+            return true;
+    }
+}
+
 uint32_t Image_getBlobSize(LockedImage* buffer, bool usingRGBAOverride) {
     ALOGV("%s", __FUNCTION__);
     LOG_ALWAYS_FATAL_IF(buffer == NULL, "Input buffer is NULL!!!");
@@ -279,6 +308,27 @@
                 return BAD_VALUE;
             }
 
+            if (buffer->dataCb && buffer->dataCr) {
+                pData =
+                    (idx == 0) ?
+                        buffer->data :
+                    (idx == 1) ?
+                        buffer->dataCb :
+                    buffer->dataCr;
+                // only map until last pixel
+                if (idx == 0) {
+                    pStride = 2;
+                    rStride = buffer->stride;
+                    dataSize = buffer->stride * (buffer->height - 1) + buffer->width * 2;
+                } else {
+                    pStride = buffer->chromaStep;
+                    rStride = buffer->chromaStride;
+                    dataSize = buffer->chromaStride * (buffer->height / 2 - 1) +
+                            buffer->chromaStep * (buffer->width / 2);
+                }
+                break;
+            }
+
             ySize = (buffer->stride * 2) * buffer->height;
             cSize = ySize / 2;
             pStride = (idx == 0) ? 2 : 4;
@@ -404,6 +454,7 @@
             rStride = buffer->stride * 3;
             break;
         default:
+            ALOGV("%s: unrecognized format 0x%x", __FUNCTION__, fmt);
             return BAD_VALUE;
     }
 
@@ -415,6 +466,79 @@
     return OK;
 }
 
+static status_t extractP010Gralloc4PlaneLayout(
+        sp<GraphicBuffer> buffer, void *pData, int format, LockedImage *outputImage) {
+    using aidl::android::hardware::graphics::common::PlaneLayoutComponent;
+    using aidl::android::hardware::graphics::common::PlaneLayoutComponentType;
+
+    GraphicBufferMapper& mapper = GraphicBufferMapper::get();
+    std::vector<ui::PlaneLayout> planeLayouts;
+    status_t res = mapper.getPlaneLayouts(buffer->handle, &planeLayouts);
+    if (res != OK) {
+        return res;
+    }
+    constexpr int64_t Y_PLANE_COMPONENTS = int64_t(PlaneLayoutComponentType::Y);
+    constexpr int64_t CBCR_PLANE_COMPONENTS =
+        int64_t(PlaneLayoutComponentType::CB) | int64_t(PlaneLayoutComponentType::CR);
+    uint8_t *dataY = nullptr;
+    uint8_t *dataCb = nullptr;
+    uint8_t *dataCr = nullptr;
+    uint32_t strideY = 0;
+    uint32_t strideCbCr = 0;
+    for (const ui::PlaneLayout &layout : planeLayouts) {
+        ALOGV("gralloc4 plane: %s", layout.toString().c_str());
+        int64_t components = 0;
+        for (const PlaneLayoutComponent &component : layout.components) {
+            if (component.sizeInBits != 10) {
+                return BAD_VALUE;
+            }
+            components |= component.type.value;
+        }
+        if (components == Y_PLANE_COMPONENTS) {
+            if (layout.sampleIncrementInBits != 16) {
+                return BAD_VALUE;
+            }
+            if (layout.components[0].offsetInBits != 6) {
+                return BAD_VALUE;
+            }
+            dataY = (uint8_t *)pData + layout.offsetInBytes;
+            strideY = layout.strideInBytes;
+        } else if (components == CBCR_PLANE_COMPONENTS) {
+            if (layout.sampleIncrementInBits != 32) {
+                return BAD_VALUE;
+            }
+            for (const PlaneLayoutComponent &component : layout.components) {
+                if (component.type.value == int64_t(PlaneLayoutComponentType::CB)
+                        && component.offsetInBits != 6) {
+                    return BAD_VALUE;
+                }
+                if (component.type.value == int64_t(PlaneLayoutComponentType::CR)
+                        && component.offsetInBits != 22) {
+                    return BAD_VALUE;
+                }
+            }
+            dataCb = (uint8_t *)pData + layout.offsetInBytes;
+            dataCr = (uint8_t *)pData + layout.offsetInBytes + 2;
+            strideCbCr = layout.strideInBytes;
+        } else {
+            return BAD_VALUE;
+        }
+    }
+
+    outputImage->data = dataY;
+    outputImage->width = buffer->getWidth();
+    outputImage->height = buffer->getHeight();
+    outputImage->format = format;
+    outputImage->flexFormat = HAL_PIXEL_FORMAT_YCBCR_P010;
+    outputImage->stride = strideY;
+
+    outputImage->dataCb = dataCb;
+    outputImage->dataCr = dataCr;
+    outputImage->chromaStride = strideCbCr;
+    outputImage->chromaStep = 4;
+    return OK;
+}
+
 status_t lockImageFromBuffer(sp<GraphicBuffer> buffer, uint32_t inUsage,
         const Rect& rect, int fenceFd, LockedImage* outputImage) {
     ALOGV("%s: Try to lock the GraphicBuffer", __FUNCTION__);
@@ -433,11 +557,12 @@
     status_t res;
     int format = buffer->getPixelFormat();
     int flexFormat = format;
+
     if (isPossiblyYUV(format)) {
         res = buffer->lockAsyncYCbCr(inUsage, rect, &ycbcr, fenceFd);
 
         if (res != OK) {
-            ALOGW("lockAsyncYCbCr failed with error %d", res);
+            ALOGW("lockAsyncYCbCr failed with error %d (format = 0x%x)", res, format);
         }
 
         pData = ycbcr.y;
@@ -451,6 +576,11 @@
             ALOGE("Lock buffer failed!");
             return res;
         }
+        if (isPossibly10BitYUV(format)
+                && OK == extractP010Gralloc4PlaneLayout(buffer, pData, format, outputImage)) {
+            ALOGV("%s: Successfully locked the P010 image", __FUNCTION__);
+            return OK;
+        }
     }
 
     outputImage->data = reinterpret_cast<uint8_t*>(pData);
diff --git a/media/jni/android_media_Utils.h b/media/jni/android_media_Utils.h
index 12841c0..4feb4f51 100644
--- a/media/jni/android_media_Utils.h
+++ b/media/jni/android_media_Utils.h
@@ -35,6 +35,8 @@
 
 bool isPossiblyYUV(PixelFormat format);
 
+bool isPossibly10BitYUV(PixelFormat format);
+
 status_t getLockedImageInfo(LockedImage* buffer, int idx, int32_t containerFormat,
         uint8_t **base, uint32_t *size, int *pixelStride, int *rowStride);
 
diff --git a/mms/OWNERS b/mms/OWNERS
index 2e419c1..7daef4e 100644
--- a/mms/OWNERS
+++ b/mms/OWNERS
@@ -1,18 +1,4 @@
 set noparent
 
-tgunn@google.com
-breadley@google.com
-rgreenwalt@google.com
-amitmahajan@google.com
-fionaxu@google.com
-jackyu@google.com
-jminjie@google.com
-satk@google.com
-shuoq@google.com
-sarahchin@google.com
-xiaotonj@google.com
-huiwang@google.com
-jayachandranc@google.com
-chinmayd@google.com
-amruthr@google.com
-sasindran@google.com
+file:platform/frameworks/base:/telephony/OWNERS
+
diff --git a/packages/CarrierDefaultApp/OWNERS b/packages/CarrierDefaultApp/OWNERS
index a2352e2..447cd51 100644
--- a/packages/CarrierDefaultApp/OWNERS
+++ b/packages/CarrierDefaultApp/OWNERS
@@ -1,18 +1,3 @@
 set noparent
-tgunn@google.com
-breadley@google.com
-rgreenwalt@google.com
-amitmahajan@google.com
-fionaxu@google.com
-jackyu@google.com
-jminjie@google.com
-satk@google.com
-shuoq@google.com
-sarahchin@google.com
-xiaotonj@google.com
-huiwang@google.com
-jayachandranc@google.com
-chinmayd@google.com
-amruthr@google.com
-sasindran@google.com
 
+file:platform/frameworks/base:/telephony/OWNERS
diff --git a/packages/SettingsLib/res/drawable/ic_4g_lte_mobiledata.xml b/packages/SettingsLib/res/drawable/ic_4g_lte_mobiledata.xml
new file mode 100644
index 0000000..43a82fa
--- /dev/null
+++ b/packages/SettingsLib/res/drawable/ic_4g_lte_mobiledata.xml
@@ -0,0 +1,25 @@
+<!--
+     Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="42.3281dp"
+    android:height="24dp"
+    android:viewportWidth="42.3281"
+    android:viewportHeight="24">
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M10.7871,12.959H11.8477V14.1016H10.7871V16H9.3633V14.1016H5.6777L5.6367,13.2344L9.3164,7.4688H10.7871V12.959ZM7.1309,12.959H9.3633V9.3965L9.2578,9.584L7.1309,12.959ZM19.5586,14.8926C19.25,15.2949 18.8223,15.5996 18.2754,15.8066C17.7285,16.0137 17.1074,16.1172 16.4121,16.1172C15.6973,16.1172 15.0645,15.9551 14.5137,15.6309C13.9629,15.3066 13.5371,14.8438 13.2363,14.2422C12.9395,13.6367 12.7852,12.9316 12.7734,12.127V11.459C12.7734,10.1699 13.082,9.1641 13.6992,8.4414C14.3164,7.7148 15.1777,7.3516 16.2832,7.3516C17.2324,7.3516 17.9863,7.5859 18.5449,8.0547C19.1035,8.5234 19.4395,9.1992 19.5527,10.082H18.0996C17.9355,9.0547 17.3398,8.541 16.3125,8.541C15.6484,8.541 15.1426,8.7813 14.7949,9.2617C14.4512,9.7383 14.2734,10.4395 14.2617,11.3652V12.0215C14.2617,12.9434 14.4551,13.6602 14.8418,14.1719C15.2324,14.6797 15.7734,14.9336 16.4648,14.9336C17.2227,14.9336 17.7617,14.7617 18.082,14.418V12.748H16.3242V11.623H19.5586V14.8926ZM25.6582,14.8164H29.5312V16H24.1758V7.4688H25.6582V14.8164ZM35.625,8.6641H32.9648V16H31.4941V8.6641H28.8574V7.4688H35.625V8.6641ZM41.7363,12.1914H38.2324V14.8164H42.3281V16H36.75V7.4688H42.2871V8.6641H38.2324V11.0195H41.7363V12.1914Z" />
+
+</vector>
diff --git a/packages/SettingsLib/res/drawable/ic_4g_lte_plus_mobiledata.xml b/packages/SettingsLib/res/drawable/ic_4g_lte_plus_mobiledata.xml
new file mode 100644
index 0000000..b80c47a
--- /dev/null
+++ b/packages/SettingsLib/res/drawable/ic_4g_lte_plus_mobiledata.xml
@@ -0,0 +1,29 @@
+<!--
+     Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="49.65dp"
+    android:height="24dp"
+    android:viewportWidth="49.65"
+    android:viewportHeight="24">
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M10.7871,12.959H11.8477V14.1016H10.7871V16H9.3633V14.1016H5.6777L5.6367,13.2344L9.3164,7.4688H10.7871V12.959ZM7.1309,12.959H9.3633V9.3965L9.2578,9.584L7.1309,12.959ZM19.5586,14.8926C19.25,15.2949 18.8223,15.5996 18.2754,15.8066C17.7285,16.0137 17.1074,16.1172 16.4121,16.1172C15.6973,16.1172 15.0645,15.9551 14.5137,15.6309C13.9629,15.3066 13.5371,14.8438 13.2363,14.2422C12.9395,13.6367 12.7852,12.9316 12.7734,12.127V11.459C12.7734,10.1699 13.082,9.1641 13.6992,8.4414C14.3164,7.7148 15.1777,7.3516 16.2832,7.3516C17.2324,7.3516 17.9863,7.5859 18.5449,8.0547C19.1035,8.5234 19.4395,9.1992 19.5527,10.082H18.0996C17.9355,9.0547 17.3398,8.541 16.3125,8.541C15.6484,8.541 15.1426,8.7813 14.7949,9.2617C14.4512,9.7383 14.2734,10.4395 14.2617,11.3652V12.0215C14.2617,12.9434 14.4551,13.6602 14.8418,14.1719C15.2324,14.6797 15.7734,14.9336 16.4648,14.9336C17.2227,14.9336 17.7617,14.7617 18.082,14.418V12.748H16.3242V11.623H19.5586V14.8926ZM25.6582,14.8164H29.5312V16H24.1758V7.4688H25.6582V14.8164ZM35.625,8.6641H32.9648V16H31.4941V8.6641H28.8574V7.4688H35.625V8.6641ZM41.7363,12.1914H38.2324V14.8164H42.3281V16H36.75V7.4688H42.2871V8.6641H38.2324V11.0195H41.7363V12.1914Z" />
+
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M 47.3 9.74L 47.3 7.39L 46 7.39L 46 9.74L 43.65 9.74L 43.65 11.04L 46 11.04L 46 13.39L 47.3 13.39L 47.3 11.04L 49.65 11.04L 49.65 9.74Z" />
+
+</vector>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 534e41c..6ca15c1 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -1478,6 +1478,12 @@
     <!-- Content description of the data connection type LTE+. [CHAR LIMIT=NONE] -->
     <string name="data_connection_lte_plus">LTE+</string>
 
+    <!-- Content description of the data connection type 4G LTE . [CHAR LIMIT=NONE] -->
+    <string name="data_connection_4g_lte" translatable="false">4G LTE</string>
+
+    <!-- Content description of the data connection type 4G LTE+ . [CHAR LIMIT=NONE] -->
+    <string name="data_connection_4g_lte_plus" translatable="false">4G LTE+</string>
+
     <!-- Content description of the data connection type 5Ge with HTML styling. DO NOT TRANSLATE [CHAR LIMIT=NONE] -->
     <string name="data_connection_5ge_html" translate="false"> &lt;i>5G &lt;small>E&lt;/small>&lt;/i> </string>
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/mobile/MobileMappings.java b/packages/SettingsLib/src/com/android/settingslib/mobile/MobileMappings.java
index 5e91a14..c941954 100644
--- a/packages/SettingsLib/src/com/android/settingslib/mobile/MobileMappings.java
+++ b/packages/SettingsLib/src/com/android/settingslib/mobile/MobileMappings.java
@@ -160,6 +160,19 @@
                         TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA),
                         TelephonyIcons.FOUR_G_PLUS);
             }
+        } else if (config.show4glteForLte) {
+            networkToIconLookup.put(toIconKey(
+                    TelephonyManager.NETWORK_TYPE_LTE),
+                    TelephonyIcons.FOUR_G_LTE);
+            if (config.hideLtePlus) {
+                networkToIconLookup.put(toDisplayIconKey(
+                        TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA),
+                        TelephonyIcons.FOUR_G_LTE);
+            } else {
+                networkToIconLookup.put(toDisplayIconKey(
+                        TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA),
+                        TelephonyIcons.FOUR_G_LTE_PLUS);
+            }
         } else {
             networkToIconLookup.put(toIconKey(
                     TelephonyManager.NETWORK_TYPE_LTE),
@@ -200,6 +213,7 @@
         public boolean show4gFor3g = false;
         public boolean alwaysShowCdmaRssi = false;
         public boolean show4gForLte = false;
+        public boolean show4glteForLte = false;
         public boolean hideLtePlus = false;
         public boolean hspaDataDistinguishable;
         public boolean alwaysShowDataRatIcon = false;
@@ -228,6 +242,8 @@
                         CarrierConfigManager.KEY_ALWAYS_SHOW_DATA_RAT_ICON_BOOL);
                 config.show4gForLte = b.getBoolean(
                         CarrierConfigManager.KEY_SHOW_4G_FOR_LTE_DATA_ICON_BOOL);
+                config.show4glteForLte = b.getBoolean(
+                        CarrierConfigManager.KEY_SHOW_4GLTE_FOR_LTE_DATA_ICON_BOOL);
                 config.show4gFor3g = b.getBoolean(
                         CarrierConfigManager.KEY_SHOW_4G_FOR_3G_DATA_ICON_BOOL);
                 config.hideLtePlus = b.getBoolean(
diff --git a/packages/SettingsLib/src/com/android/settingslib/mobile/TelephonyIcons.java b/packages/SettingsLib/src/com/android/settingslib/mobile/TelephonyIcons.java
index d4e58f7..23e0923 100644
--- a/packages/SettingsLib/src/com/android/settingslib/mobile/TelephonyIcons.java
+++ b/packages/SettingsLib/src/com/android/settingslib/mobile/TelephonyIcons.java
@@ -39,6 +39,8 @@
     public static final int ICON_3G = R.drawable.ic_3g_mobiledata;
     public static final int ICON_4G = R.drawable.ic_4g_mobiledata;
     public static final int ICON_4G_PLUS = R.drawable.ic_4g_plus_mobiledata;
+    public static final int ICON_4G_LTE = R.drawable.ic_4g_lte_mobiledata;
+    public static final int ICON_4G_LTE_PLUS = R.drawable.ic_4g_lte_plus_mobiledata;
     public static final int ICON_5G_E = R.drawable.ic_5g_e_mobiledata;
     public static final int ICON_1X = R.drawable.ic_1x_mobiledata;
     public static final int ICON_5G = R.drawable.ic_5g_mobiledata;
@@ -225,6 +227,34 @@
             TelephonyIcons.ICON_LTE_PLUS
     );
 
+    public static final MobileIconGroup FOUR_G_LTE = new MobileIconGroup(
+            "4G LTE",
+            null,
+            null,
+            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
+            0,
+            0,
+            0,
+            0,
+            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
+            R.string.data_connection_4g_lte,
+            TelephonyIcons.ICON_4G_LTE
+    );
+
+    public static final MobileIconGroup FOUR_G_LTE_PLUS = new MobileIconGroup(
+            "4G LTE+",
+            null,
+            null,
+            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
+            0,
+            0,
+            0,
+            0,
+            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
+            R.string.data_connection_4g_lte_plus,
+            TelephonyIcons.ICON_4G_LTE_PLUS
+    );
+
     public static final MobileIconGroup LTE_CA_5G_E = new MobileIconGroup(
             "5Ge",
             null,
@@ -327,6 +357,8 @@
         ICON_NAME_TO_ICON.put("h+", H_PLUS);
         ICON_NAME_TO_ICON.put("4g", FOUR_G);
         ICON_NAME_TO_ICON.put("4g+", FOUR_G_PLUS);
+        ICON_NAME_TO_ICON.put("4glte", FOUR_G_LTE);
+        ICON_NAME_TO_ICON.put("4glte+", FOUR_G_LTE_PLUS);
         ICON_NAME_TO_ICON.put("5ge", LTE_CA_5G_E);
         ICON_NAME_TO_ICON.put("lte", LTE);
         ICON_NAME_TO_ICON.put("lte+", LTE_PLUS);
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index c03ed03..208bfbbf 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -609,6 +609,9 @@
     <!-- Permission required for ATS test - CarDevicePolicyManagerTest -->
     <uses-permission android:name="android.permission.LOCK_DEVICE" />
 
+    <!-- Permission required for CTS test - CtsKeystoreTestCases -->
+    <uses-permission android:name="android.permission.REQUEST_UNIQUE_ID_ATTESTATION" />
+
     <application android:label="@string/app_label"
                 android:theme="@android:style/Theme.DeviceDefault.DayNight"
                 android:defaultToDeviceProtectedStorage="true"
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java
index 96ae646..290bf0d 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java
@@ -41,26 +41,23 @@
 
 import javax.inject.Inject;
 
-import dagger.Lazy;
-
 public class GlobalActionsImpl implements GlobalActions, CommandQueue.Callbacks {
 
     private final Context mContext;
-    private final Lazy<GlobalActionsDialogLite> mGlobalActionsDialogLazy;
     private final KeyguardStateController mKeyguardStateController;
     private final DeviceProvisionedController mDeviceProvisionedController;
     private final BlurUtils mBlurUtils;
     private final CommandQueue mCommandQueue;
-    private GlobalActionsDialogLite mGlobalActionsDialog;
+    private final GlobalActionsDialogLite mGlobalActionsDialog;
     private boolean mDisabled;
 
     @Inject
     public GlobalActionsImpl(Context context, CommandQueue commandQueue,
-            Lazy<GlobalActionsDialogLite> globalActionsDialogLazy, BlurUtils blurUtils,
+            GlobalActionsDialogLite globalActionsDialog, BlurUtils blurUtils,
             KeyguardStateController keyguardStateController,
             DeviceProvisionedController deviceProvisionedController) {
         mContext = context;
-        mGlobalActionsDialogLazy = globalActionsDialogLazy;
+        mGlobalActionsDialog = globalActionsDialog;
         mKeyguardStateController = keyguardStateController;
         mDeviceProvisionedController = deviceProvisionedController;
         mCommandQueue = commandQueue;
@@ -71,16 +68,12 @@
     @Override
     public void destroy() {
         mCommandQueue.removeCallback(this);
-        if (mGlobalActionsDialog != null) {
-            mGlobalActionsDialog.destroy();
-            mGlobalActionsDialog = null;
-        }
+        mGlobalActionsDialog.destroy();
     }
 
     @Override
     public void showGlobalActions(GlobalActionsManager manager) {
         if (mDisabled) return;
-        mGlobalActionsDialog = mGlobalActionsDialogLazy.get();
         mGlobalActionsDialog.showOrHideDialog(mKeyguardStateController.isShowing(),
                 mDeviceProvisionedController.isDeviceProvisioned(), null /* view */);
     }
@@ -189,7 +182,7 @@
         final boolean disabled = (state2 & DISABLE2_GLOBAL_ACTIONS) != 0;
         if (displayId != mContext.getDisplayId() || disabled == mDisabled) return;
         mDisabled = disabled;
-        if (disabled && mGlobalActionsDialog != null) {
+        if (disabled) {
             mGlobalActionsDialog.dismissDialog();
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java b/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java
index e9dea65..d558336 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java
@@ -237,7 +237,7 @@
             String subjectDate = DateFormat.getDateTimeInstance().format(new Date(mImageTime));
             String subject = String.format(SCREENSHOT_SHARE_SUBJECT_TEMPLATE, subjectDate);
             Intent sharingIntent = new Intent(Intent.ACTION_SEND);
-            sharingIntent.setType("image/png");
+            sharingIntent.setDataAndType(uri, "image/png");
             sharingIntent.putExtra(Intent.EXTRA_STREAM, uri);
             // Include URI in ClipData also, so that grantPermission picks it up.
             // We don't use setData here because some apps interpret this as "to:".
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
index f14cc93c..9f44060 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
@@ -279,11 +279,11 @@
 
         @Override
         public void onThemeChanged() {
-            updateShowEmptyShadeView();
             mView.updateCornerRadius();
             mView.updateBgColor();
             mView.updateDecorViews();
             mView.reinflateViews();
+            updateShowEmptyShadeView();
             updateFooter();
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
index 2c70a5f..c4567df 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
@@ -376,6 +376,11 @@
 
         final float stackHeight = ambientState.getStackHeight()  - shelfHeight - scrimPadding;
         final float stackEndHeight = ambientState.getStackEndHeight() - shelfHeight - scrimPadding;
+        if (stackEndHeight == 0f) {
+            // This should not happen, since even when the shade is empty we show EmptyShadeView
+            // but check just in case, so we don't return infinity or NaN.
+            return 0f;
+        }
         return stackHeight / stackEndHeight;
     }
 
diff --git a/services/core/Android.bp b/services/core/Android.bp
index b7e39a1..e4a0097 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -112,7 +112,6 @@
         "java/com/android/server/am/EventLogTags.logtags",
         "java/com/android/server/wm/EventLogTags.logtags",
         "java/com/android/server/policy/EventLogTags.logtags",
-        ":services.connectivity-tiramisu-sources",
     ],
 
     libs: [
@@ -165,9 +164,6 @@
         "overlayable_policy_aidl-java",
         "SurfaceFlingerProperties",
         "com.android.sysprop.watchdog",
-        // This is used for services.connectivity-tiramisu-sources.
-        // TODO: delete when NetworkStatsService is moved to the mainline module.
-        "net-utils-device-common-bpf",
     ],
     javac_shard_size: 50,
 }
diff --git a/services/core/java/com/android/server/VcnManagementService.java b/services/core/java/com/android/server/VcnManagementService.java
index 2d328d8..210532a 100644
--- a/services/core/java/com/android/server/VcnManagementService.java
+++ b/services/core/java/com/android/server/VcnManagementService.java
@@ -153,7 +153,7 @@
 public class VcnManagementService extends IVcnManagementService.Stub {
     @NonNull private static final String TAG = VcnManagementService.class.getSimpleName();
     private static final long DUMP_TIMEOUT_MILLIS = TimeUnit.SECONDS.toMillis(5);
-    private static final int LOCAL_LOG_LINE_COUNT = 128;
+    private static final int LOCAL_LOG_LINE_COUNT = 512;
 
     // Public for use in all other VCN classes
     @NonNull public static final LocalLog LOCAL_LOG = new LocalLog(LOCAL_LOG_LINE_COUNT);
@@ -456,7 +456,7 @@
             synchronized (mLock) {
                 final TelephonySubscriptionSnapshot oldSnapshot = mLastSnapshot;
                 mLastSnapshot = snapshot;
-                logDbg("new snapshot: " + mLastSnapshot);
+                logInfo("new snapshot: " + mLastSnapshot);
 
                 // Start any VCN instances as necessary
                 for (Entry<ParcelUuid, VcnConfig> entry : mConfigs.entrySet()) {
@@ -522,6 +522,8 @@
 
     @GuardedBy("mLock")
     private void stopVcnLocked(@NonNull ParcelUuid uuidToTeardown) {
+        logInfo("Stopping VCN config for subGrp: " + uuidToTeardown);
+
         // Remove in 2 steps. Make sure teardownAsync is triggered before removing from the map.
         final Vcn vcnToTeardown = mVcns.get(uuidToTeardown);
         if (vcnToTeardown == null) {
@@ -567,7 +569,7 @@
 
     @GuardedBy("mLock")
     private void startVcnLocked(@NonNull ParcelUuid subscriptionGroup, @NonNull VcnConfig config) {
-        logDbg("Starting VCN config for subGrp: " + subscriptionGroup);
+        logInfo("Starting VCN config for subGrp: " + subscriptionGroup);
 
         // TODO(b/193687515): Support multiple VCNs active at the same time
         if (!mVcns.isEmpty()) {
@@ -626,7 +628,7 @@
         if (!config.getProvisioningPackageName().equals(opPkgName)) {
             throw new IllegalArgumentException("Mismatched caller and VcnConfig creator");
         }
-        logDbg("VCN config updated for subGrp: " + subscriptionGroup);
+        logInfo("VCN config updated for subGrp: " + subscriptionGroup);
 
         mContext.getSystemService(AppOpsManager.class)
                 .checkPackage(mDeps.getBinderCallingUid(), config.getProvisioningPackageName());
@@ -652,7 +654,7 @@
     public void clearVcnConfig(@NonNull ParcelUuid subscriptionGroup, @NonNull String opPkgName) {
         requireNonNull(subscriptionGroup, "subscriptionGroup was null");
         requireNonNull(opPkgName, "opPkgName was null");
-        logDbg("VCN config cleared for subGrp: " + subscriptionGroup);
+        logInfo("VCN config cleared for subGrp: " + subscriptionGroup);
 
         mContext.getSystemService(AppOpsManager.class)
                 .checkPackage(mDeps.getBinderCallingUid(), opPkgName);
@@ -1050,24 +1052,34 @@
         Slog.d(TAG, msg, tr);
     }
 
+    private void logInfo(String msg) {
+        Slog.i(TAG, msg);
+        LOCAL_LOG.log("[INFO] [" + TAG + "] " + msg);
+    }
+
+    private void logInfo(String msg, Throwable tr) {
+        Slog.i(TAG, msg, tr);
+        LOCAL_LOG.log("[INFO] [" + TAG + "] " + msg + tr);
+    }
+
     private void logErr(String msg) {
         Slog.e(TAG, msg);
-        LOCAL_LOG.log(TAG + " ERR: " + msg);
+        LOCAL_LOG.log("[ERR] [" + TAG + "] " + msg);
     }
 
     private void logErr(String msg, Throwable tr) {
         Slog.e(TAG, msg, tr);
-        LOCAL_LOG.log(TAG + " ERR: " + msg + tr);
+        LOCAL_LOG.log("[ERR ] [" + TAG + "] " + msg + tr);
     }
 
     private void logWtf(String msg) {
         Slog.wtf(TAG, msg);
-        LOCAL_LOG.log(TAG + " WTF: " + msg);
+        LOCAL_LOG.log("[WTF] [" + TAG + "] " + msg);
     }
 
     private void logWtf(String msg, Throwable tr) {
         Slog.wtf(TAG, msg, tr);
-        LOCAL_LOG.log(TAG + " WTF: " + msg + tr);
+        LOCAL_LOG.log("[WTF ] [" + TAG + "] " + msg + tr);
     }
 
     /**
diff --git a/services/core/java/com/android/server/adb/AdbDebuggingManager.java b/services/core/java/com/android/server/adb/AdbDebuggingManager.java
index f591b26..297d28d 100644
--- a/services/core/java/com/android/server/adb/AdbDebuggingManager.java
+++ b/services/core/java/com/android/server/adb/AdbDebuggingManager.java
@@ -18,6 +18,7 @@
 
 import static com.android.internal.util.dump.DumpUtils.writeStringIfNotNull;
 
+import android.annotation.NonNull;
 import android.annotation.TestApi;
 import android.app.ActivityManager;
 import android.app.Notification;
@@ -170,6 +171,12 @@
         mAdbConnectionInfo = new AdbConnectionInfo();
     }
 
+    static void sendBroadcastWithDebugPermission(@NonNull Context context, @NonNull Intent intent,
+            @NonNull UserHandle userHandle) {
+        context.sendBroadcastAsUser(intent, userHandle,
+                android.Manifest.permission.MANAGE_DEBUGGING);
+    }
+
     class PairingThread extends Thread implements NsdManager.RegistrationListener {
         private NsdManager mNsdManager;
         private String mPublicKey;
@@ -1278,7 +1285,7 @@
                     ? AdbManager.WIRELESS_STATUS_CONNECTED
                     : AdbManager.WIRELESS_STATUS_DISCONNECTED);
             intent.putExtra(AdbManager.WIRELESS_DEBUG_PORT_EXTRA, port);
-            mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+            AdbDebuggingManager.sendBroadcastWithDebugPermission(mContext, intent, UserHandle.ALL);
         }
 
         private void onAdbdWifiServerConnected(int port) {
@@ -1350,7 +1357,8 @@
             if (publicKey == null) {
                 Intent intent = new Intent(AdbManager.WIRELESS_DEBUG_PAIRING_RESULT_ACTION);
                 intent.putExtra(AdbManager.WIRELESS_STATUS_EXTRA, AdbManager.WIRELESS_STATUS_FAIL);
-                mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+                AdbDebuggingManager.sendBroadcastWithDebugPermission(mContext, intent,
+                        UserHandle.ALL);
             } else {
                 Intent intent = new Intent(AdbManager.WIRELESS_DEBUG_PAIRING_RESULT_ACTION);
                 intent.putExtra(AdbManager.WIRELESS_STATUS_EXTRA,
@@ -1366,7 +1374,8 @@
                 device.guid = hostname;
                 device.connected = false;
                 intent.putExtra(AdbManager.WIRELESS_PAIR_DEVICE_EXTRA, device);
-                mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+                AdbDebuggingManager.sendBroadcastWithDebugPermission(mContext, intent,
+                        UserHandle.ALL);
                 // Add the key into the keystore
                 mAdbKeyStore.setLastConnectionTime(publicKey,
                         System.currentTimeMillis());
@@ -1380,14 +1389,14 @@
             intent.putExtra(AdbManager.WIRELESS_STATUS_EXTRA,
                     AdbManager.WIRELESS_STATUS_CONNECTED);
             intent.putExtra(AdbManager.WIRELESS_DEBUG_PORT_EXTRA, port);
-            mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+            AdbDebuggingManager.sendBroadcastWithDebugPermission(mContext, intent, UserHandle.ALL);
         }
 
         private void sendPairedDevicesToUI(Map<String, PairDevice> devices) {
             Intent intent = new Intent(AdbManager.WIRELESS_DEBUG_PAIRED_DEVICES_ACTION);
             // Map is not serializable, so need to downcast
             intent.putExtra(AdbManager.WIRELESS_DEVICES_EXTRA, (HashMap) devices);
-            mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+            AdbDebuggingManager.sendBroadcastWithDebugPermission(mContext, intent, UserHandle.ALL);
         }
 
         private void updateUIPairCode(String code) {
@@ -1397,7 +1406,7 @@
             intent.putExtra(AdbManager.WIRELESS_PAIRING_CODE_EXTRA, code);
             intent.putExtra(AdbManager.WIRELESS_STATUS_EXTRA,
                     AdbManager.WIRELESS_STATUS_PAIRING_CODE);
-            mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+            AdbDebuggingManager.sendBroadcastWithDebugPermission(mContext, intent, UserHandle.ALL);
         }
     }
 
diff --git a/services/core/java/com/android/server/adb/AdbService.java b/services/core/java/com/android/server/adb/AdbService.java
index 7a4d2ce..2845fbf 100644
--- a/services/core/java/com/android/server/adb/AdbService.java
+++ b/services/core/java/com/android/server/adb/AdbService.java
@@ -459,7 +459,7 @@
                 ? AdbManager.WIRELESS_STATUS_CONNECTED
                 : AdbManager.WIRELESS_STATUS_DISCONNECTED);
         intent.putExtra(AdbManager.WIRELESS_DEBUG_PORT_EXTRA, port);
-        mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+        AdbDebuggingManager.sendBroadcastWithDebugPermission(mContext, intent, UserHandle.ALL);
         Slog.i(TAG, "sent port broadcast port=" + port);
     }
 
diff --git a/services/core/java/com/android/server/clipboard/ClipboardService.java b/services/core/java/com/android/server/clipboard/ClipboardService.java
index a0c5aa3..863be98 100644
--- a/services/core/java/com/android/server/clipboard/ClipboardService.java
+++ b/services/core/java/com/android/server/clipboard/ClipboardService.java
@@ -582,7 +582,7 @@
 
     void setPrimaryClipInternal(PerUserClipboard clipboard, @Nullable ClipData clip,
             int uid) {
-        synchronized ("mLock") {
+        synchronized (mLock) {
             setPrimaryClipInternalLocked(clipboard, clip, uid, null);
         }
     }
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 35217db..33440a3 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -20,6 +20,7 @@
 import static android.Manifest.permission.CONTROL_VPN;
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
 import static android.net.RouteInfo.RTN_THROW;
 import static android.net.RouteInfo.RTN_UNREACHABLE;
 import static android.net.VpnManager.NOTIFICATION_CHANNEL_VPN;
@@ -2542,6 +2543,7 @@
                 req = new NetworkRequest.Builder()
                         .clearCapabilities()
                         .addTransportType(NetworkCapabilities.TRANSPORT_TEST)
+                        .addCapability(NET_CAPABILITY_NOT_VPN)
                         .build();
             } else {
                 // Basically, the request here is referring to the default request which is defined
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
index 4071858..7ff65f5 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
@@ -127,6 +127,7 @@
         // We'll not invalidate the active source on the hotplug event to pass CETC 11.2.2-2 ~ 3.
         if (!connected) {
             getWakeLock().release();
+            mService.getHdmiCecNetwork().removeDevicesConnectedToPort(portId);
         }
     }
 
@@ -274,7 +275,9 @@
         try {
             String iso3Language = new String(message.getParams(), 0, 3, "US-ASCII");
             Locale currentLocale = mService.getContext().getResources().getConfiguration().locale;
-            if (currentLocale.getISO3Language().equals(iso3Language)) {
+            String curIso3Language = mService.localeToMenuLanguage(currentLocale);
+            HdmiLogger.debug("handleSetMenuLanguage " + iso3Language + " cur:" + curIso3Language);
+            if (curIso3Language.equals(iso3Language)) {
                 // Do not switch language if the new language is the same as the current one.
                 // This helps avoid accidental country variant switching from en_US to en_AU
                 // due to the limitation of CEC. See the warning below.
@@ -286,7 +289,7 @@
             final List<LocaleInfo> localeInfos = LocalePicker.getAllAssetLocales(
                     mService.getContext(), false);
             for (LocaleInfo localeInfo : localeInfos) {
-                if (localeInfo.getLocale().getISO3Language().equals(iso3Language)) {
+                if (mService.localeToMenuLanguage(localeInfo.getLocale()).equals(iso3Language)) {
                     // WARNING: CEC adopts ISO/FDIS-2 for language code, while Android requires
                     // additional country variant to pinpoint the locale. This keeps the right
                     // locale from being chosen. 'eng' in the CEC command, for instance,
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
index 3d218cf..b1ffbda 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
@@ -1218,6 +1218,11 @@
     @ServiceThreadOnly
     void onHotplug(int portId, boolean connected) {
         assertRunOnServiceThread();
+
+        if (!connected) {
+            mService.getHdmiCecNetwork().removeCecSwitches(portId);
+        }
+
         // Turning System Audio Mode off when the AVR is unlugged or standby.
         // When the device is not unplugged but reawaken from standby, we check if the System
         // Audio Control Feature is enabled or not then decide if turning SAM on/off accordingly.
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecNetwork.java b/services/core/java/com/android/server/hdmi/HdmiCecNetwork.java
index 7ceaa95..72b79f4 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecNetwork.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecNetwork.java
@@ -269,7 +269,10 @@
             // The addition of a local device should not notify listeners
             return;
         }
-        if (old == null) {
+        if (info.getPhysicalAddress() == HdmiDeviceInfo.PATH_INVALID) {
+            // Don't notify listeners of devices that haven't reported their physical address yet
+            return;
+        } else if (old == null  || old.getPhysicalAddress() == HdmiDeviceInfo.PATH_INVALID) {
             invokeDeviceEventListener(info,
                     HdmiControlManager.DEVICE_EVENT_ADD_DEVICE);
         } else if (!old.equals(info)) {
@@ -296,7 +299,10 @@
         assertRunOnServiceThread();
         HdmiDeviceInfo old = addDeviceInfo(info);
 
-        if (old == null) {
+        if (info.getPhysicalAddress() == HdmiDeviceInfo.PATH_INVALID) {
+            // Don't notify listeners of devices that haven't reported their physical address yet
+            return;
+        } else if (old == null  || old.getPhysicalAddress() == HdmiDeviceInfo.PATH_INVALID) {
             invokeDeviceEventListener(info,
                     HdmiControlManager.DEVICE_EVENT_ADD_DEVICE);
         } else if (!old.equals(info)) {
@@ -370,10 +376,12 @@
     // This only applies to TV devices.
     // Returns true if the policy is set to true, and the device to check does not have
     // a parent CEC device (which should be the CEC-enabled switch) in the list.
+    // Devices with an invalid physical address are assumed to NOT be connected to a legacy switch.
     private boolean hideDevicesBehindLegacySwitch(HdmiDeviceInfo info) {
         return isLocalDeviceAddress(Constants.ADDR_TV)
                 && HdmiConfig.HIDE_DEVICES_BEHIND_LEGACY_SWITCH
-                && !isConnectedToCecSwitch(info.getPhysicalAddress(), getCecSwitches());
+                && !isConnectedToCecSwitch(info.getPhysicalAddress(), getCecSwitches())
+                && info.getPhysicalAddress() != HdmiDeviceInfo.PATH_INVALID;
     }
 
     /**
@@ -387,6 +395,10 @@
         HdmiDeviceInfo info = removeDeviceInfo(HdmiDeviceInfo.idForCecDevice(address));
 
         localDevice.mCecMessageCache.flushMessagesFrom(address);
+        if (info.getPhysicalAddress() == HdmiDeviceInfo.PATH_INVALID) {
+            // Don't notify listeners of devices that haven't reported their physical address yet
+            return;
+        }
         invokeDeviceEventListener(info,
                 HdmiControlManager.DEVICE_EVENT_REMOVE_DEVICE);
     }
@@ -498,6 +510,34 @@
     }
 
     /**
+     * Attempts to deduce the device type of a device given its logical address.
+     * If multiple types are possible, returns {@link HdmiDeviceInfo#DEVICE_RESERVED}.
+     */
+    private static int logicalAddressToDeviceType(int logicalAddress) {
+        switch (logicalAddress) {
+            case Constants.ADDR_TV:
+                return HdmiDeviceInfo.DEVICE_TV;
+            case Constants.ADDR_RECORDER_1:
+            case Constants.ADDR_RECORDER_2:
+            case Constants.ADDR_RECORDER_3:
+                return HdmiDeviceInfo.DEVICE_RECORDER;
+            case Constants.ADDR_TUNER_1:
+            case Constants.ADDR_TUNER_2:
+            case Constants.ADDR_TUNER_3:
+            case Constants.ADDR_TUNER_4:
+                return HdmiDeviceInfo.DEVICE_TUNER;
+            case Constants.ADDR_PLAYBACK_1:
+            case Constants.ADDR_PLAYBACK_2:
+            case Constants.ADDR_PLAYBACK_3:
+                return HdmiDeviceInfo.DEVICE_PLAYBACK;
+            case Constants.ADDR_AUDIO_SYSTEM:
+                return HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM;
+            default:
+                return HdmiDeviceInfo.DEVICE_RESERVED;
+        }
+    }
+
+    /**
      * Passively listen to incoming CEC messages.
      *
      * This shall not result in any CEC messages being sent.
@@ -510,7 +550,7 @@
         if (getCecDeviceInfo(sourceAddress) == null) {
             HdmiDeviceInfo newDevice = new HdmiDeviceInfo(sourceAddress,
                     HdmiDeviceInfo.PATH_INVALID, HdmiDeviceInfo.PORT_INVALID,
-                    HdmiDeviceInfo.DEVICE_RESERVED, Constants.UNKNOWN_VENDOR_ID,
+                    logicalAddressToDeviceType(sourceAddress), Constants.UNKNOWN_VENDOR_ID,
                     HdmiUtils.getDefaultDeviceName(sourceAddress));
             addCecDevice(newDevice);
         }
@@ -668,7 +708,7 @@
         return mCecSwitches;
     }
 
-    void removeDevicesConnectedToPort(int portId) {
+    void removeCecSwitches(int portId) {
         Iterator<Integer> it = mCecSwitches.iterator();
         while (it.hasNext()) {
             int path = it.next();
@@ -677,6 +717,11 @@
                 it.remove();
             }
         }
+    }
+
+    void removeDevicesConnectedToPort(int portId) {
+        removeCecSwitches(portId);
+
         List<Integer> toRemove = new ArrayList<>();
         for (int i = 0; i < mDeviceInfos.size(); i++) {
             int key = mDeviceInfos.keyAt(i);
@@ -788,7 +833,10 @@
     public void clearDeviceList() {
         assertRunOnServiceThread();
         for (HdmiDeviceInfo info : HdmiUtils.sparseArrayToList(mDeviceInfos)) {
-            if (info.getPhysicalAddress() == getPhysicalAddress()) {
+            if (info.getPhysicalAddress() == getPhysicalAddress()
+                    || info.getPhysicalAddress() == HdmiDeviceInfo.PATH_INVALID) {
+                // Don't notify listeners of local devices or devices that haven't reported their
+                // physical address yet
                 continue;
             }
             invokeDeviceEventListener(info,
@@ -835,10 +883,13 @@
      * on the current device.
      */
     int physicalAddressToPortId(int path) {
+        int physicalAddress = getPhysicalAddress();
+        if (path == physicalAddress) {
+            // The local device isn't connected to any port; assign portId 0
+            return Constants.CEC_SWITCH_HOME;
+        }
         int mask = 0xF000;
         int finalMask = 0xF000;
-        int physicalAddress;
-        physicalAddress = getPhysicalAddress();
         int maskedAddress = physicalAddress;
 
         while (maskedAddress != 0) {
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecStandbyModeHandler.java b/services/core/java/com/android/server/hdmi/HdmiCecStandbyModeHandler.java
index 1c296e5..8647680 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecStandbyModeHandler.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecStandbyModeHandler.java
@@ -83,7 +83,9 @@
     private final HdmiCecLocalDevice mDevice;
 
     private final SparseArray<CecMessageHandler> mCecMessageHandlers = new SparseArray<>();
-    private final CecMessageHandler mDefaultHandler = new Aborter(
+    private final CecMessageHandler mDefaultHandler;
+
+    private final CecMessageHandler mAborterUnrecognizedOpcode = new Aborter(
             Constants.ABORT_UNRECOGNIZED_OPCODE);
     private final CecMessageHandler mAborterIncorrectMode = new Aborter(
             Constants.ABORT_NOT_IN_CORRECT_MODE);
@@ -95,6 +97,10 @@
             mUserControlProcessedHandler = new UserControlProcessedHandler();
 
     private void addCommonHandlers() {
+        addHandler(Constants.MESSAGE_USER_CONTROL_PRESSED, mUserControlProcessedHandler);
+    }
+
+    private void addTvHandlers() {
         addHandler(Constants.MESSAGE_ACTIVE_SOURCE, mBystander);
         addHandler(Constants.MESSAGE_REQUEST_ACTIVE_SOURCE, mBystander);
         addHandler(Constants.MESSAGE_ROUTING_CHANGE, mBystander);
@@ -118,17 +124,13 @@
         addHandler(Constants.MESSAGE_REPORT_POWER_STATUS, mBypasser);
         addHandler(Constants.MESSAGE_GIVE_FEATURES, mBypasser);
 
-        addHandler(Constants.MESSAGE_USER_CONTROL_PRESSED, mUserControlProcessedHandler);
-
         addHandler(Constants.MESSAGE_GIVE_DEVICE_POWER_STATUS, mBypasser);
         addHandler(Constants.MESSAGE_ABORT, mBypasser);
         addHandler(Constants.MESSAGE_GET_CEC_VERSION, mBypasser);
 
         addHandler(Constants.MESSAGE_VENDOR_COMMAND_WITH_ID, mAborterIncorrectMode);
         addHandler(Constants.MESSAGE_SET_SYSTEM_AUDIO_MODE, mAborterIncorrectMode);
-    }
 
-    private void addTvHandlers() {
         addHandler(Constants.MESSAGE_IMAGE_VIEW_ON, mAutoOnHandler);
         addHandler(Constants.MESSAGE_TEXT_VIEW_ON, mAutoOnHandler);
 
@@ -153,6 +155,9 @@
         addCommonHandlers();
         if (mDevice.getType() == HdmiDeviceInfo.DEVICE_TV) {
             addTvHandlers();
+            mDefaultHandler = mAborterUnrecognizedOpcode;
+        } else {
+            mDefaultHandler = mBypasser;
         }
     }
 
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index 8dadf5a..a16bd3b 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -1251,10 +1251,6 @@
             device.onHotplug(portId, connected);
         }
 
-        if (!connected) {
-            mHdmiCecNetwork.removeDevicesConnectedToPort(portId);
-        }
-
         announceHotplugEvent(portId, connected);
     }
 
diff --git a/services/core/java/com/android/server/hdmi/HotplugDetectionAction.java b/services/core/java/com/android/server/hdmi/HotplugDetectionAction.java
index 4c4c978..3d77164 100644
--- a/services/core/java/com/android/server/hdmi/HotplugDetectionAction.java
+++ b/services/core/java/com/android/server/hdmi/HotplugDetectionAction.java
@@ -36,9 +36,9 @@
 final class HotplugDetectionAction extends HdmiCecFeatureAction {
     private static final String TAG = "HotPlugDetectionAction";
 
-    private static final int POLLING_INTERVAL_MS = 5000;
-    private static final int TIMEOUT_COUNT = 3;
-    private static final int AVR_COUNT_MAX = 3;
+    public static final int POLLING_INTERVAL_MS = 5000;
+    public static final int TIMEOUT_COUNT = 3;
+    public static final int AVR_COUNT_MAX = 3;
 
     // State in which waits for next polling
     private static final int STATE_WAIT_FOR_NEXT_POLLING = 1;
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java b/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java
index a73c8e0..0e4bbbb 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java
@@ -18,12 +18,14 @@
 
 import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_NONE;
 import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PATTERN;
+import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN;
 
 import android.app.ActivityManager;
 import android.app.admin.PasswordMetrics;
 import android.content.Context;
 import android.os.ShellCommand;
 import android.os.SystemProperties;
+import android.os.UserHandle;
 import android.text.TextUtils;
 import android.util.Slog;
 
@@ -48,6 +50,8 @@
     private static final String COMMAND_REMOVE_CACHE = "remove-cache";
     private static final String COMMAND_SET_ROR_PROVIDER_PACKAGE =
             "set-resume-on-reboot-provider-package";
+    private static final String COMMAND_REQUIRE_STRONG_AUTH =
+            "require-strong-auth";
     private static final String COMMAND_HELP = "help";
 
     private int mCurrentUserId;
@@ -97,6 +101,9 @@
                 case COMMAND_SET_ROR_PROVIDER_PACKAGE:
                     runSetResumeOnRebootProviderPackage();
                     return 0;
+                case COMMAND_REQUIRE_STRONG_AUTH:
+                    runRequireStrongAuth();
+                    return 0;
                 case COMMAND_HELP:
                     onHelp();
                     return 0;
@@ -192,6 +199,10 @@
             pw.println("    Sets the package name for server based resume on reboot service "
                     + "provider.");
             pw.println("");
+            pw.println("  require-strong-auth [--user USER_ID] <reason>");
+            pw.println("    Requires the strong authentication. The current supported reasons: "
+                    + "STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN.");
+            pw.println("");
         }
     }
 
@@ -288,6 +299,24 @@
         return true;
     }
 
+    private boolean runRequireStrongAuth() {
+        final String reason = mNew;
+        int strongAuthReason;
+        switch (reason) {
+            case "STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN":
+                strongAuthReason = STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN;
+                mCurrentUserId = UserHandle.USER_ALL;
+                break;
+            default:
+                getErrPrintWriter().println("Unsupported reason: " + reason);
+                return false;
+        }
+        mLockPatternUtils.requireStrongAuth(strongAuthReason, mCurrentUserId);
+        getOutPrintWriter().println("Require strong auth for USER_ID "
+                + mCurrentUserId + " because of " + mNew);
+        return true;
+    }
+
     private boolean runClear() {
         LockscreenCredential none = LockscreenCredential.createNone();
         if (!isNewCredentialSufficient(none)) {
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerInternal.java b/services/core/java/com/android/server/net/NetworkPolicyManagerInternal.java
index 8ef42ff..3cb5878 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerInternal.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerInternal.java
@@ -91,4 +91,10 @@
      */
     public abstract void setMeteredRestrictedPackagesAsync(
             Set<String> packageNames, int userId);
+
+    /** Informs that Low Power Standby has become active */
+    public abstract void setLowPowerStandbyActive(boolean active);
+
+    /** Informs that the Low Power Standby allowlist has changed */
+    public abstract void setLowPowerStandbyAllowlist(int[] uids);
 }
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 67b4469..ea851ba 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -46,17 +46,19 @@
 import static android.net.ConnectivityManager.BLOCKED_REASON_APP_STANDBY;
 import static android.net.ConnectivityManager.BLOCKED_REASON_BATTERY_SAVER;
 import static android.net.ConnectivityManager.BLOCKED_REASON_DOZE;
+import static android.net.ConnectivityManager.BLOCKED_REASON_LOW_POWER_STANDBY;
 import static android.net.ConnectivityManager.BLOCKED_REASON_NONE;
 import static android.net.ConnectivityManager.BLOCKED_REASON_RESTRICTED_MODE;
 import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_DOZABLE;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_LOW_POWER_STANDBY;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_POWERSAVE;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_RESTRICTED;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_STANDBY;
 import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_DISABLED;
 import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_ENABLED;
 import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_WHITELISTED;
 import static android.net.ConnectivityManager.TYPE_MOBILE;
-import static android.net.INetd.FIREWALL_CHAIN_DOZABLE;
-import static android.net.INetd.FIREWALL_CHAIN_POWERSAVE;
-import static android.net.INetd.FIREWALL_CHAIN_RESTRICTED;
-import static android.net.INetd.FIREWALL_CHAIN_STANDBY;
 import static android.net.INetd.FIREWALL_RULE_ALLOW;
 import static android.net.INetd.FIREWALL_RULE_DENY;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
@@ -69,11 +71,13 @@
 import static android.net.NetworkPolicyManager.ALLOWED_METERED_REASON_SYSTEM;
 import static android.net.NetworkPolicyManager.ALLOWED_METERED_REASON_USER_EXEMPTED;
 import static android.net.NetworkPolicyManager.ALLOWED_REASON_FOREGROUND;
+import static android.net.NetworkPolicyManager.ALLOWED_REASON_LOW_POWER_STANDBY_ALLOWLIST;
 import static android.net.NetworkPolicyManager.ALLOWED_REASON_NONE;
 import static android.net.NetworkPolicyManager.ALLOWED_REASON_POWER_SAVE_ALLOWLIST;
 import static android.net.NetworkPolicyManager.ALLOWED_REASON_POWER_SAVE_EXCEPT_IDLE_ALLOWLIST;
 import static android.net.NetworkPolicyManager.ALLOWED_REASON_RESTRICTED_MODE_PERMISSIONS;
 import static android.net.NetworkPolicyManager.ALLOWED_REASON_SYSTEM;
+import static android.net.NetworkPolicyManager.ALLOWED_REASON_TOP;
 import static android.net.NetworkPolicyManager.EXTRA_NETWORK_TEMPLATE;
 import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT;
 import static android.net.NetworkPolicyManager.POLICY_ALLOW_METERED_BACKGROUND;
@@ -87,6 +91,7 @@
 import static android.net.NetworkPolicyManager.RULE_TEMPORARY_ALLOW_METERED;
 import static android.net.NetworkPolicyManager.SUBSCRIPTION_OVERRIDE_UNMETERED;
 import static android.net.NetworkPolicyManager.isProcStateAllowedWhileIdleOrPowerSaveMode;
+import static android.net.NetworkPolicyManager.isProcStateAllowedWhileInLowPowerStandby;
 import static android.net.NetworkPolicyManager.isProcStateAllowedWhileOnRestrictBackground;
 import static android.net.NetworkPolicyManager.resolveNetworkId;
 import static android.net.NetworkPolicyManager.uidPoliciesToString;
@@ -477,6 +482,8 @@
     volatile boolean mRestrictBackgroundChangedInBsm;
     @GuardedBy("mUidRulesFirstLock")
     volatile boolean mRestrictedNetworkingMode;
+    @GuardedBy("mUidRulesFirstLock")
+    volatile boolean mLowPowerStandbyActive;
 
     private final boolean mSuppressDefaultPolicy;
 
@@ -516,6 +523,8 @@
     final SparseIntArray mUidFirewallPowerSaveRules = new SparseIntArray();
     @GuardedBy("mUidRulesFirstLock")
     final SparseIntArray mUidFirewallRestrictedModeRules = new SparseIntArray();
+    @GuardedBy("mUidRulesFirstLock")
+    final SparseIntArray mUidFirewallLowPowerStandbyModeRules = new SparseIntArray();
 
     /** Set of states for the child firewall chains. True if the chain is active. */
     @GuardedBy("mUidRulesFirstLock")
@@ -544,6 +553,9 @@
     @GuardedBy("mUidRulesFirstLock")
     private final SparseBooleanArray mPowerSaveTempWhitelistAppIds = new SparseBooleanArray();
 
+    @GuardedBy("mUidRulesFirstLock")
+    private final SparseBooleanArray mLowPowerStandbyAllowlistUids = new SparseBooleanArray();
+
     /**
      * UIDs that have been allowlisted temporarily to be able to have network access despite being
      * idle. Other power saving restrictions still apply.
@@ -3785,6 +3797,7 @@
                 fout.print("Restrict power: "); fout.println(mRestrictPower);
                 fout.print("Device idle: "); fout.println(mDeviceIdleMode);
                 fout.print("Restricted networking mode: "); fout.println(mRestrictedNetworkingMode);
+                fout.print("Low Power Standby mode: "); fout.println(mLowPowerStandbyActive);
                 synchronized (mMeteredIfacesLock) {
                     fout.print("Metered ifaces: ");
                     fout.println(mMeteredIfaces);
@@ -3920,6 +3933,18 @@
                     fout.decreaseIndent();
                 }
 
+                size = mLowPowerStandbyAllowlistUids.size();
+                if (size > 0) {
+                    fout.println("Low Power Standby allowlist uids:");
+                    fout.increaseIndent();
+                    for (int i = 0; i < size; i++) {
+                        fout.print("UID=");
+                        fout.print(mLowPowerStandbyAllowlistUids.keyAt(i));
+                        fout.println();
+                    }
+                    fout.decreaseIndent();
+                }
+
                 final SparseBooleanArray knownUids = new SparseBooleanArray();
                 collectKeys(mUidState, knownUids);
                 collectKeys(mUidBlockedState, knownUids);
@@ -4001,6 +4026,12 @@
         return isProcStateAllowedWhileIdleOrPowerSaveMode(uidState);
     }
 
+    @GuardedBy("mUidRulesFirstLock")
+    private boolean isUidTop(int uid) {
+        final UidState uidState = mUidState.get(uid);
+        return isProcStateAllowedWhileInLowPowerStandby(uidState);
+    }
+
     /**
      * Process state of UID changed; if needed, will trigger
      * {@link #updateRulesForDataUsageRestrictionsUL(int)} and
@@ -4017,8 +4048,10 @@
                 // state changed, push updated rules
                 mUidState.put(uid, newUidState);
                 updateRestrictBackgroundRulesOnUidStatusChangedUL(uid, oldUidState, newUidState);
-                if (isProcStateAllowedWhileIdleOrPowerSaveMode(oldUidState)
-                        != isProcStateAllowedWhileIdleOrPowerSaveMode(newUidState)) {
+                boolean allowedWhileIdleOrPowerSaveModeChanged =
+                        isProcStateAllowedWhileIdleOrPowerSaveMode(oldUidState)
+                                != isProcStateAllowedWhileIdleOrPowerSaveMode(newUidState);
+                if (allowedWhileIdleOrPowerSaveModeChanged) {
                     updateRuleForAppIdleUL(uid);
                     if (mDeviceIdleMode) {
                         updateRuleForDeviceIdleUL(uid);
@@ -4028,6 +4061,17 @@
                     }
                     updateRulesForPowerRestrictionsUL(uid);
                 }
+                if (mLowPowerStandbyActive) {
+                    boolean allowedInLpsChanged =
+                            isProcStateAllowedWhileInLowPowerStandby(oldUidState)
+                                    != isProcStateAllowedWhileInLowPowerStandby(newUidState);
+                    if (allowedInLpsChanged) {
+                        if (!allowedWhileIdleOrPowerSaveModeChanged) {
+                            updateRulesForPowerRestrictionsUL(uid);
+                        }
+                        updateRuleForLowPowerStandbyUL(uid);
+                    }
+                }
                 return true;
             }
         } finally {
@@ -4051,6 +4095,9 @@
                     updateRuleForRestrictPowerUL(uid);
                 }
                 updateRulesForPowerRestrictionsUL(uid);
+                if (mLowPowerStandbyActive) {
+                    updateRuleForLowPowerStandbyUL(uid);
+                }
                 return true;
             }
         }
@@ -4254,6 +4301,50 @@
         }
     }
 
+    @GuardedBy("mUidRulesFirstLock")
+    void updateRulesForLowPowerStandbyUL() {
+        Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "updateRulesForLowPowerStandbyUL");
+        try {
+            if (mLowPowerStandbyActive) {
+                mUidFirewallLowPowerStandbyModeRules.clear();
+                for (int i = mUidState.size() - 1; i >= 0; i--) {
+                    final int uid = mUidState.keyAt(i);
+                    UidBlockedState uidBlockedState = mUidBlockedState.get(uid);
+                    if (hasInternetPermissionUL(uid) && uidBlockedState != null
+                            && (uidBlockedState.effectiveBlockedReasons
+                                    & BLOCKED_REASON_LOW_POWER_STANDBY) == 0) {
+                        mUidFirewallLowPowerStandbyModeRules.put(mUidBlockedState.keyAt(i),
+                                FIREWALL_RULE_ALLOW);
+                    }
+                }
+                setUidFirewallRulesUL(FIREWALL_CHAIN_LOW_POWER_STANDBY,
+                        mUidFirewallLowPowerStandbyModeRules, CHAIN_TOGGLE_ENABLE);
+            } else {
+                setUidFirewallRulesUL(FIREWALL_CHAIN_LOW_POWER_STANDBY, null, CHAIN_TOGGLE_DISABLE);
+            }
+        } finally {
+            Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
+        }
+    }
+
+    @GuardedBy("mUidRulesFirstLock")
+    void updateRuleForLowPowerStandbyUL(int uid) {
+        if (!hasInternetPermissionUL(uid)) {
+            return;
+        }
+
+        final UidBlockedState uidBlockedState = mUidBlockedState.get(uid);
+        if (mUidState.contains(uid) && uidBlockedState != null
+                && (uidBlockedState.effectiveBlockedReasons & BLOCKED_REASON_LOW_POWER_STANDBY)
+                == 0) {
+            mUidFirewallLowPowerStandbyModeRules.put(uid, FIREWALL_RULE_ALLOW);
+            setUidFirewallRuleUL(FIREWALL_CHAIN_LOW_POWER_STANDBY, uid, FIREWALL_RULE_ALLOW);
+        } else {
+            mUidFirewallLowPowerStandbyModeRules.delete(uid);
+            setUidFirewallRuleUL(FIREWALL_CHAIN_LOW_POWER_STANDBY, uid, FIREWALL_RULE_DEFAULT);
+        }
+    }
+
     /**
      * Returns whether a uid is allowlisted from power saving restrictions (eg: Battery Saver, Doze
      * mode, and app idle).
@@ -4283,6 +4374,14 @@
         return mPowerSaveWhitelistExceptIdleAppIds.get(appId);
     }
 
+    /**
+     * Returns whether a uid is allowlisted from low power standby restrictions.
+     */
+    @GuardedBy("mUidRulesFirstLock")
+    private boolean isAllowlistedFromLowPowerStandbyUL(int uid) {
+        return mLowPowerStandbyAllowlistUids.get(uid);
+    }
+
     // NOTE: since both fw_dozable and fw_powersave uses the same map
     // (mPowerSaveTempWhitelistAppIds) for allowlisting, we can reuse their logic in this method.
     @GuardedBy("mUidRulesFirstLock")
@@ -4620,6 +4719,7 @@
         mPowerSaveTempWhitelistAppIds.delete(uid);
         mAppIdleTempWhitelistAppIds.delete(uid);
         mUidFirewallRestrictedModeRules.delete(uid);
+        mUidFirewallLowPowerStandbyModeRules.delete(uid);
         synchronized (mUidStateCallbackInfos) {
             mUidStateCallbackInfos.remove(uid);
         }
@@ -4845,6 +4945,7 @@
         }
 
         final boolean isForeground = isUidForegroundOnRestrictPowerUL(uid);
+        final boolean isTop = isUidTop(uid);
 
         final boolean isWhitelisted = isWhitelistedFromPowerSaveUL(uid, mDeviceIdleMode);
 
@@ -4858,17 +4959,21 @@
         int newAllowedReasons = ALLOWED_REASON_NONE;
         newBlockedReasons |= (mRestrictPower ? BLOCKED_REASON_BATTERY_SAVER : 0);
         newBlockedReasons |= (mDeviceIdleMode ? BLOCKED_REASON_DOZE : 0);
+        newBlockedReasons |= (mLowPowerStandbyActive ? BLOCKED_REASON_LOW_POWER_STANDBY : 0);
         newBlockedReasons |= (isUidIdle ? BLOCKED_REASON_APP_STANDBY : 0);
         newBlockedReasons |= (uidBlockedState.blockedReasons & BLOCKED_REASON_RESTRICTED_MODE);
 
         newAllowedReasons |= (isSystem(uid) ? ALLOWED_REASON_SYSTEM : 0);
         newAllowedReasons |= (isForeground ? ALLOWED_REASON_FOREGROUND : 0);
+        newAllowedReasons |= (isTop ? ALLOWED_REASON_TOP : 0);
         newAllowedReasons |= (isWhitelistedFromPowerSaveUL(uid, true)
                 ? ALLOWED_REASON_POWER_SAVE_ALLOWLIST : 0);
         newAllowedReasons |= (isWhitelistedFromPowerSaveExceptIdleUL(uid)
                 ? ALLOWED_REASON_POWER_SAVE_EXCEPT_IDLE_ALLOWLIST : 0);
         newAllowedReasons |= (uidBlockedState.allowedReasons
                 & ALLOWED_REASON_RESTRICTED_MODE_PERMISSIONS);
+        newAllowedReasons |= (isAllowlistedFromLowPowerStandbyUL(uid))
+                ? ALLOWED_REASON_LOW_POWER_STANDBY_ALLOWLIST : 0;
 
         uidBlockedState.blockedReasons = (uidBlockedState.blockedReasons
                 & BLOCKED_METERED_REASON_MASK) | newBlockedReasons;
@@ -4890,6 +4995,7 @@
                     + ", mRestrictPower: " + mRestrictPower
                     + ", mDeviceIdleMode: " + mDeviceIdleMode
                     + ", isForeground=" + isForeground
+                    + ", isTop=" + isTop
                     + ", isWhitelisted=" + isWhitelisted
                     + ", oldUidBlockedState=" + previousUidBlockedState.toString()
                     + ", newUidBlockedState=" + uidBlockedState.toString());
@@ -5421,6 +5527,8 @@
                 mUidFirewallPowerSaveRules.put(uid, rule);
             } else if (chain == FIREWALL_CHAIN_RESTRICTED) {
                 mUidFirewallRestrictedModeRules.put(uid, rule);
+            } else if (chain == FIREWALL_CHAIN_LOW_POWER_STANDBY) {
+                mUidFirewallLowPowerStandbyModeRules.put(uid, rule);
             }
 
             try {
@@ -5468,6 +5576,9 @@
                     .setFirewallUidRule(FIREWALL_CHAIN_POWERSAVE, uid, FIREWALL_RULE_DEFAULT);
             mNetworkManager
                     .setFirewallUidRule(FIREWALL_CHAIN_RESTRICTED, uid, FIREWALL_RULE_DEFAULT);
+            mNetworkManager
+                    .setFirewallUidRule(FIREWALL_CHAIN_LOW_POWER_STANDBY, uid,
+                            FIREWALL_RULE_DEFAULT);
             mNetworkManager.setUidOnMeteredNetworkAllowlist(uid, false);
             mNetworkManager.setUidOnMeteredNetworkDenylist(uid, false);
         } catch (IllegalStateException e) {
@@ -5747,6 +5858,67 @@
             mHandler.obtainMessage(MSG_METERED_RESTRICTED_PACKAGES_CHANGED,
                     userId, 0, packageNames).sendToTarget();
         }
+
+        @Override
+        public void setLowPowerStandbyActive(boolean active) {
+            Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "setLowPowerStandbyActive");
+            try {
+                synchronized (mUidRulesFirstLock) {
+                    if (mLowPowerStandbyActive == active) {
+                        return;
+                    }
+                    mLowPowerStandbyActive = active;
+                    synchronized (mNetworkPoliciesSecondLock) {
+                        if (!mSystemReady) return;
+                    }
+
+                    forEachUid("updateRulesForRestrictPower",
+                            uid -> updateRulesForPowerRestrictionsUL(uid));
+                    updateRulesForLowPowerStandbyUL();
+                }
+            } finally {
+                Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
+            }
+        }
+
+        @Override
+        public void setLowPowerStandbyAllowlist(int[] uids) {
+            synchronized (mUidRulesFirstLock) {
+                final SparseBooleanArray changedUids = new SparseBooleanArray();
+                for (int i = 0; i < mLowPowerStandbyAllowlistUids.size(); i++) {
+                    final int oldUid = mLowPowerStandbyAllowlistUids.keyAt(i);
+                    if (!ArrayUtils.contains(uids, oldUid)) {
+                        changedUids.put(oldUid, true);
+                    }
+                }
+
+                for (int i = 0; i < changedUids.size(); i++) {
+                    final int deletedUid = changedUids.keyAt(i);
+                    mLowPowerStandbyAllowlistUids.delete(deletedUid);
+                }
+
+                for (int newUid : uids) {
+                    if (mLowPowerStandbyAllowlistUids.indexOfKey(newUid) < 0) {
+                        changedUids.append(newUid, true);
+                        mLowPowerStandbyAllowlistUids.append(newUid, true);
+                    }
+                }
+
+                if (!mLowPowerStandbyActive) {
+                    return;
+                }
+
+                synchronized (mNetworkPoliciesSecondLock) {
+                    if (!mSystemReady) return;
+                }
+
+                for (int i = 0; i < changedUids.size(); i++) {
+                    final int changedUid = changedUids.keyAt(i);
+                    updateRulesForPowerRestrictionsUL(changedUid);
+                    updateRuleForLowPowerStandbyUL(changedUid);
+                }
+            }
+        }
     }
 
     private void setMeteredRestrictedPackagesInternal(Set<String> packageNames, int userId) {
@@ -5904,6 +6076,9 @@
                 effectiveBlockedReasons &= ~BLOCKED_METERED_REASON_DATA_SAVER;
                 effectiveBlockedReasons &= ~BLOCKED_METERED_REASON_USER_RESTRICTED;
             }
+            if ((allowedReasons & ALLOWED_REASON_TOP) != 0) {
+                effectiveBlockedReasons &= ~BLOCKED_REASON_LOW_POWER_STANDBY;
+            }
             if ((allowedReasons & ALLOWED_REASON_POWER_SAVE_ALLOWLIST) != 0) {
                 effectiveBlockedReasons &= ~BLOCKED_REASON_BATTERY_SAVER;
                 effectiveBlockedReasons &= ~BLOCKED_REASON_DOZE;
@@ -5919,6 +6094,10 @@
             if ((allowedReasons & ALLOWED_METERED_REASON_USER_EXEMPTED) != 0) {
                 effectiveBlockedReasons &= ~BLOCKED_METERED_REASON_DATA_SAVER;
             }
+            if ((allowedReasons & ALLOWED_REASON_LOW_POWER_STANDBY_ALLOWLIST) != 0) {
+                effectiveBlockedReasons &= ~BLOCKED_REASON_LOW_POWER_STANDBY;
+            }
+
             return effectiveBlockedReasons;
         }
 
@@ -5943,6 +6122,7 @@
                 BLOCKED_REASON_DOZE,
                 BLOCKED_REASON_APP_STANDBY,
                 BLOCKED_REASON_RESTRICTED_MODE,
+                BLOCKED_REASON_LOW_POWER_STANDBY,
                 BLOCKED_METERED_REASON_DATA_SAVER,
                 BLOCKED_METERED_REASON_USER_RESTRICTED,
                 BLOCKED_METERED_REASON_ADMIN_DISABLED,
@@ -5951,9 +6131,11 @@
         private static final int[] ALLOWED_REASONS = {
                 ALLOWED_REASON_SYSTEM,
                 ALLOWED_REASON_FOREGROUND,
+                ALLOWED_REASON_TOP,
                 ALLOWED_REASON_POWER_SAVE_ALLOWLIST,
                 ALLOWED_REASON_POWER_SAVE_EXCEPT_IDLE_ALLOWLIST,
                 ALLOWED_REASON_RESTRICTED_MODE_PERMISSIONS,
+                ALLOWED_REASON_LOW_POWER_STANDBY_ALLOWLIST,
                 ALLOWED_METERED_REASON_USER_EXEMPTED,
                 ALLOWED_METERED_REASON_SYSTEM,
                 ALLOWED_METERED_REASON_FOREGROUND,
@@ -5971,6 +6153,8 @@
                     return "APP_STANDBY";
                 case BLOCKED_REASON_RESTRICTED_MODE:
                     return "RESTRICTED_MODE";
+                case BLOCKED_REASON_LOW_POWER_STANDBY:
+                    return "LOW_POWER_STANDBY";
                 case BLOCKED_METERED_REASON_DATA_SAVER:
                     return "DATA_SAVER";
                 case BLOCKED_METERED_REASON_USER_RESTRICTED:
@@ -5991,12 +6175,16 @@
                     return "SYSTEM";
                 case ALLOWED_REASON_FOREGROUND:
                     return "FOREGROUND";
+                case ALLOWED_REASON_TOP:
+                    return "TOP";
                 case ALLOWED_REASON_POWER_SAVE_ALLOWLIST:
                     return "POWER_SAVE_ALLOWLIST";
                 case ALLOWED_REASON_POWER_SAVE_EXCEPT_IDLE_ALLOWLIST:
                     return "POWER_SAVE_EXCEPT_IDLE_ALLOWLIST";
                 case ALLOWED_REASON_RESTRICTED_MODE_PERMISSIONS:
                     return "RESTRICTED_MODE_PERMISSIONS";
+                case ALLOWED_REASON_LOW_POWER_STANDBY_ALLOWLIST:
+                    return "LOW_POWER_STANDBY_ALLOWLIST";
                 case ALLOWED_METERED_REASON_USER_EXEMPTED:
                     return "METERED_USER_EXEMPTED";
                 case ALLOWED_METERED_REASON_SYSTEM:
@@ -6063,7 +6251,8 @@
 
             int powerBlockedReasons = BLOCKED_REASON_APP_STANDBY
                     | BLOCKED_REASON_DOZE
-                    | BLOCKED_REASON_BATTERY_SAVER;
+                    | BLOCKED_REASON_BATTERY_SAVER
+                    | BLOCKED_REASON_LOW_POWER_STANDBY;
             if ((effectiveBlockedReasons & powerBlockedReasons) != 0) {
                 uidRule |= RULE_REJECT_ALL;
             } else if ((blockedReasons & powerBlockedReasons) != 0) {
diff --git a/services/core/java/com/android/server/net/TEST_MAPPING b/services/core/java/com/android/server/net/TEST_MAPPING
index 02095eb..4ccf09e 100644
--- a/services/core/java/com/android/server/net/TEST_MAPPING
+++ b/services/core/java/com/android/server/net/TEST_MAPPING
@@ -2,12 +2,8 @@
   "presubmit-large": [
     {
       "name": "CtsHostsideNetworkTests",
-      "file_patterns": ["(/|^)NetworkPolicy[^/]*\\.java"],
       "options": [
         {
-          "include-filter": "com.android.cts.net.HostsideRestrictBackgroundNetworkTests"
-        },
-        {
           "exclude-annotation": "androidx.test.filters.FlakyTest"
         },
         {
diff --git a/services/core/java/com/android/server/notification/GroupHelper.java b/services/core/java/com/android/server/notification/GroupHelper.java
index 9cb8a01..4f26809 100644
--- a/services/core/java/com/android/server/notification/GroupHelper.java
+++ b/services/core/java/com/android/server/notification/GroupHelper.java
@@ -82,7 +82,7 @@
         }
         String combinedKey = generatePackageGroupKey(userId, sbn.getPackageName(), group);
         boolean needsOngoingFlag = notifications.size() > 0;
-        mCallback.updateAutogroupSummary(sbn.getKey(), needsOngoingFlag);
+        mCallback.updateAutogroupSummary(userId, sbn.getPackageName(), needsOngoingFlag);
     }
 
     public void onNotificationUpdated(StatusBarNotification childSbn,
@@ -211,6 +211,6 @@
         void removeAutoGroup(String key);
         void addAutoGroupSummary(int userId, String pkg, String triggeringKey);
         void removeAutoGroupSummary(int user, String pkg);
-        void updateAutogroupSummary(String key, boolean needsOngoingFlag);
+        void updateAutogroupSummary(int userId, String pkg, boolean needsOngoingFlag);
     }
 }
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 211f8d6..d9f2e97 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -2498,19 +2498,11 @@
             }
 
             @Override
-            public void updateAutogroupSummary(String key, boolean needsOngoingFlag) {
-                String pkg;
-                synchronized (mNotificationLock) {
-                    NotificationRecord r = mNotificationsByKey.get(key);
-                    pkg = r != null && r.getSbn() != null ? r.getSbn().getPackageName() : null;
-                }
+            public void updateAutogroupSummary(int userId, String pkg, boolean needsOngoingFlag) {
                 boolean isAppForeground = pkg != null
                         && mActivityManager.getPackageImportance(pkg) == IMPORTANCE_FOREGROUND;
                 synchronized (mNotificationLock) {
-                    NotificationRecord r = mNotificationsByKey.get(key);
-                    if (r == null) return;
-                    updateAutobundledSummaryFlags(r.getUser().getIdentifier(),
-                            r.getSbn().getPackageName(), needsOngoingFlag, isAppForeground);
+                    updateAutobundledSummaryFlags(userId, pkg, needsOngoingFlag, isAppForeground);
                 }
             }
         });
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index 419b726..24b9f48 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -815,7 +815,7 @@
         PendingIntent injectCreatePendingIntent(int requestCode, @NonNull Intent[] intents,
                 int flags, Bundle options, String ownerPackage, int ownerUserId) {
             return mActivityManagerInternal.getPendingIntentActivityAsApp(requestCode, intents,
-                    flags, options, ownerPackage, ownerUserId);
+                    flags, null /* options */, ownerPackage, ownerUserId);
         }
 
         @Override
@@ -1117,7 +1117,7 @@
                 // calling identity to mirror the startActivityAsUser() call which does not validate
                 // the calling user
                 return PendingIntent.getActivityAsUser(mContext, 0 /* requestCode */, launchIntent,
-                        FLAG_IMMUTABLE, opts, user);
+                        FLAG_IMMUTABLE, null /* options */, user);
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 265e606..d01f962 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -3516,7 +3516,7 @@
             }
             List<PermissionInfo> ps = mPermissionManager
                     .queryPermissionsByGroup(groupList.get(i), 0 /*flags*/);
-            final int count = ps.size();
+            final int count = (ps == null ? 0 : ps.size());
             boolean first = true;
             for (int p = 0 ; p < count ; p++) {
                 PermissionInfo pi = ps.get(p);
diff --git a/services/core/java/com/android/server/pm/dex/OdsignStatsLogger.java b/services/core/java/com/android/server/pm/dex/OdsignStatsLogger.java
new file mode 100644
index 0000000..fa08add
--- /dev/null
+++ b/services/core/java/com/android/server/pm/dex/OdsignStatsLogger.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm.dex;
+
+import android.util.Slog;
+
+import com.android.internal.art.ArtStatsLog;
+import com.android.internal.os.BackgroundThread;
+
+import libcore.io.IoUtils;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+
+/**
+ * This class is responsible for reading metrics files generated by odsign and sending them to
+ * statsd. odsign can't send the stats directly to statsd, because statsd can't run until after
+ * odsign has completed. The code here is intended to run once per boot, since odsign runs at boot
+ * time.
+ */
+public class OdsignStatsLogger {
+    private static final String TAG = "OdsignStatsLogger";
+
+    // These need to be kept in sync with system/security/ondevice-signing/StatsReporter.{h, cpp}.
+    private static final String METRICS_FILE = "/data/misc/odsign/metrics/odsign-metrics.txt";
+    private static final String COMPOS_METRIC_NAME = "comp_os_artifacts_check_record";
+
+    /**
+     * Arrange for stats to be uploaded in the background.
+     */
+    public static void triggerStatsWrite() {
+        BackgroundThread.getExecutor().execute(OdsignStatsLogger::writeStats);
+    }
+
+    private static void writeStats() {
+        try {
+            String lines = IoUtils.readFileAsString(METRICS_FILE);
+
+            // Delete the file now so we don't upload it more than once, and don't keep trying
+            // to re-parse it if there is a problem.
+            if (!new File(METRICS_FILE).delete()) {
+                Slog.w(TAG, "Failed to delete metrics file");
+            }
+
+            // The format is simple - each line is a series of space separated tokens. The first is
+            // the metric name and subsequent ones are the metric values. The logic here must be
+            // kept in sync with system/security/ondevice-signing/StatsReporter.cpp.
+
+            for (String line : lines.split("\n")) {
+                String[] metrics = line.split(" ");
+
+                if (metrics.length != 4 || !metrics[0].equals(COMPOS_METRIC_NAME)) {
+                    Slog.w(TAG, "Malformed metrics file");
+                    break;
+                }
+
+                boolean currentArtifactsOk = metrics[1].equals("1");
+                boolean compOsPendingArtifactsExists = metrics[2].equals("1");
+                boolean useCompOsGeneratedArtifacts = metrics[3].equals("1");
+
+                ArtStatsLog.write(ArtStatsLog.EARLY_BOOT_COMP_OS_ARTIFACTS_CHECK_REPORTED,
+                        currentArtifactsOk, compOsPendingArtifactsExists,
+                        useCompOsGeneratedArtifacts);
+            }
+        } catch (FileNotFoundException e) {
+            // This is normal and probably means no new metrics have been generated.
+        } catch (IOException e) {
+            Slog.w(TAG, "Reading metrics file failed", e);
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/telecom/OWNERS b/services/core/java/com/android/server/telecom/OWNERS
index 39be2c1..cad25a4 100644
--- a/services/core/java/com/android/server/telecom/OWNERS
+++ b/services/core/java/com/android/server/telecom/OWNERS
@@ -1,6 +1 @@
-breadley@google.com
-hallliu@google.com
-tgunn@google.com
-xiaotonj@google.com
-shuoq@google.com
-rgreenwalt@google.com
+file:platform/frameworks/base:/telecomm/OWNERS
diff --git a/services/core/java/com/android/server/vcn/Vcn.java b/services/core/java/com/android/server/vcn/Vcn.java
index f29c40f..37f0450 100644
--- a/services/core/java/com/android/server/vcn/Vcn.java
+++ b/services/core/java/com/android/server/vcn/Vcn.java
@@ -341,6 +341,9 @@
                 if (gatewayConnection == null) {
                     logWtf("Found gatewayConnectionConfig without GatewayConnection");
                 } else {
+                    logInfo(
+                            "Config updated, restarting gateway "
+                                    + gatewayConnection.getLogPrefix());
                     gatewayConnection.teardownAsynchronously();
                 }
             }
@@ -397,7 +400,7 @@
         // If preexisting VcnGatewayConnection(s) satisfy request, return
         for (VcnGatewayConnectionConfig gatewayConnectionConfig : mVcnGatewayConnections.keySet()) {
             if (isRequestSatisfiedByGatewayConnectionConfig(request, gatewayConnectionConfig)) {
-                logDbg("Request already satisfied by existing VcnGatewayConnection: " + request);
+                logVdbg("Request already satisfied by existing VcnGatewayConnection: " + request);
                 return;
             }
         }
@@ -407,8 +410,6 @@
         for (VcnGatewayConnectionConfig gatewayConnectionConfig :
                 mConfig.getGatewayConnectionConfigs()) {
             if (isRequestSatisfiedByGatewayConnectionConfig(request, gatewayConnectionConfig)) {
-                logDbg("Bringing up new VcnGatewayConnection for request " + request);
-
                 if (getExposedCapabilitiesForMobileDataState(gatewayConnectionConfig).isEmpty()) {
                     // Skip; this network does not provide any services if mobile data is disabled.
                     continue;
@@ -424,6 +425,7 @@
                     return;
                 }
 
+                logInfo("Bringing up new VcnGatewayConnection for request " + request);
                 final VcnGatewayConnection vcnGatewayConnection =
                         mDeps.newVcnGatewayConnection(
                                 mVcnContext,
@@ -455,7 +457,7 @@
     }
 
     private void handleGatewayConnectionQuit(VcnGatewayConnectionConfig config) {
-        logDbg("VcnGatewayConnection quit: " + config);
+        logInfo("VcnGatewayConnection quit: " + config);
         mVcnGatewayConnections.remove(config);
 
         // Trigger a re-evaluation of all NetworkRequests (to make sure any that can be satisfied
@@ -534,7 +536,7 @@
             // Trigger re-evaluation of all requests; mobile data state impacts supported caps.
             mVcnContext.getVcnNetworkProvider().resendAllRequests(mRequestListener);
 
-            logDbg("Mobile data " + (mIsMobileDataEnabled ? "enabled" : "disabled"));
+            logInfo("Mobile data " + (mIsMobileDataEnabled ? "enabled" : "disabled"));
         }
     }
 
@@ -569,11 +571,11 @@
     }
 
     private String getLogPrefix() {
-        return "["
+        return "("
                 + LogUtils.getHashedSubscriptionGroup(mSubscriptionGroup)
                 + "-"
                 + System.identityHashCode(this)
-                + "] ";
+                + ") ";
     }
 
     private void logVdbg(String msg) {
diff --git a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
index 597f7f2..cefd8ef 100644
--- a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
+++ b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
@@ -544,6 +544,7 @@
     private final boolean mIsMobileDataEnabled;
 
     @NonNull private final IpSecManager mIpSecManager;
+    @NonNull private final ConnectivityManager mConnectivityManager;
 
     @Nullable private IpSecTunnelInterface mTunnelIface = null;
 
@@ -701,6 +702,7 @@
                         mLastSnapshot,
                         mUnderlyingNetworkControllerCallback);
         mIpSecManager = mVcnContext.getContext().getSystemService(IpSecManager.class);
+        mConnectivityManager = mVcnContext.getContext().getSystemService(ConnectivityManager.class);
 
         addState(mDisconnectedState);
         addState(mDisconnectingState);
@@ -730,14 +732,11 @@
         logDbg("Triggering async teardown");
         sendDisconnectRequestedAndAcquireWakelock(
                 DISCONNECT_REASON_TEARDOWN, true /* shouldQuit */);
-
-        // TODO: Notify VcnInstance (via callbacks) of permanent teardown of this tunnel, since this
-        // is also called asynchronously when a NetworkAgent becomes unwanted
     }
 
     @Override
     protected void onQuitting() {
-        logDbg("Quitting VcnGatewayConnection");
+        logInfo("Quitting VcnGatewayConnection");
 
         if (mNetworkAgent != null) {
             logWtf("NetworkAgent was non-null in onQuitting");
@@ -792,7 +791,7 @@
             // TODO(b/180132994): explore safely removing this Thread check
             mVcnContext.ensureRunningOnLooperThread();
 
-            logDbg(
+            logInfo(
                     "Selected underlying network changed: "
                             + (underlying == null ? null : underlying.network));
 
@@ -1333,7 +1332,7 @@
         protected void handleDisconnectRequested(EventDisconnectRequestedInfo info) {
             // TODO(b/180526152): notify VcnStatusCallback for Network loss
 
-            logDbg("Tearing down. Cause: " + info.reason);
+            logInfo("Tearing down. Cause: " + info.reason + "; quitting = " + info.shouldQuit);
             if (info.shouldQuit) {
                 mIsQuitting.setTrue();
             }
@@ -1351,7 +1350,7 @@
 
         protected void handleSafeModeTimeoutExceeded() {
             mSafeModeTimeoutAlarm = null;
-            logDbg("Entering safe mode after timeout exceeded");
+            logInfo("Entering safe mode after timeout exceeded");
 
             // Connectivity for this GatewayConnection is broken; tear down the Network.
             teardownNetwork();
@@ -1360,7 +1359,7 @@
         }
 
         protected void logUnexpectedEvent(int what) {
-            logDbg(
+            logVdbg(
                     "Unexpected event code "
                             + what
                             + " in state "
@@ -1670,7 +1669,7 @@
                                     return;
                                 }
 
-                                logDbg("NetworkAgent was unwanted");
+                                logInfo("NetworkAgent was unwanted");
                                 teardownAsynchronously();
                             } /* networkUnwantedCallback */,
                             (status) -> {
@@ -1683,6 +1682,14 @@
                                         clearFailedAttemptCounterAndSafeModeAlarm();
                                         break;
                                     case NetworkAgent.VALIDATION_STATUS_NOT_VALID:
+                                        // Trigger re-validation of underlying networks; if it
+                                        // fails, the VCN will attempt to migrate away.
+                                        if (mUnderlying != null) {
+                                            mConnectivityManager.reportNetworkConnectivity(
+                                                    mUnderlying.network,
+                                                    false /* hasConnectivity */);
+                                        }
+
                                         // Will only set a new alarm if no safe mode alarm is
                                         // currently scheduled.
                                         setSafeModeAlarm();
@@ -1738,7 +1745,7 @@
                             tunnelIface, IpSecManager.DIRECTION_FWD, transform);
                 }
             } catch (IOException e) {
-                logDbg("Transform application failed for network " + token, e);
+                logInfo("Transform application failed for network " + token, e);
                 sessionLost(token, e);
             }
         }
@@ -1772,7 +1779,7 @@
                     tunnelIface.removeAddress(address.getAddress(), address.getPrefixLength());
                 }
             } catch (IOException e) {
-                logDbg("Adding address to tunnel failed for token " + token, e);
+                logInfo("Adding address to tunnel failed for token " + token, e);
                 sessionLost(token, e);
             }
         }
@@ -1852,7 +1859,7 @@
         }
 
         private void handleMigrationCompleted(EventMigrationCompletedInfo migrationCompletedInfo) {
-            logDbg("Migration completed: " + mUnderlying.network);
+            logInfo("Migration completed: " + mUnderlying.network);
 
             applyTransform(
                     mCurrentToken,
@@ -1869,6 +1876,10 @@
                     IpSecManager.DIRECTION_OUT);
 
             updateNetworkAgent(mTunnelIface, mNetworkAgent, mChildConfig);
+
+            // Trigger re-validation after migration events.
+            mConnectivityManager.reportNetworkConnectivity(
+                    mNetworkAgent.getNetwork(), false /* hasConnectivity */);
         }
 
         private void handleUnderlyingNetworkChanged(@NonNull Message msg) {
@@ -1876,7 +1887,7 @@
             mUnderlying = ((EventUnderlyingNetworkChangedInfo) msg.obj).newUnderlying;
 
             if (mUnderlying == null) {
-                logDbg("Underlying network lost");
+                logInfo("Underlying network lost");
 
                 // Ignored for now; a new network may be coming up. If none does, the delayed
                 // NETWORK_LOST disconnect will be fired, and tear down the session + network.
@@ -1886,7 +1897,7 @@
             // mUnderlying assumed non-null, given check above.
             // If network changed, migrate. Otherwise, update any existing networkAgent.
             if (oldUnderlying == null || !oldUnderlying.network.equals(mUnderlying.network)) {
-                logDbg("Migrating to new network: " + mUnderlying.network);
+                logInfo("Migrating to new network: " + mUnderlying.network);
                 mIkeSession.setNetwork(mUnderlying.network);
             } else {
                 // oldUnderlying is non-null & underlying network itself has not changed
@@ -2154,13 +2165,13 @@
 
         @Override
         public void onClosedExceptionally(@NonNull IkeException exception) {
-            logDbg("IkeClosedExceptionally for token " + mToken, exception);
+            logInfo("IkeClosedExceptionally for token " + mToken, exception);
             sessionClosed(mToken, exception);
         }
 
         @Override
         public void onError(@NonNull IkeProtocolException exception) {
-            logDbg("IkeError for token " + mToken, exception);
+            logInfo("IkeError for token " + mToken, exception);
             // Non-fatal, log and continue.
         }
     }
@@ -2194,7 +2205,7 @@
 
         @Override
         public void onClosedExceptionally(@NonNull IkeException exception) {
-            logDbg("ChildClosedExceptionally for token " + mToken, exception);
+            logInfo("ChildClosedExceptionally for token " + mToken, exception);
             sessionLost(mToken, exception);
         }
 
@@ -2220,14 +2231,19 @@
         }
     }
 
-    private String getLogPrefix() {
-        return "["
+    // Used in Vcn.java, but must be public for mockito to mock this.
+    public String getLogPrefix() {
+        return "("
                 + LogUtils.getHashedSubscriptionGroup(mSubscriptionGroup)
                 + "-"
                 + mConnectionConfig.getGatewayConnectionName()
                 + "-"
                 + System.identityHashCode(this)
-                + "] ";
+                + ") ";
+    }
+
+    private String getTagLogPrefix() {
+        return "[ " + TAG + " " + getLogPrefix() + "]";
     }
 
     private void logVdbg(String msg) {
@@ -2244,34 +2260,44 @@
         Slog.d(TAG, getLogPrefix() + msg, tr);
     }
 
+    private void logInfo(String msg) {
+        Slog.i(TAG, getLogPrefix() + msg);
+        LOCAL_LOG.log("[INFO] " + getTagLogPrefix() + msg);
+    }
+
+    private void logInfo(String msg, Throwable tr) {
+        Slog.i(TAG, getLogPrefix() + msg, tr);
+        LOCAL_LOG.log("[INFO] " + getTagLogPrefix() + msg + tr);
+    }
+
     private void logWarn(String msg) {
         Slog.w(TAG, getLogPrefix() + msg);
-        LOCAL_LOG.log(getLogPrefix() + "WARN: " + msg);
+        LOCAL_LOG.log("[WARN] " + getTagLogPrefix() + msg);
     }
 
     private void logWarn(String msg, Throwable tr) {
         Slog.w(TAG, getLogPrefix() + msg, tr);
-        LOCAL_LOG.log(getLogPrefix() + "WARN: " + msg + tr);
+        LOCAL_LOG.log("[WARN] " + getTagLogPrefix() + msg + tr);
     }
 
     private void logErr(String msg) {
         Slog.e(TAG, getLogPrefix() + msg);
-        LOCAL_LOG.log(getLogPrefix() + "ERR: " + msg);
+        LOCAL_LOG.log("[ERR ] " + getTagLogPrefix() + msg);
     }
 
     private void logErr(String msg, Throwable tr) {
         Slog.e(TAG, getLogPrefix() + msg, tr);
-        LOCAL_LOG.log(getLogPrefix() + "ERR: " + msg + tr);
+        LOCAL_LOG.log("[ERR ] " + getTagLogPrefix() + msg + tr);
     }
 
     private void logWtf(String msg) {
         Slog.wtf(TAG, getLogPrefix() + msg);
-        LOCAL_LOG.log(getLogPrefix() + "WTF: " + msg);
+        LOCAL_LOG.log("[WTF ] " + msg);
     }
 
     private void logWtf(String msg, Throwable tr) {
         Slog.wtf(TAG, getLogPrefix() + msg, tr);
-        LOCAL_LOG.log(getLogPrefix() + "WTF: " + msg + tr);
+        LOCAL_LOG.log("[WTF ] " + msg + tr);
     }
 
     /**
diff --git a/services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkController.java b/services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkController.java
index ca2e449..a3babf7 100644
--- a/services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkController.java
+++ b/services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkController.java
@@ -48,6 +48,7 @@
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;
 import com.android.server.vcn.VcnContext;
+import com.android.server.vcn.util.LogUtils;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -368,6 +369,18 @@
             return;
         }
 
+        String allNetworkPriorities = "";
+        for (UnderlyingNetworkRecord record : sorted) {
+            if (!allNetworkPriorities.isEmpty()) {
+                allNetworkPriorities += ", ";
+            }
+            allNetworkPriorities += record.network + ": " + record.getPriorityClass();
+        }
+        logInfo(
+                "Selected network changed to "
+                        + (candidate == null ? null : candidate.network)
+                        + ", selected from list: "
+                        + allNetworkPriorities);
         mCurrentRecord = candidate;
         mCb.onSelectedUnderlyingNetworkChanged(mCurrentRecord);
     }
@@ -478,14 +491,38 @@
         }
     }
 
-    private static void logWtf(String msg) {
-        Slog.wtf(TAG, msg);
-        LOCAL_LOG.log(TAG + " WTF: " + msg);
+    private String getLogPrefix() {
+        return "("
+                + LogUtils.getHashedSubscriptionGroup(mSubscriptionGroup)
+                + "-"
+                + mConnectionConfig.getGatewayConnectionName()
+                + "-"
+                + System.identityHashCode(this)
+                + ") ";
     }
 
-    private static void logWtf(String msg, Throwable tr) {
+    private String getTagLogPrefix() {
+        return "[ " + TAG + " " + getLogPrefix() + "]";
+    }
+
+    private void logInfo(String msg) {
+        Slog.i(TAG, getLogPrefix() + msg);
+        LOCAL_LOG.log("[INFO] " + getTagLogPrefix() + msg);
+    }
+
+    private void logInfo(String msg, Throwable tr) {
+        Slog.i(TAG, getLogPrefix() + msg, tr);
+        LOCAL_LOG.log("[INFO] " + getTagLogPrefix() + msg + tr);
+    }
+
+    private void logWtf(String msg) {
+        Slog.wtf(TAG, msg);
+        LOCAL_LOG.log(TAG + "[WTF ] " + getTagLogPrefix() + msg);
+    }
+
+    private void logWtf(String msg, Throwable tr) {
         Slog.wtf(TAG, msg, tr);
-        LOCAL_LOG.log(TAG + " WTF: " + msg + tr);
+        LOCAL_LOG.log(TAG + "[WTF ] " + getTagLogPrefix() + msg + tr);
     }
 
     /** Dumps the state of this record for logging and debugging purposes. */
diff --git a/services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkRecord.java b/services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkRecord.java
index c0488b1..06f9280 100644
--- a/services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkRecord.java
+++ b/services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkRecord.java
@@ -41,11 +41,15 @@
  * @hide
  */
 public class UnderlyingNetworkRecord {
+    private static final int PRIORITY_CLASS_INVALID = Integer.MAX_VALUE;
+
     @NonNull public final Network network;
     @NonNull public final NetworkCapabilities networkCapabilities;
     @NonNull public final LinkProperties linkProperties;
     public final boolean isBlocked;
 
+    private int mPriorityClass = PRIORITY_CLASS_INVALID;
+
     @VisibleForTesting(visibility = Visibility.PRIVATE)
     public UnderlyingNetworkRecord(
             @NonNull Network network,
@@ -58,6 +62,34 @@
         this.isBlocked = isBlocked;
     }
 
+    private int getOrCalculatePriorityClass(
+            VcnContext vcnContext,
+            List<VcnUnderlyingNetworkTemplate> underlyingNetworkTemplates,
+            ParcelUuid subscriptionGroup,
+            TelephonySubscriptionSnapshot snapshot,
+            UnderlyingNetworkRecord currentlySelected,
+            PersistableBundle carrierConfig) {
+        // Never changes after the underlying network record is created.
+        if (mPriorityClass == PRIORITY_CLASS_INVALID) {
+            mPriorityClass =
+                    NetworkPriorityClassifier.calculatePriorityClass(
+                            vcnContext,
+                            this,
+                            underlyingNetworkTemplates,
+                            subscriptionGroup,
+                            snapshot,
+                            currentlySelected,
+                            carrierConfig);
+        }
+
+        return mPriorityClass;
+    }
+
+    // Used in UnderlyingNetworkController
+    int getPriorityClass() {
+        return mPriorityClass;
+    }
+
     @Override
     public boolean equals(Object o) {
         if (this == o) return true;
@@ -84,18 +116,16 @@
             PersistableBundle carrierConfig) {
         return (left, right) -> {
             final int leftIndex =
-                    NetworkPriorityClassifier.calculatePriorityClass(
+                    left.getOrCalculatePriorityClass(
                             vcnContext,
-                            left,
                             underlyingNetworkTemplates,
                             subscriptionGroup,
                             snapshot,
                             currentlySelected,
                             carrierConfig);
             final int rightIndex =
-                    NetworkPriorityClassifier.calculatePriorityClass(
+                    right.getOrCalculatePriorityClass(
                             vcnContext,
-                            right,
                             underlyingNetworkTemplates,
                             subscriptionGroup,
                             snapshot,
@@ -142,16 +172,15 @@
         pw.increaseIndent();
 
         final int priorityIndex =
-                NetworkPriorityClassifier.calculatePriorityClass(
+                getOrCalculatePriorityClass(
                         vcnContext,
-                        this,
                         underlyingNetworkTemplates,
                         subscriptionGroup,
                         snapshot,
                         currentlySelected,
                         carrierConfig);
 
-        pw.println("Priority index:" + priorityIndex);
+        pw.println("Priority index: " + priorityIndex);
         pw.println("mNetwork: " + network);
         pw.println("mNetworkCapabilities: " + networkCapabilities);
         pw.println("mLinkProperties: " + linkProperties);
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index f580bd0..e70517f 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -7380,7 +7380,8 @@
         mSizeCompatBounds = null;
         mCompatDisplayInsets = null;
 
-        onRequestedOverrideConfigurationChanged(getRequestedOverrideConfiguration());
+        // Clear config override in #updateCompatDisplayInsets().
+        onRequestedOverrideConfigurationChanged(EMPTY);
     }
 
     @Override
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 1748f5b..5e95a785 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -1497,23 +1497,6 @@
             return StorageManager.isFileEncryptedNativeOnly();
         }
 
-        boolean storageManagerIsNonDefaultBlockEncrypted() {
-            final long identity = Binder.clearCallingIdentity();
-            try {
-                return StorageManager.isNonDefaultBlockEncrypted();
-            } finally {
-                Binder.restoreCallingIdentity(identity);
-            }
-        }
-
-        boolean storageManagerIsEncrypted() {
-            return StorageManager.isEncrypted();
-        }
-
-        boolean storageManagerIsEncryptable() {
-            return StorageManager.isEncryptable();
-        }
-
         Looper getMyLooper() {
             return Looper.myLooper();
         }
@@ -7673,21 +7656,12 @@
 
     /**
      * Hook to low-levels:  Reporting the current status of encryption.
-     * @return A value such as {@link DevicePolicyManager#ENCRYPTION_STATUS_UNSUPPORTED},
-     * {@link DevicePolicyManager#ENCRYPTION_STATUS_INACTIVE},
-     * {@link DevicePolicyManager#ENCRYPTION_STATUS_ACTIVE_DEFAULT_KEY},
-     * {@link DevicePolicyManager#ENCRYPTION_STATUS_ACTIVE_PER_USER}, or
-     * {@link DevicePolicyManager#ENCRYPTION_STATUS_ACTIVE}.
+     * @return Either {@link DevicePolicyManager#ENCRYPTION_STATUS_UNSUPPORTED}
+     * or {@link DevicePolicyManager#ENCRYPTION_STATUS_ACTIVE_PER_USER}.
      */
     private int getEncryptionStatus() {
         if (mInjector.storageManagerIsFileBasedEncryptionEnabled()) {
             return DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE_PER_USER;
-        } else if (mInjector.storageManagerIsNonDefaultBlockEncrypted()) {
-            return DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE;
-        } else if (mInjector.storageManagerIsEncrypted()) {
-            return DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE_DEFAULT_KEY;
-        } else if (mInjector.storageManagerIsEncryptable()) {
-            return DevicePolicyManager.ENCRYPTION_STATUS_INACTIVE;
         } else {
             return DevicePolicyManager.ENCRYPTION_STATUS_UNSUPPORTED;
         }
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 77d40d2..8e4afe6 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -159,6 +159,7 @@
 import com.android.server.pm.PackageManagerService;
 import com.android.server.pm.ShortcutService;
 import com.android.server.pm.UserManagerService;
+import com.android.server.pm.dex.OdsignStatsLogger;
 import com.android.server.pm.dex.SystemServerDexLoadReporter;
 import com.android.server.pm.verify.domain.DomainVerificationService;
 import com.android.server.policy.AppOpsPolicy;
@@ -2887,6 +2888,14 @@
                 setIncrementalServiceSystemReady(mIncrementalServiceHandle);
                 t.traceEnd();
             }
+
+            t.traceBegin("OdsignStatsLogger");
+            try {
+                OdsignStatsLogger.triggerStatsWrite();
+            } catch (Throwable e) {
+                reportWtf("Triggering OdsignStatsLogger", e);
+            }
+            t.traceEnd();
         }, t);
 
         t.traceBegin("StartSystemUI");
diff --git a/services/tests/servicestests/src/com/android/server/adb/AdbDebuggingManagerTest.java b/services/tests/servicestests/src/com/android/server/adb/AdbDebuggingManagerTest.java
index cffff66..02cf971 100644
--- a/services/tests/servicestests/src/com/android/server/adb/AdbDebuggingManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/adb/AdbDebuggingManagerTest.java
@@ -23,7 +23,14 @@
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
+import android.content.BroadcastReceiver;
 import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.debug.AdbManager;
+import android.debug.IAdbManager;
+import android.os.ServiceManager;
 import android.provider.Settings;
 import android.util.Log;
 
@@ -105,6 +112,7 @@
     public void tearDown() throws Exception {
         mKeyStore.deleteKeyStore();
         setAllowedConnectionTime(mOriginalAllowedConnectionTime);
+        dropShellPermissionIdentity();
     }
 
     /**
@@ -813,6 +821,108 @@
         return hasAtLeastOneLetter;
     }
 
+    CountDownLatch mAdbActionLatch = new CountDownLatch(1);
+    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            String action = intent.getAction();
+            Log.i(TAG, "Received intent action=" + action);
+            if (AdbManager.WIRELESS_DEBUG_PAIRED_DEVICES_ACTION.equals(action)) {
+                assertEquals("Received broadcast without MANAGE_DEBUGGING permission.",
+                        context.checkSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING),
+                        PackageManager.PERMISSION_GRANTED);
+                Log.i(TAG, "action=" + action + " paired_device=" + intent.getSerializableExtra(
+                        AdbManager.WIRELESS_DEVICES_EXTRA).toString());
+                mAdbActionLatch.countDown();
+            } else if (AdbManager.WIRELESS_DEBUG_STATE_CHANGED_ACTION.equals(action)) {
+                assertEquals("Received broadcast without MANAGE_DEBUGGING permission.",
+                        context.checkSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING),
+                        PackageManager.PERMISSION_GRANTED);
+                int status = intent.getIntExtra(AdbManager.WIRELESS_STATUS_EXTRA,
+                        AdbManager.WIRELESS_STATUS_DISCONNECTED);
+                Log.i(TAG, "action=" + action + " status=" + status);
+                mAdbActionLatch.countDown();
+            } else if (AdbManager.WIRELESS_DEBUG_PAIRING_RESULT_ACTION.equals(action)) {
+                assertEquals("Received broadcast without MANAGE_DEBUGGING permission.",
+                        context.checkSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING),
+                        PackageManager.PERMISSION_GRANTED);
+                Integer res = intent.getIntExtra(
+                        AdbManager.WIRELESS_STATUS_EXTRA,
+                        AdbManager.WIRELESS_STATUS_FAIL);
+                Log.i(TAG, "action=" + action + " result=" + res);
+
+                if (res.equals(AdbManager.WIRELESS_STATUS_PAIRING_CODE)) {
+                    String pairingCode = intent.getStringExtra(
+                                AdbManager.WIRELESS_PAIRING_CODE_EXTRA);
+                    Log.i(TAG, "pairingCode=" + pairingCode);
+                } else if (res.equals(AdbManager.WIRELESS_STATUS_CONNECTED)) {
+                    int port = intent.getIntExtra(AdbManager.WIRELESS_DEBUG_PORT_EXTRA, 0);
+                    Log.i(TAG, "port=" + port);
+                }
+                mAdbActionLatch.countDown();
+            }
+        }
+    };
+
+    private void adoptShellPermissionIdentity() {
+        InstrumentationRegistry.getInstrumentation().getUiAutomation()
+            .adoptShellPermissionIdentity(android.Manifest.permission.MANAGE_DEBUGGING);
+    }
+
+    private void dropShellPermissionIdentity() {
+        InstrumentationRegistry.getInstrumentation().getUiAutomation()
+            .dropShellPermissionIdentity();
+    }
+
+    @Test
+    public void testBroadcastReceiverWithPermissions() throws Exception {
+        adoptShellPermissionIdentity();
+        final IAdbManager mAdbManager = IAdbManager.Stub.asInterface(
+                ServiceManager.getService(Context.ADB_SERVICE));
+        IntentFilter intentFilter =
+                new IntentFilter(AdbManager.WIRELESS_DEBUG_PAIRED_DEVICES_ACTION);
+        intentFilter.addAction(AdbManager.WIRELESS_DEBUG_STATE_CHANGED_ACTION);
+        intentFilter.addAction(AdbManager.WIRELESS_DEBUG_PAIRING_RESULT_ACTION);
+        assertEquals("Context does not have MANAGE_DEBUGGING permission.",
+                mContext.checkSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING),
+                PackageManager.PERMISSION_GRANTED);
+        try {
+            mContext.registerReceiver(mReceiver, intentFilter);
+            mAdbManager.enablePairingByPairingCode();
+            if (!mAdbActionLatch.await(TIMEOUT, TIMEOUT_TIME_UNIT)) {
+                fail("Receiver did not receive adb intent action within the timeout duration");
+            }
+        } finally {
+            mContext.unregisterReceiver(mReceiver);
+        }
+    }
+
+    @Test
+    public void testBroadcastReceiverWithoutPermissions() throws Exception {
+        adoptShellPermissionIdentity();
+        final IAdbManager mAdbManager = IAdbManager.Stub.asInterface(
+                ServiceManager.getService(Context.ADB_SERVICE));
+        IntentFilter intentFilter =
+                new IntentFilter(AdbManager.WIRELESS_DEBUG_PAIRED_DEVICES_ACTION);
+        intentFilter.addAction(AdbManager.WIRELESS_DEBUG_STATE_CHANGED_ACTION);
+        intentFilter.addAction(AdbManager.WIRELESS_DEBUG_PAIRING_RESULT_ACTION);
+        mAdbManager.enablePairingByPairingCode();
+
+        dropShellPermissionIdentity();
+        assertEquals("Context has MANAGE_DEBUGGING permission.",
+                mContext.checkSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING),
+                PackageManager.PERMISSION_DENIED);
+        try {
+            mContext.registerReceiver(mReceiver, intentFilter);
+
+            if (mAdbActionLatch.await(TIMEOUT, TIMEOUT_TIME_UNIT)) {
+                fail("Broadcast receiver received adb action intent without debug permissions");
+            }
+        } finally {
+            mContext.unregisterReceiver(mReceiver);
+        }
+    }
+
     /**
      * Runs an adb test with the provided configuration.
      *
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
index 61d7ede..59236dc 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
@@ -255,21 +255,6 @@
         }
 
         @Override
-        boolean storageManagerIsNonDefaultBlockEncrypted() {
-            return services.storageManager.isNonDefaultBlockEncrypted();
-        }
-
-        @Override
-        boolean storageManagerIsEncrypted() {
-            return services.storageManager.isEncrypted();
-        }
-
-        @Override
-        boolean storageManagerIsEncryptable() {
-            return services.storageManager.isEncryptable();
-        }
-
-        @Override
         String getDevicePolicyFilePathForSystemUser() {
             return services.systemUserDataDir.getAbsolutePath() + "/";
         }
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java b/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java
index 8a2919d..248af0e 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java
@@ -492,18 +492,6 @@
         public boolean isFileBasedEncryptionEnabled() {
             return false;
         }
-
-        public boolean isNonDefaultBlockEncrypted() {
-            return false;
-        }
-
-        public boolean isEncrypted() {
-            return false;
-        }
-
-        public boolean isEncryptable() {
-            return false;
-        }
     }
 
     // We have to keep track of broadcast receivers registered for a given intent ourselves as the
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java
index 524ad62..77af225 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java
@@ -1789,4 +1789,32 @@
         assertThat(mNativeWrapper.getResultMessages()).doesNotContain(featureAbortPressed);
         assertThat(mNativeWrapper.getResultMessages()).doesNotContain(featureAbortReleased);
     }
+
+    @Test
+    public void onHotplugClearsDevices() {
+        mHdmiControlService.getHdmiCecNetwork().clearDeviceList();
+        assertThat(mHdmiControlService.getHdmiCecNetwork().getDeviceInfoList(false))
+                .isEmpty();
+        // Add a device to the network and assert that this device is included in the list of
+        // devices.
+        HdmiDeviceInfo infoPlayback = new HdmiDeviceInfo(
+                Constants.ADDR_PLAYBACK_3,
+                0x1000,
+                PORT_1,
+                HdmiDeviceInfo.DEVICE_PLAYBACK,
+                0x1000,
+                "Playback 3",
+                HdmiControlManager.POWER_STATUS_ON);
+        mHdmiControlService.getHdmiCecNetwork().addCecDevice(infoPlayback);
+        mTestLooper.dispatchAll();
+        assertThat(mHdmiControlService.getHdmiCecNetwork().getDeviceInfoList(false))
+                .hasSize(1);
+
+        // HAL detects a hotplug out. Assert that this device gets removed from the list of devices.
+        mHdmiControlService.onHotplug(PORT_1, false);
+        mTestLooper.dispatchAll();
+
+        assertThat(mHdmiControlService.getHdmiCecNetwork().getDeviceInfoList(false))
+                .isEmpty();
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java
index 59711a6..0afd27c 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java
@@ -19,6 +19,7 @@
 import static com.android.server.hdmi.Constants.ADDR_AUDIO_SYSTEM;
 import static com.android.server.hdmi.Constants.ADDR_BROADCAST;
 import static com.android.server.hdmi.Constants.ADDR_PLAYBACK_1;
+import static com.android.server.hdmi.Constants.ADDR_PLAYBACK_2;
 import static com.android.server.hdmi.Constants.ADDR_RECORDER_1;
 import static com.android.server.hdmi.Constants.ADDR_TV;
 import static com.android.server.hdmi.HdmiControlService.INITIATED_BY_ENABLE_CEC;
@@ -56,12 +57,14 @@
 import org.mockito.MockitoAnnotations;
 
 import java.util.ArrayList;
+import java.util.List;
 
 @SmallTest
 @RunWith(JUnit4.class)
 /** Tests for {@link HdmiCecLocalDeviceTv} class. */
 public class HdmiCecLocalDeviceTvTest {
     private static final int TIMEOUT_MS = HdmiConfig.TIMEOUT_MS + 1;
+    private static final int PORT_1 = 1;
 
     private HdmiControlService mHdmiControlService;
     private HdmiCecController mHdmiCecController;
@@ -73,6 +76,25 @@
     private int mTvPhysicalAddress;
     private int mTvLogicalAddress;
     private boolean mWokenUp;
+    private List<DeviceEventListener> mDeviceEventListeners = new ArrayList<>();
+
+    private class DeviceEventListener {
+        private HdmiDeviceInfo mDevice;
+        private int mStatus;
+
+        DeviceEventListener(HdmiDeviceInfo device, int status) {
+            this.mDevice = device;
+            this.mStatus = status;
+        }
+
+        int getStatus() {
+            return mStatus;
+        }
+
+        HdmiDeviceInfo getDeviceInfo() {
+            return mDevice;
+        }
+    }
 
     @Mock
     private IPowerManager mIPowerManagerMock;
@@ -124,6 +146,11 @@
                     AudioManager getAudioManager() {
                         return mAudioManager;
                     }
+
+                    @Override
+                    void invokeDeviceEventListeners(HdmiDeviceInfo device, int status) {
+                        mDeviceEventListeners.add(new DeviceEventListener(device, status));
+                    }
                 };
 
         mHdmiCecLocalDeviceTv = new HdmiCecLocalDeviceTv(mHdmiControlService);
@@ -596,4 +623,147 @@
 
         verify(mAudioManager, never()).setStreamVolume(anyInt(), anyInt(), anyInt());
     }
+
+    @Test
+    public void hotplugDetectionActionClearsDevices() {
+        mHdmiControlService.getHdmiCecNetwork().clearDeviceList();
+        assertThat(mHdmiControlService.getHdmiCecNetwork().getDeviceInfoList(false))
+                .isEmpty();
+        // Add a device to the network and assert that this device is included in the list of
+        // devices.
+        HdmiDeviceInfo infoPlayback = new HdmiDeviceInfo(
+                Constants.ADDR_PLAYBACK_2,
+                0x1000,
+                PORT_1,
+                HdmiDeviceInfo.DEVICE_PLAYBACK,
+                0x1000,
+                "Playback 2",
+                HdmiControlManager.POWER_STATUS_ON);
+        mHdmiControlService.getHdmiCecNetwork().addCecDevice(infoPlayback);
+        mTestLooper.dispatchAll();
+        assertThat(mHdmiControlService.getHdmiCecNetwork().getDeviceInfoList(false))
+                .hasSize(1);
+        mDeviceEventListeners.clear();
+        assertThat(mDeviceEventListeners.size()).isEqualTo(0);
+
+        // HAL detects a hotplug out. Assert that this device stays in the list of devices.
+        mHdmiControlService.onHotplug(PORT_1, false);
+        assertThat(mHdmiControlService.getHdmiCecNetwork().getDeviceInfoList(false))
+                .hasSize(1);
+        assertThat(mDeviceEventListeners).isEmpty();
+        mTestLooper.dispatchAll();
+        // Make the device not acknowledge the poll message sent by the HotplugDetectionAction.
+        // Assert that this device is removed from the list of devices.
+        mNativeWrapper.setPollAddressResponse(Constants.ADDR_PLAYBACK_2, SendMessageResult.NACK);
+        for (int pollCount = 0; pollCount < HotplugDetectionAction.TIMEOUT_COUNT; pollCount++) {
+            mTestLooper.moveTimeForward(HotplugDetectionAction.POLLING_INTERVAL_MS);
+            mTestLooper.dispatchAll();
+        }
+
+        assertThat(mHdmiControlService.getHdmiCecNetwork().getDeviceInfoList(false))
+                .isEmpty();
+        assertThat(mDeviceEventListeners.size()).isEqualTo(1);
+        assertThat(mDeviceEventListeners.get(0).getStatus())
+                .isEqualTo(HdmiControlManager.DEVICE_EVENT_REMOVE_DEVICE);
+        HdmiDeviceInfo removedDeviceInfo = mDeviceEventListeners.get(0).getDeviceInfo();
+        assertThat(removedDeviceInfo.getPortId()).isEqualTo(PORT_1);
+        assertThat(removedDeviceInfo.getLogicalAddress()).isEqualTo(Constants.ADDR_PLAYBACK_2);
+        assertThat(removedDeviceInfo.getPhysicalAddress()).isEqualTo(0x1000);
+        assertThat(removedDeviceInfo.getDeviceType()).isEqualTo(HdmiDeviceInfo.DEVICE_PLAYBACK);
+    }
+
+    @Test
+    public void hotplugDetectionActionClearsDevices_AudioSystem() {
+        mHdmiControlService.getHdmiCecNetwork().clearDeviceList();
+        assertThat(mHdmiControlService.getHdmiCecNetwork().getDeviceInfoList(false))
+                .isEmpty();
+        // Add a device to the network and assert that this device is included in the list of
+        // devices.
+        HdmiDeviceInfo infoAudioSystem = new HdmiDeviceInfo(
+                ADDR_AUDIO_SYSTEM,
+                0x1000,
+                PORT_1,
+                HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM,
+                0x1000,
+                "Audio System",
+                HdmiControlManager.POWER_STATUS_ON);
+        mHdmiControlService.getHdmiCecNetwork().addCecDevice(infoAudioSystem);
+        mTestLooper.dispatchAll();
+        assertThat(mHdmiControlService.getHdmiCecNetwork().getDeviceInfoList(false))
+                .hasSize(1);
+        mDeviceEventListeners.clear();
+        assertThat(mDeviceEventListeners.size()).isEqualTo(0);
+
+        // HAL detects a hotplug out. Assert that this device stays in the list of devices.
+        mHdmiControlService.onHotplug(PORT_1, false);
+        assertThat(mHdmiControlService.getHdmiCecNetwork().getDeviceInfoList(false))
+                .hasSize(1);
+        assertThat(mDeviceEventListeners).isEmpty();
+        mTestLooper.dispatchAll();
+        // Make the device not acknowledge the poll message sent by the HotplugDetectionAction.
+        // Assert that this device is removed from the list of devices.
+        mNativeWrapper.setPollAddressResponse(ADDR_AUDIO_SYSTEM, SendMessageResult.NACK);
+        for (int pollCount = 0; pollCount < HotplugDetectionAction.TIMEOUT_COUNT; pollCount++) {
+            mTestLooper.moveTimeForward(HotplugDetectionAction.POLLING_INTERVAL_MS);
+            mTestLooper.dispatchAll();
+        }
+
+        assertThat(mHdmiControlService.getHdmiCecNetwork().getDeviceInfoList(false))
+                .isEmpty();
+        assertThat(mDeviceEventListeners.size()).isEqualTo(1);
+        assertThat(mDeviceEventListeners.get(0).getStatus())
+                .isEqualTo(HdmiControlManager.DEVICE_EVENT_REMOVE_DEVICE);
+        HdmiDeviceInfo removedDeviceInfo = mDeviceEventListeners.get(0).getDeviceInfo();
+        assertThat(removedDeviceInfo.getPortId()).isEqualTo(PORT_1);
+        assertThat(removedDeviceInfo.getLogicalAddress()).isEqualTo(Constants.ADDR_AUDIO_SYSTEM);
+        assertThat(removedDeviceInfo.getPhysicalAddress()).isEqualTo(0x1000);
+        assertThat(removedDeviceInfo.getDeviceType()).isEqualTo(HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM);
+    }
+
+    @Test
+    public void listenerInvokedIfPhysicalAddressReported() {
+        mHdmiControlService.getHdmiCecNetwork().clearDeviceList();
+        assertThat(mHdmiControlService.getHdmiCecNetwork().getDeviceInfoList(false))
+                .isEmpty();
+        HdmiCecMessage reportPhysicalAddress =
+                HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
+                ADDR_PLAYBACK_2, 0x1000, HdmiDeviceInfo.DEVICE_PLAYBACK);
+        mNativeWrapper.onCecMessage(reportPhysicalAddress);
+        mTestLooper.dispatchAll();
+
+        assertThat(mHdmiControlService.getHdmiCecNetwork().getDeviceInfoList(false))
+                .hasSize(1);
+        assertThat(mDeviceEventListeners.size()).isEqualTo(1);
+        assertThat(mDeviceEventListeners.get(0).getStatus())
+                .isEqualTo(HdmiControlManager.DEVICE_EVENT_ADD_DEVICE);
+    }
+
+    @Test
+    public void listenerNotInvokedIfPhysicalAddressUnknown() {
+        mHdmiControlService.getHdmiCecNetwork().clearDeviceList();
+        assertThat(mHdmiControlService.getHdmiCecNetwork().getDeviceInfoList(false))
+                .isEmpty();
+        HdmiCecMessage setOsdName = HdmiCecMessageBuilder.buildSetOsdNameCommand(
+                ADDR_PLAYBACK_2, ADDR_TV, "Playback 2");
+        mNativeWrapper.onCecMessage(setOsdName);
+        mTestLooper.dispatchAll();
+
+        assertThat(mHdmiControlService.getHdmiCecNetwork().getDeviceInfoList(false))
+                .hasSize(1);
+        assertThat(mDeviceEventListeners).isEmpty();
+
+        // When the device reports its physical address, the listener eventually is invoked.
+        HdmiCecMessage reportPhysicalAddress =
+                HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
+                ADDR_PLAYBACK_2, 0x1000, HdmiDeviceInfo.DEVICE_PLAYBACK);
+        mNativeWrapper.onCecMessage(reportPhysicalAddress);
+        mTestLooper.dispatchAll();
+
+        assertThat(mHdmiControlService.getHdmiCecNetwork().getDeviceInfoList(false))
+                .hasSize(1);
+        assertThat(mDeviceEventListeners.size()).isEqualTo(1);
+        assertThat(mDeviceEventListeners.get(0).getStatus())
+                .isEqualTo(HdmiControlManager.DEVICE_EVENT_ADD_DEVICE);
+
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecNetworkTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecNetworkTest.java
index b1998f5..c617d21 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecNetworkTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecNetworkTest.java
@@ -100,6 +100,8 @@
                 new HdmiPortInfo(5, HdmiPortInfo.PORT_OUTPUT, 0x0000, true, false, false);
         mNativeWrapper.setPortInfo(mHdmiPortInfo);
         mHdmiCecNetwork.initPortInfo();
+
+        mHdmiCecNetwork = mHdmiControlService.getHdmiCecNetwork();
     }
 
     @Test
@@ -140,7 +142,24 @@
     }
 
     @Test
+    public void physicalAddressToPort_localDevice_weAreSourceDevice() {
+        mNativeWrapper.setPhysicalAddress(0x2000);
+        mHdmiCecNetwork.initPortInfo();
+        assertThat(mHdmiCecNetwork.physicalAddressToPortId(0x2000))
+                .isEqualTo(Constants.CEC_SWITCH_HOME);
+    }
+
+    @Test
+    public void physicalAddressToPort_localDevice_weAreTv() {
+        mNativeWrapper.setPhysicalAddress(0x0000);
+        mHdmiCecNetwork.initPortInfo();
+        assertThat(mHdmiCecNetwork.physicalAddressToPortId(0x0000))
+                .isEqualTo(Constants.CEC_SWITCH_HOME);
+    }
+
+    @Test
     public void localDevices_verifyOne_tv() {
+        mHdmiCecNetwork.clearLocalDevices();
         mHdmiCecNetwork.addLocalDevice(HdmiDeviceInfo.DEVICE_TV,
                 new HdmiCecLocalDeviceTv(mHdmiControlService));
 
@@ -153,6 +172,7 @@
 
     @Test
     public void localDevices_verifyOne_playback() {
+        mHdmiCecNetwork.clearLocalDevices();
         mHdmiCecNetwork.addLocalDevice(HdmiDeviceInfo.DEVICE_PLAYBACK,
                 new HdmiCecLocalDevicePlayback(mHdmiControlService));
 
@@ -175,27 +195,26 @@
         assertThat(cecDeviceInfo.getLogicalAddress()).isEqualTo(logicalAddress);
         assertThat(cecDeviceInfo.getPhysicalAddress()).isEqualTo(
                 Constants.INVALID_PHYSICAL_ADDRESS);
-        assertThat(cecDeviceInfo.getDeviceType()).isEqualTo(HdmiDeviceInfo.DEVICE_RESERVED);
+        assertThat(cecDeviceInfo.getDeviceType()).isEqualTo(HdmiDeviceInfo.DEVICE_PLAYBACK);
         assertThat(cecDeviceInfo.getDisplayName()).isEqualTo(
                 HdmiUtils.getDefaultDeviceName(logicalAddress));
         assertThat(cecDeviceInfo.getVendorId()).isEqualTo(Constants.UNKNOWN_VENDOR_ID);
         assertThat(cecDeviceInfo.getDevicePowerStatus()).isEqualTo(
                 HdmiControlManager.POWER_STATUS_UNKNOWN);
 
-        assertThat(mDeviceEventListenerStatuses).containsExactly(
-                HdmiControlManager.DEVICE_EVENT_ADD_DEVICE);
+        assertThat(mDeviceEventListenerStatuses).isEmpty();
     }
 
     @Test
     public void cecDevices_tracking_logicalAddressOnly_doesntNotifyAgain() throws Exception {
         int logicalAddress = Constants.ADDR_PLAYBACK_1;
+        int physicalAddress = 0x1000;
         mHdmiCecNetwork.handleCecMessage(
-                HdmiCecMessageBuilder.buildActiveSource(logicalAddress, 0x1000));
+                HdmiCecMessageBuilder.buildActiveSource(logicalAddress, physicalAddress));
         mHdmiCecNetwork.handleCecMessage(
-                HdmiCecMessageBuilder.buildActiveSource(logicalAddress, 0x1000));
+                HdmiCecMessageBuilder.buildActiveSource(logicalAddress, physicalAddress));
 
-        assertThat(mDeviceEventListenerStatuses).containsExactly(
-                HdmiControlManager.DEVICE_EVENT_ADD_DEVICE);
+        assertThat(mDeviceEventListenerStatuses).isEmpty();
     }
 
     @Test
@@ -219,6 +238,9 @@
         assertThat(cecDeviceInfo.getVendorId()).isEqualTo(Constants.UNKNOWN_VENDOR_ID);
         assertThat(cecDeviceInfo.getDevicePowerStatus()).isEqualTo(
                 HdmiControlManager.POWER_STATUS_UNKNOWN);
+
+        assertThat(mDeviceEventListenerStatuses).containsExactly(
+                HdmiControlManager.DEVICE_EVENT_ADD_DEVICE);
     }
 
     @Test
@@ -236,11 +258,10 @@
                         physicalAddress, type));
 
 
-        // ADD for logical address first detected
-        // UPDATE for updating device with physical address
+        // ADD for physical address first detected
+        // no UPDATE, since physical address didn't change
         assertThat(mDeviceEventListenerStatuses).containsExactly(
-                HdmiControlManager.DEVICE_EVENT_ADD_DEVICE,
-                HdmiControlManager.DEVICE_EVENT_UPDATE_DEVICE);
+                HdmiControlManager.DEVICE_EVENT_ADD_DEVICE);
     }
 
     @Test
@@ -257,11 +278,13 @@
         assertThat(cecDeviceInfo.getLogicalAddress()).isEqualTo(logicalAddress);
         assertThat(cecDeviceInfo.getPhysicalAddress()).isEqualTo(
                 Constants.INVALID_PHYSICAL_ADDRESS);
-        assertThat(cecDeviceInfo.getDeviceType()).isEqualTo(HdmiDeviceInfo.DEVICE_RESERVED);
+        assertThat(cecDeviceInfo.getDeviceType()).isEqualTo(HdmiDeviceInfo.DEVICE_PLAYBACK);
         assertThat(cecDeviceInfo.getVendorId()).isEqualTo(Constants.UNKNOWN_VENDOR_ID);
         assertThat(cecDeviceInfo.getDisplayName()).isEqualTo(
                 HdmiUtils.getDefaultDeviceName(logicalAddress));
         assertThat(cecDeviceInfo.getDevicePowerStatus()).isEqualTo(powerStatus);
+
+        assertThat(mDeviceEventListenerStatuses).isEmpty();
     }
 
     @Test
@@ -278,11 +301,13 @@
         assertThat(cecDeviceInfo.getLogicalAddress()).isEqualTo(logicalAddress);
         assertThat(cecDeviceInfo.getPhysicalAddress()).isEqualTo(
                 Constants.INVALID_PHYSICAL_ADDRESS);
-        assertThat(cecDeviceInfo.getDeviceType()).isEqualTo(HdmiDeviceInfo.DEVICE_RESERVED);
+        assertThat(cecDeviceInfo.getDeviceType()).isEqualTo(HdmiDeviceInfo.DEVICE_PLAYBACK);
         assertThat(cecDeviceInfo.getVendorId()).isEqualTo(Constants.UNKNOWN_VENDOR_ID);
         assertThat(cecDeviceInfo.getDisplayName()).isEqualTo(osdName);
         assertThat(cecDeviceInfo.getDevicePowerStatus()).isEqualTo(
                 HdmiControlManager.POWER_STATUS_UNKNOWN);
+
+        assertThat(mDeviceEventListenerStatuses).isEmpty();
     }
 
     @Test
@@ -298,12 +323,14 @@
         assertThat(cecDeviceInfo.getLogicalAddress()).isEqualTo(logicalAddress);
         assertThat(cecDeviceInfo.getPhysicalAddress()).isEqualTo(
                 Constants.INVALID_PHYSICAL_ADDRESS);
-        assertThat(cecDeviceInfo.getDeviceType()).isEqualTo(HdmiDeviceInfo.DEVICE_RESERVED);
+        assertThat(cecDeviceInfo.getDeviceType()).isEqualTo(HdmiDeviceInfo.DEVICE_PLAYBACK);
         assertThat(cecDeviceInfo.getDisplayName()).isEqualTo(
                 HdmiUtils.getDefaultDeviceName(logicalAddress));
         assertThat(cecDeviceInfo.getVendorId()).isEqualTo(vendorId);
         assertThat(cecDeviceInfo.getDevicePowerStatus()).isEqualTo(
                 HdmiControlManager.POWER_STATUS_UNKNOWN);
+
+        assertThat(mDeviceEventListenerStatuses).isEmpty();
     }
 
     @Test
@@ -362,12 +389,10 @@
         assertThat(cecDeviceInfo.getPhysicalAddress()).isEqualTo(updatedPhysicalAddress);
         assertThat(cecDeviceInfo.getDeviceType()).isEqualTo(type);
 
-        // ADD for logical address first detected
-        // UPDATE for updating device with physical address
+        // ADD for physical address first detected
         // UPDATE for updating device with new physical address
         assertThat(mDeviceEventListenerStatuses).containsExactly(
                 HdmiControlManager.DEVICE_EVENT_ADD_DEVICE,
-                HdmiControlManager.DEVICE_EVENT_UPDATE_DEVICE,
                 HdmiControlManager.DEVICE_EVENT_UPDATE_DEVICE);
     }
 
@@ -429,7 +454,7 @@
         assertThat(cecDeviceInfo.getLogicalAddress()).isEqualTo(logicalAddress);
         assertThat(cecDeviceInfo.getPhysicalAddress()).isEqualTo(
                 Constants.INVALID_PHYSICAL_ADDRESS);
-        assertThat(cecDeviceInfo.getDeviceType()).isEqualTo(HdmiDeviceInfo.DEVICE_RESERVED);
+        assertThat(cecDeviceInfo.getDeviceType()).isEqualTo(HdmiDeviceInfo.DEVICE_PLAYBACK);
         assertThat(cecDeviceInfo.getDisplayName()).isEqualTo(
                 HdmiUtils.getDefaultDeviceName(logicalAddress));
         assertThat(cecDeviceInfo.getVendorId()).isEqualTo(updatedVendorId);
@@ -451,9 +476,8 @@
 
         assertThat(mHdmiCecNetwork.getSafeCecDevicesLocked()).isEmpty();
 
-        assertThat(mDeviceEventListenerStatuses).containsExactly(
-                HdmiControlManager.DEVICE_EVENT_ADD_DEVICE,
-                HdmiControlManager.DEVICE_EVENT_REMOVE_DEVICE);
+        // Physical address never got reported, so no listeners are triggered
+        assertThat(mDeviceEventListenerStatuses).isEmpty();
     }
 
     @Test
@@ -470,7 +494,7 @@
         assertThat(cecDeviceInfo.getLogicalAddress()).isEqualTo(logicalAddress);
         assertThat(cecDeviceInfo.getPhysicalAddress()).isEqualTo(
                 Constants.INVALID_PHYSICAL_ADDRESS);
-        assertThat(cecDeviceInfo.getDeviceType()).isEqualTo(HdmiDeviceInfo.DEVICE_RESERVED);
+        assertThat(cecDeviceInfo.getDeviceType()).isEqualTo(HdmiDeviceInfo.DEVICE_PLAYBACK);
         assertThat(cecDeviceInfo.getVendorId()).isEqualTo(Constants.UNKNOWN_VENDOR_ID);
         assertThat(cecDeviceInfo.getDisplayName()).isEqualTo(
                 HdmiUtils.getDefaultDeviceName(logicalAddress));
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsShellCommandTest.java b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsShellCommandTest.java
index 33ea710..b9ae670 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsShellCommandTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsShellCommandTest.java
@@ -25,6 +25,8 @@
 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
 
+import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN;
+
 import static junit.framework.Assert.assertEquals;
 
 import static org.mockito.ArgumentMatchers.anyInt;
@@ -48,6 +50,7 @@
 import android.os.Process;
 import android.os.ResultReceiver;
 import android.os.ShellCallback;
+import android.os.UserHandle;
 import android.platform.test.annotations.Presubmit;
 
 import androidx.test.InstrumentationRegistry;
@@ -370,6 +373,19 @@
                 mUserId);
     }
 
+    @Test
+    public void testRequireStrongAuth_STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN() throws Exception {
+        when(mLockPatternUtils.isSecure(mUserId)).thenReturn(true);
+
+        assertEquals(0, mCommand.exec(new Binder(), in, out, err,
+                new String[] { "require-strong-auth", "STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN"},
+                mShellCallback, mResultReceiver));
+
+        verify(mLockPatternUtils).requireStrongAuth(
+                STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN,
+                UserHandle.USER_ALL);
+    }
+
     private List<LockPatternView.Cell> stringToPattern(String str) {
         return LockPatternUtils.byteArrayToPattern(str.getBytes());
     }
diff --git a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
index f865a50..af8ac6f 100644
--- a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
@@ -23,11 +23,13 @@
 import static android.net.ConnectivityManager.BLOCKED_REASON_APP_STANDBY;
 import static android.net.ConnectivityManager.BLOCKED_REASON_BATTERY_SAVER;
 import static android.net.ConnectivityManager.BLOCKED_REASON_DOZE;
+import static android.net.ConnectivityManager.BLOCKED_REASON_LOW_POWER_STANDBY;
 import static android.net.ConnectivityManager.BLOCKED_REASON_NONE;
 import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_LOW_POWER_STANDBY;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_RESTRICTED;
 import static android.net.ConnectivityManager.TYPE_MOBILE;
 import static android.net.ConnectivityManager.TYPE_WIFI;
-import static android.net.INetd.FIREWALL_CHAIN_RESTRICTED;
 import static android.net.INetd.FIREWALL_RULE_ALLOW;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING;
 import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
@@ -38,8 +40,10 @@
 import static android.net.NetworkPolicyManager.ALLOWED_METERED_REASON_FOREGROUND;
 import static android.net.NetworkPolicyManager.ALLOWED_METERED_REASON_SYSTEM;
 import static android.net.NetworkPolicyManager.ALLOWED_REASON_FOREGROUND;
+import static android.net.NetworkPolicyManager.ALLOWED_REASON_LOW_POWER_STANDBY_ALLOWLIST;
 import static android.net.NetworkPolicyManager.ALLOWED_REASON_NONE;
 import static android.net.NetworkPolicyManager.ALLOWED_REASON_SYSTEM;
+import static android.net.NetworkPolicyManager.ALLOWED_REASON_TOP;
 import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT;
 import static android.net.NetworkPolicyManager.POLICY_ALLOW_METERED_BACKGROUND;
 import static android.net.NetworkPolicyManager.POLICY_NONE;
@@ -200,6 +204,7 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Calendar;
+import java.util.HashMap;
 import java.util.Iterator;
 import java.util.LinkedHashSet;
 import java.util.List;
@@ -1877,55 +1882,99 @@
     }
 
     @Test
+    public void testLowPowerStandbyAllowlist() throws Exception {
+        callOnUidStateChanged(UID_A, ActivityManager.PROCESS_STATE_TOP, 0);
+        callOnUidStateChanged(UID_B, ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE, 0);
+        callOnUidStateChanged(UID_C, ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE, 0);
+        expectHasInternetPermission(UID_A, true);
+        expectHasInternetPermission(UID_B, true);
+        expectHasInternetPermission(UID_C, true);
+
+        final NetworkPolicyManagerInternal internal = LocalServices
+                .getService(NetworkPolicyManagerInternal.class);
+
+        Map<Integer, Integer> firewallUidRules = new ArrayMap<>();
+        doAnswer(arg -> {
+            int[] uids = arg.getArgument(1);
+            int[] rules = arg.getArgument(2);
+            assertTrue(uids.length == rules.length);
+
+            for (int i = 0; i < uids.length; ++i) {
+                firewallUidRules.put(uids[i], rules[i]);
+            }
+            return null;
+        }).when(mNetworkManager).setFirewallUidRules(eq(FIREWALL_CHAIN_LOW_POWER_STANDBY),
+                any(int[].class), any(int[].class));
+
+        internal.setLowPowerStandbyAllowlist(new int[] { UID_B });
+        internal.setLowPowerStandbyActive(true);
+        assertEquals(FIREWALL_RULE_ALLOW, firewallUidRules.get(UID_A).intValue());
+        assertEquals(FIREWALL_RULE_ALLOW, firewallUidRules.get(UID_B).intValue());
+        assertFalse(mService.isUidNetworkingBlocked(UID_A, false));
+        assertFalse(mService.isUidNetworkingBlocked(UID_B, false));
+        assertTrue(mService.isUidNetworkingBlocked(UID_C, false));
+
+        internal.setLowPowerStandbyActive(false);
+        assertFalse(mService.isUidNetworkingBlocked(UID_A, false));
+        assertFalse(mService.isUidNetworkingBlocked(UID_B, false));
+        assertFalse(mService.isUidNetworkingBlocked(UID_C, false));
+    }
+
+    @Test
     public void testUpdateEffectiveBlockedReasons() {
-        final SparseArray<Pair<Integer, Integer>> effectiveBlockedReasons = new SparseArray<>();
-        effectiveBlockedReasons.put(BLOCKED_REASON_NONE,
-                Pair.create(BLOCKED_REASON_NONE, ALLOWED_REASON_NONE));
+        final Map<Pair<Integer, Integer>, Integer> effectiveBlockedReasons = new HashMap<>();
+        effectiveBlockedReasons.put(Pair.create(BLOCKED_REASON_NONE, ALLOWED_REASON_NONE),
+                BLOCKED_REASON_NONE);
 
-        effectiveBlockedReasons.put(BLOCKED_REASON_NONE,
-                Pair.create(BLOCKED_REASON_BATTERY_SAVER, ALLOWED_REASON_SYSTEM));
-        effectiveBlockedReasons.put(BLOCKED_REASON_NONE,
-                Pair.create(BLOCKED_REASON_BATTERY_SAVER | BLOCKED_REASON_DOZE,
-                        ALLOWED_REASON_SYSTEM));
-        effectiveBlockedReasons.put(BLOCKED_REASON_NONE,
-                Pair.create(BLOCKED_METERED_REASON_DATA_SAVER,
-                        ALLOWED_METERED_REASON_SYSTEM));
-        effectiveBlockedReasons.put(BLOCKED_REASON_NONE,
-                Pair.create(BLOCKED_METERED_REASON_DATA_SAVER
-                                | BLOCKED_METERED_REASON_USER_RESTRICTED,
-                        ALLOWED_METERED_REASON_SYSTEM));
+        effectiveBlockedReasons.put(
+                Pair.create(BLOCKED_REASON_BATTERY_SAVER, ALLOWED_REASON_SYSTEM),
+                BLOCKED_REASON_NONE);
+        effectiveBlockedReasons.put(Pair.create(BLOCKED_REASON_BATTERY_SAVER | BLOCKED_REASON_DOZE,
+                ALLOWED_REASON_SYSTEM), BLOCKED_REASON_NONE);
+        effectiveBlockedReasons.put(
+                Pair.create(BLOCKED_METERED_REASON_DATA_SAVER, ALLOWED_METERED_REASON_SYSTEM),
+                BLOCKED_REASON_NONE);
+        effectiveBlockedReasons.put(Pair.create(BLOCKED_METERED_REASON_DATA_SAVER
+                        | BLOCKED_METERED_REASON_USER_RESTRICTED,
+                ALLOWED_METERED_REASON_SYSTEM), BLOCKED_REASON_NONE);
 
-        effectiveBlockedReasons.put(BLOCKED_METERED_REASON_DATA_SAVER,
+        effectiveBlockedReasons.put(
                 Pair.create(BLOCKED_REASON_BATTERY_SAVER | BLOCKED_METERED_REASON_DATA_SAVER,
-                        ALLOWED_REASON_SYSTEM));
-        effectiveBlockedReasons.put(BLOCKED_REASON_APP_STANDBY,
+                        ALLOWED_REASON_SYSTEM), BLOCKED_METERED_REASON_DATA_SAVER);
+        effectiveBlockedReasons.put(
                 Pair.create(BLOCKED_REASON_APP_STANDBY | BLOCKED_METERED_REASON_USER_RESTRICTED,
-                        ALLOWED_METERED_REASON_SYSTEM));
+                        ALLOWED_METERED_REASON_SYSTEM), BLOCKED_REASON_APP_STANDBY);
 
-        effectiveBlockedReasons.put(BLOCKED_REASON_NONE,
-                Pair.create(BLOCKED_REASON_BATTERY_SAVER, ALLOWED_REASON_FOREGROUND));
-        effectiveBlockedReasons.put(BLOCKED_REASON_NONE,
-                Pair.create(BLOCKED_REASON_BATTERY_SAVER | BLOCKED_REASON_DOZE,
-                        ALLOWED_REASON_FOREGROUND));
-        effectiveBlockedReasons.put(BLOCKED_REASON_NONE,
-                Pair.create(BLOCKED_METERED_REASON_DATA_SAVER, ALLOWED_METERED_REASON_FOREGROUND));
-        effectiveBlockedReasons.put(BLOCKED_REASON_NONE,
-                Pair.create(BLOCKED_METERED_REASON_DATA_SAVER
-                                | BLOCKED_METERED_REASON_USER_RESTRICTED,
-                        ALLOWED_METERED_REASON_FOREGROUND));
-        effectiveBlockedReasons.put(BLOCKED_METERED_REASON_DATA_SAVER,
+        effectiveBlockedReasons.put(
+                Pair.create(BLOCKED_REASON_BATTERY_SAVER, ALLOWED_REASON_FOREGROUND),
+                BLOCKED_REASON_NONE);
+        effectiveBlockedReasons.put(Pair.create(BLOCKED_REASON_BATTERY_SAVER | BLOCKED_REASON_DOZE,
+                ALLOWED_REASON_FOREGROUND), BLOCKED_REASON_NONE);
+        effectiveBlockedReasons.put(
+                Pair.create(BLOCKED_METERED_REASON_DATA_SAVER, ALLOWED_METERED_REASON_FOREGROUND),
+                BLOCKED_REASON_NONE);
+        effectiveBlockedReasons.put(Pair.create(BLOCKED_METERED_REASON_DATA_SAVER
+                        | BLOCKED_METERED_REASON_USER_RESTRICTED,
+                ALLOWED_METERED_REASON_FOREGROUND), BLOCKED_REASON_NONE);
+        effectiveBlockedReasons.put(
                 Pair.create(BLOCKED_REASON_BATTERY_SAVER | BLOCKED_METERED_REASON_DATA_SAVER,
-                        ALLOWED_REASON_FOREGROUND));
-        effectiveBlockedReasons.put(BLOCKED_REASON_BATTERY_SAVER,
-                Pair.create(BLOCKED_REASON_BATTERY_SAVER
-                                | BLOCKED_METERED_REASON_USER_RESTRICTED,
-                        ALLOWED_METERED_REASON_FOREGROUND));
+                        ALLOWED_REASON_FOREGROUND), BLOCKED_METERED_REASON_DATA_SAVER);
+        effectiveBlockedReasons.put(Pair.create(BLOCKED_REASON_BATTERY_SAVER
+                        | BLOCKED_METERED_REASON_USER_RESTRICTED,
+                ALLOWED_METERED_REASON_FOREGROUND), BLOCKED_REASON_BATTERY_SAVER);
+
+        effectiveBlockedReasons.put(Pair.create(BLOCKED_REASON_LOW_POWER_STANDBY,
+                ALLOWED_REASON_FOREGROUND), BLOCKED_REASON_LOW_POWER_STANDBY);
+        effectiveBlockedReasons.put(Pair.create(BLOCKED_REASON_LOW_POWER_STANDBY,
+                ALLOWED_REASON_TOP), BLOCKED_REASON_NONE);
+        effectiveBlockedReasons.put(Pair.create(BLOCKED_REASON_LOW_POWER_STANDBY,
+                ALLOWED_REASON_LOW_POWER_STANDBY_ALLOWLIST), BLOCKED_REASON_NONE);
         // TODO: test more combinations of blocked reasons.
 
-        for (int i = 0; i < effectiveBlockedReasons.size(); ++i) {
-            final int expectedEffectiveBlockedReasons = effectiveBlockedReasons.keyAt(i);
-            final int blockedReasons = effectiveBlockedReasons.valueAt(i).first;
-            final int allowedReasons = effectiveBlockedReasons.valueAt(i).second;
+        for (Map.Entry<Pair<Integer, Integer>, Integer> test : effectiveBlockedReasons.entrySet()) {
+            final int expectedEffectiveBlockedReasons = test.getValue();
+            final int blockedReasons = test.getKey().first;
+            final int allowedReasons = test.getKey().second;
             final String errorMsg = "Expected="
                     + blockedReasonsToString(expectedEffectiveBlockedReasons)
                     + "; blockedReasons=" + blockedReasonsToString(blockedReasons)
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/GroupHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/GroupHelperTest.java
index 721641a..5458a5b 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/GroupHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/GroupHelperTest.java
@@ -174,7 +174,7 @@
         }
 
         verify(mCallback, times(AUTOGROUP_AT_COUNT + 1))
-            .updateAutogroupSummary(anyString(), eq(true));
+            .updateAutogroupSummary(anyInt(), anyString(), eq(true));
 
         int userId = UserHandle.SYSTEM.getIdentifier();
         assertEquals(mGroupHelper.getOngoingGroupCount(
@@ -203,7 +203,7 @@
         mGroupHelper.onNotificationUpdated(notifications.get(0), true);
 
         verify(mCallback, times(AUTOGROUP_AT_COUNT + 2))
-                .updateAutogroupSummary(anyString(), eq(true));
+                .updateAutogroupSummary(anyInt(), anyString(), eq(true));
 
         int userId = UserHandle.SYSTEM.getIdentifier();
         assertEquals(mGroupHelper.getOngoingGroupCount(
@@ -236,7 +236,7 @@
         mGroupHelper.onNotificationUpdated(notifications.get(0), true);
 
         verify(mCallback, times(AUTOGROUP_AT_COUNT + 3))
-                .updateAutogroupSummary(anyString(), eq(true));
+                .updateAutogroupSummary(anyInt(), anyString(), eq(true));
 
         int userId = UserHandle.SYSTEM.getIdentifier();
         assertEquals(mGroupHelper.getOngoingGroupCount(
@@ -263,7 +263,7 @@
         mGroupHelper.onNotificationRemoved(notifications.get(0));
 
         verify(mCallback, times(AUTOGROUP_AT_COUNT + 2))
-                .updateAutogroupSummary(anyString(), eq(true));
+                .updateAutogroupSummary(anyInt(), anyString(), eq(true));
 
         int userId = UserHandle.SYSTEM.getIdentifier();
         assertEquals(mGroupHelper.getOngoingGroupCount(
@@ -291,7 +291,7 @@
         mGroupHelper.onNotificationUpdated(notifications.get(0), true);
 
         verify(mCallback, times(1))
-                .updateAutogroupSummary(anyString(), eq(true));
+                .updateAutogroupSummary(anyInt(), anyString(), eq(true));
 
         int userId = UserHandle.SYSTEM.getIdentifier();
         assertEquals(mGroupHelper.getOngoingGroupCount(
@@ -315,7 +315,7 @@
         }
 
         verify(mCallback, times(1))
-                .updateAutogroupSummary(anyString(), eq(true));
+                .updateAutogroupSummary(anyInt(), anyString(), eq(true));
 
         int userId = UserHandle.SYSTEM.getIdentifier();
         assertEquals(mGroupHelper.getOngoingGroupCount(
@@ -339,7 +339,7 @@
         }
 
         verify(mCallback, times(0))
-                .updateAutogroupSummary(anyString(), eq(true));
+                .updateAutogroupSummary(anyInt(), anyString(), eq(true));
 
         int userId = UserHandle.SYSTEM.getIdentifier();
         assertEquals(mGroupHelper.getOngoingGroupCount(userId, pkg, AUTOGROUP_KEY), 0);
diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
index 9639aa7..dc378dc 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
@@ -76,6 +76,7 @@
 import android.content.pm.ActivityInfo.ScreenOrientation;
 import android.content.res.Configuration;
 import android.graphics.Rect;
+import android.os.UserHandle;
 import android.platform.test.annotations.Presubmit;
 import android.provider.DeviceConfig;
 import android.provider.DeviceConfig.Properties;
@@ -2181,6 +2182,29 @@
                 .computeAspectRatio(sizeCompatAppBounds), delta);
     }
 
+    @Test
+    public void testClearSizeCompat_resetOverrideConfig() {
+        final int origDensity = 480;
+        final int newDensity = 520;
+        final DisplayContent display = new TestDisplayContent.Builder(mAtm, 600, 800)
+                .setDensityDpi(origDensity)
+                .build();
+        setUpApp(display);
+        prepareUnresizable(mActivity, -1.f /* maxAspect */, SCREEN_ORIENTATION_PORTRAIT);
+
+        // Activity should enter size compat with old density after display density change.
+        display.setForcedDensity(newDensity, UserHandle.USER_CURRENT);
+
+        assertScaled();
+        assertEquals(origDensity, mActivity.getConfiguration().densityDpi);
+
+        // Activity should exit size compat with new density.
+        mActivity.clearSizeCompatMode();
+
+        assertFitted();
+        assertEquals(newDensity, mActivity.getConfiguration().densityDpi);
+    }
+
     private void assertHorizontalPositionForDifferentDisplayConfigsForLandscapeActivity(
             float letterboxHorizontalPositionMultiplier) {
         // Set up a display in landscape and ignoring orientation request.
diff --git a/telecomm/OWNERS b/telecomm/OWNERS
index 9969ee9..eb0c432 100644
--- a/telecomm/OWNERS
+++ b/telecomm/OWNERS
@@ -1,8 +1,6 @@
 set noparent
 
 breadley@google.com
-hallliu@google.com
 tgunn@google.com
 xiaotonj@google.com
-shuoq@google.com
 rgreenwalt@google.com
diff --git a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
index 6f286d9..23b5787 100644
--- a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
+++ b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
@@ -344,6 +344,11 @@
 
     void setTestDefaultCallRedirectionApp(String packageName);
 
+    /**
+     * @see TelecomServiceImpl#requestLogMark
+     */
+    void requestLogMark(in String message);
+
     void setTestPhoneAcctSuggestionComponent(String flattenedComponentName);
 
     void setTestDefaultCallScreeningApp(String packageName);
diff --git a/telephony/OWNERS b/telephony/OWNERS
index f248fd5..9681ee8 100644
--- a/telephony/OWNERS
+++ b/telephony/OWNERS
@@ -1,15 +1,10 @@
 set noparent
 
-amitmahajan@google.com
 breadley@google.com
 fionaxu@google.com
 jackyu@google.com
 rgreenwalt@google.com
 tgunn@google.com
-jminjie@google.com
-shuoq@google.com
-sarahchin@google.com
-xiaotonj@google.com
 huiwang@google.com
 jayachandranc@google.com
 chinmayd@google.com
diff --git a/telephony/java/android/service/euicc/OWNERS b/telephony/java/android/service/euicc/OWNERS
index 6aa399d..fbeb6da 100644
--- a/telephony/java/android/service/euicc/OWNERS
+++ b/telephony/java/android/service/euicc/OWNERS
@@ -1,5 +1,5 @@
-# Bug component: 20868
+set noparent
 
+fionaxu@google.com
 rgreenwalt@google.com
-tgunn@google.com
-amitmahajan@google.com
+amruthr@google.com
diff --git a/telephony/java/android/service/sms/OWNERS b/telephony/java/android/service/sms/OWNERS
deleted file mode 100644
index 6aa399d..0000000
--- a/telephony/java/android/service/sms/OWNERS
+++ /dev/null
@@ -1,5 +0,0 @@
-# Bug component: 20868
-
-rgreenwalt@google.com
-tgunn@google.com
-amitmahajan@google.com
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index b85426b..83c78cd 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -1900,6 +1900,13 @@
             "show_4g_for_lte_data_icon_bool";
 
     /**
+     * Boolean indicating if default data account should show 4G LTE or 4G icon.
+     * @hide
+     */
+    public static final String KEY_SHOW_4GLTE_FOR_LTE_DATA_ICON_BOOL =
+            "show_4glte_for_lte_data_icon_bool";
+
+    /**
      * Boolean indicating if default data account should show 4G icon when in 3G.
      */
     public static final String KEY_SHOW_4G_FOR_3G_DATA_ICON_BOOL =
@@ -6239,6 +6246,7 @@
         sDefaults.putBoolean(KEY_SPN_DISPLAY_RULE_USE_ROAMING_FROM_SERVICE_STATE_BOOL, false);
         sDefaults.putBoolean(KEY_ALWAYS_SHOW_DATA_RAT_ICON_BOOL, false);
         sDefaults.putBoolean(KEY_SHOW_4G_FOR_LTE_DATA_ICON_BOOL, false);
+        sDefaults.putBoolean(KEY_SHOW_4GLTE_FOR_LTE_DATA_ICON_BOOL, false);
         sDefaults.putBoolean(KEY_SHOW_4G_FOR_3G_DATA_ICON_BOOL, false);
         sDefaults.putString(KEY_OPERATOR_NAME_FILTER_PATTERN_STRING, "");
         sDefaults.putString(KEY_SHOW_CARRIER_DATA_ICON_PATTERN_STRING, "");
diff --git a/telephony/java/android/telephony/OWNERS b/telephony/java/android/telephony/OWNERS
deleted file mode 100644
index 6aa399d..0000000
--- a/telephony/java/android/telephony/OWNERS
+++ /dev/null
@@ -1,5 +0,0 @@
-# Bug component: 20868
-
-rgreenwalt@google.com
-tgunn@google.com
-amitmahajan@google.com
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index a5adf52..b482515 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -11487,7 +11487,25 @@
         if (SubscriptionManager.isValidPhoneId(phoneId)) {
             List<String> newList = updateTelephonyProperty(
                     TelephonyProperties.operator_alpha(), phoneId, name);
-            TelephonyProperties.operator_alpha(newList);
+            try {
+                TelephonyProperties.operator_alpha(newList);
+            } catch (IllegalArgumentException e) { //property value is longer than the byte limit
+                Log.e(TAG, "setNetworkOperatorNameForPhone: ", e);
+
+                int numberOfEntries = newList.size();
+                int maxOperatorLength = //save 1 byte for joiner " , "
+                        (SystemProperties.PROP_VALUE_MAX - numberOfEntries) / numberOfEntries;
+
+                //examine and truncate every operator and retry
+                for (int i = 0; i < newList.size(); i++) {
+                    if (newList.get(i) != null) {
+                        newList.set(i, TextUtils
+                                .truncateStringForUtf8Storage(newList.get(i), maxOperatorLength));
+                    }
+                }
+                TelephonyProperties.operator_alpha(newList);
+                Log.e(TAG, "successfully truncated operator_alpha: " + newList);
+            }
         }
     }
 
diff --git a/telephony/java/android/telephony/cdma/OWNERS b/telephony/java/android/telephony/cdma/OWNERS
deleted file mode 100644
index 6aa399d..0000000
--- a/telephony/java/android/telephony/cdma/OWNERS
+++ /dev/null
@@ -1,5 +0,0 @@
-# Bug component: 20868
-
-rgreenwalt@google.com
-tgunn@google.com
-amitmahajan@google.com
diff --git a/telephony/java/android/telephony/data/ApnSetting.java b/telephony/java/android/telephony/data/ApnSetting.java
index 281b018..b0ddf2c 100644
--- a/telephony/java/android/telephony/data/ApnSetting.java
+++ b/telephony/java/android/telephony/data/ApnSetting.java
@@ -369,6 +369,10 @@
     public @interface AuthType {}
 
     // Possible values for protocol which is defined in TS 27.007 section 10.1.1.
+    /** Unknown protocol.
+     * @hide
+     */
+    public static final int PROTOCOL_UNKNOWN = -1;
     /** Internet protocol. */
     public static final int PROTOCOL_IP = 0;
     /** Internet protocol, version 6. */
diff --git a/telephony/java/android/telephony/data/DataServiceCallback.java b/telephony/java/android/telephony/data/DataServiceCallback.java
index ec73471..77d4837 100644
--- a/telephony/java/android/telephony/data/DataServiceCallback.java
+++ b/telephony/java/android/telephony/data/DataServiceCallback.java
@@ -50,12 +50,13 @@
      */
     @Retention(RetentionPolicy.SOURCE)
     @IntDef({RESULT_SUCCESS, RESULT_ERROR_UNSUPPORTED, RESULT_ERROR_INVALID_ARG, RESULT_ERROR_BUSY,
-            RESULT_ERROR_ILLEGAL_STATE})
+            RESULT_ERROR_ILLEGAL_STATE, RESULT_ERROR_TEMPORARILY_UNAVAILABLE,
+            RESULT_ERROR_INVALID_RESPONSE})
     public @interface ResultCode {}
 
     /** Request is completed successfully */
     public static final int RESULT_SUCCESS              = 0;
-    /** Request is not support */
+    /** Request is not supported */
     public static final int RESULT_ERROR_UNSUPPORTED    = 1;
     /** Request contains invalid arguments */
     public static final int RESULT_ERROR_INVALID_ARG    = 2;
@@ -68,6 +69,11 @@
      * @hide
      */
     public static final int RESULT_ERROR_TEMPORARILY_UNAVAILABLE = 5;
+    /**
+     * Request failed to complete due to an invalid response.
+     * @hide
+     */
+    public static final int RESULT_ERROR_INVALID_RESPONSE = 6;
 
     private final IDataServiceCallback mCallback;
 
@@ -255,6 +261,8 @@
                 return "RESULT_ERROR_ILLEGAL_STATE";
             case RESULT_ERROR_TEMPORARILY_UNAVAILABLE:
                 return "RESULT_ERROR_TEMPORARILY_UNAVAILABLE";
+            case RESULT_ERROR_INVALID_RESPONSE:
+                return "RESULT_ERROR_INVALID_RESPONSE";
             default:
                 return "Unknown(" + resultCode + ")";
         }
diff --git a/telephony/java/android/telephony/data/OWNERS b/telephony/java/android/telephony/data/OWNERS
index 932b35c..9dce366 100644
--- a/telephony/java/android/telephony/data/OWNERS
+++ b/telephony/java/android/telephony/data/OWNERS
@@ -1,5 +1,6 @@
-# Bug component: 20868
+set noparent
 
-rgreenwalt@google.com
-tgunn@google.com
 jackyu@google.com
+amruthr@google.com
+rgreenwalt@google.com
+
diff --git a/telephony/java/android/telephony/emergency/OWNERS b/telephony/java/android/telephony/emergency/OWNERS
index fa07dce..1d8de5d 100644
--- a/telephony/java/android/telephony/emergency/OWNERS
+++ b/telephony/java/android/telephony/emergency/OWNERS
@@ -1,5 +1,3 @@
-# Bug component: 20868
+set noparent
 
-rgreenwalt@google.com
-tgunn@google.com
-shuoq@google.com
+file:platform/frameworks/base:/telecomm/OWNERS
diff --git a/telephony/java/android/telephony/euicc/OWNERS b/telephony/java/android/telephony/euicc/OWNERS
index 9e51a4b..781550c 100644
--- a/telephony/java/android/telephony/euicc/OWNERS
+++ b/telephony/java/android/telephony/euicc/OWNERS
@@ -1,6 +1,4 @@
-# Bug component: 20868
+set noparent
 
-rgreenwalt@google.com
-tgunn@google.com
-refuhoo@google.com
-amitmahajan@google.com
+file:platform/frameworks/base:/telephony/java/android/service/euicc/OWNERS
+
diff --git a/telephony/java/android/telephony/gsm/OWNERS b/telephony/java/android/telephony/gsm/OWNERS
deleted file mode 100644
index 6aa399d..0000000
--- a/telephony/java/android/telephony/gsm/OWNERS
+++ /dev/null
@@ -1,5 +0,0 @@
-# Bug component: 20868
-
-rgreenwalt@google.com
-tgunn@google.com
-amitmahajan@google.com
diff --git a/telephony/java/android/telephony/ims/OWNERS b/telephony/java/android/telephony/ims/OWNERS
index 0854c5d..3c72680 100644
--- a/telephony/java/android/telephony/ims/OWNERS
+++ b/telephony/java/android/telephony/ims/OWNERS
@@ -1,5 +1,6 @@
-# Bug component: 20868
+set noparent
 
 rgreenwalt@google.com
 tgunn@google.com
 breadley@google.com
+amruthr@google.com
diff --git a/telephony/java/android/telephony/ims/aidl/OWNERS b/telephony/java/android/telephony/ims/aidl/OWNERS
deleted file mode 100644
index 0854c5d..0000000
--- a/telephony/java/android/telephony/ims/aidl/OWNERS
+++ /dev/null
@@ -1,5 +0,0 @@
-# Bug component: 20868
-
-rgreenwalt@google.com
-tgunn@google.com
-breadley@google.com
diff --git a/telephony/java/android/telephony/ims/compat/OWNERS b/telephony/java/android/telephony/ims/compat/OWNERS
deleted file mode 100644
index 0854c5d..0000000
--- a/telephony/java/android/telephony/ims/compat/OWNERS
+++ /dev/null
@@ -1,5 +0,0 @@
-# Bug component: 20868
-
-rgreenwalt@google.com
-tgunn@google.com
-breadley@google.com
diff --git a/telephony/java/android/telephony/ims/compat/feature/OWNERS b/telephony/java/android/telephony/ims/compat/feature/OWNERS
deleted file mode 100644
index 0854c5d..0000000
--- a/telephony/java/android/telephony/ims/compat/feature/OWNERS
+++ /dev/null
@@ -1,5 +0,0 @@
-# Bug component: 20868
-
-rgreenwalt@google.com
-tgunn@google.com
-breadley@google.com
diff --git a/telephony/java/android/telephony/ims/compat/stub/OWNERS b/telephony/java/android/telephony/ims/compat/stub/OWNERS
deleted file mode 100644
index 0854c5d..0000000
--- a/telephony/java/android/telephony/ims/compat/stub/OWNERS
+++ /dev/null
@@ -1,5 +0,0 @@
-# Bug component: 20868
-
-rgreenwalt@google.com
-tgunn@google.com
-breadley@google.com
diff --git a/telephony/java/android/telephony/ims/feature/OWNERS b/telephony/java/android/telephony/ims/feature/OWNERS
deleted file mode 100644
index 0854c5d..0000000
--- a/telephony/java/android/telephony/ims/feature/OWNERS
+++ /dev/null
@@ -1,5 +0,0 @@
-# Bug component: 20868
-
-rgreenwalt@google.com
-tgunn@google.com
-breadley@google.com
diff --git a/telephony/java/android/telephony/ims/stub/OWNERS b/telephony/java/android/telephony/ims/stub/OWNERS
deleted file mode 100644
index 0854c5d..0000000
--- a/telephony/java/android/telephony/ims/stub/OWNERS
+++ /dev/null
@@ -1,5 +0,0 @@
-# Bug component: 20868
-
-rgreenwalt@google.com
-tgunn@google.com
-breadley@google.com
diff --git a/telephony/java/android/telephony/mbms/OWNERS b/telephony/java/android/telephony/mbms/OWNERS
index 718e0a2..1d8de5d 100644
--- a/telephony/java/android/telephony/mbms/OWNERS
+++ b/telephony/java/android/telephony/mbms/OWNERS
@@ -1,5 +1,3 @@
-# Bug component: 20868
+set noparent
 
-rgreenwalt@google.com
-tgunn@google.com
-hallliu@google.com
+file:platform/frameworks/base:/telecomm/OWNERS
diff --git a/telephony/java/android/telephony/mbms/vendor/OWNERS b/telephony/java/android/telephony/mbms/vendor/OWNERS
deleted file mode 100644
index 718e0a2..0000000
--- a/telephony/java/android/telephony/mbms/vendor/OWNERS
+++ /dev/null
@@ -1,5 +0,0 @@
-# Bug component: 20868
-
-rgreenwalt@google.com
-tgunn@google.com
-hallliu@google.com
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 883e2ad..7799113 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -2556,4 +2556,7 @@
      * for the slot, or {@code null} if none is resolved
      */
     String getCarrierServicePackageNameForLogicalSlot(int logicalSlotIndex);
+
+    /** Check if telephony new data stack is enabled. */
+    boolean isUsingNewDataStack();
 }
diff --git a/test-legacy/Android.mk b/test-legacy/Android.mk
index 284008c..da9dc25 100644
--- a/test-legacy/Android.mk
+++ b/test-legacy/Android.mk
@@ -40,6 +40,10 @@
 
 include $(BUILD_STATIC_JAVA_LIBRARY)
 
+$(call declare-license-metadata,$(full_classes_jar),\
+    SPDX-license-identifier-Apache-2.0 SPDX-license-identifier-MIT SPDX-license-identifier-Unicode-DFS,\
+    notice,$(LOCAL_PATH)/../NOTICE,Android,frameworks/base)
+
 # Archive a copy of the classes.jar in SDK build.
 $(call dist-for-goals,sdk,$(full_classes_jar):android.test.legacy.jar)
 
diff --git a/tests/FlickerTests/OWNERS b/tests/FlickerTests/OWNERS
index c1221e3..d40ff56 100644
--- a/tests/FlickerTests/OWNERS
+++ b/tests/FlickerTests/OWNERS
@@ -1,4 +1,4 @@
-# Bug component: 909476
+# Bug component: 1157642
 include /services/core/java/com/android/server/wm/OWNERS
 natanieljr@google.com
 pablogamito@google.com
diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java
index 4cfa93b..841b81c 100644
--- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java
+++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java
@@ -252,6 +252,9 @@
                         && TEST_TCP_BUFFER_SIZES_2.equals(lp.getTcpBufferSizes())));
         verify(mNetworkAgent)
                 .setUnderlyingNetworks(eq(singletonList(TEST_UNDERLYING_NETWORK_RECORD_2.network)));
+
+        // Verify revalidation is triggered on VCN network
+        verify(mConnMgr).reportNetworkConnectivity(eq(mNetworkAgent.getNetwork()), eq(false));
     }
 
     private void triggerChildOpened() {
@@ -425,6 +428,9 @@
         triggerValidation(NetworkAgent.VALIDATION_STATUS_NOT_VALID);
         mTestLooper.dispatchAll();
 
+        verify(mConnMgr)
+                .reportNetworkConnectivity(eq(TEST_UNDERLYING_NETWORK_RECORD_1.network), eq(false));
+
         final ArgumentCaptor<Runnable> runnableCaptor = ArgumentCaptor.forClass(Runnable.class);
         verify(mDeps, times(2))
                 .newWakeupMessage(
diff --git a/tools/aapt2/Android.bp b/tools/aapt2/Android.bp
index 740b44e..50cd455 100644
--- a/tools/aapt2/Android.bp
+++ b/tools/aapt2/Android.bp
@@ -165,6 +165,7 @@
     ],
     proto: {
         export_proto_headers: true,
+        type: "full",
     },
     defaults: ["aapt2_defaults"],
 }
diff --git a/tools/aapt2/Android.mk b/tools/aapt2/Android.mk
index b165c6b..7b94e71 100644
--- a/tools/aapt2/Android.mk
+++ b/tools/aapt2/Android.mk
@@ -15,6 +15,8 @@
 $(aapt2_results): $(HOST_OUT_NATIVE_TESTS)/aapt2_tests/aapt2_tests
 	-$(HOST_OUT_NATIVE_TESTS)/aapt2_tests/aapt2_tests --gtest_output=xml:$@ > /dev/null 2>&1
 
+$(call declare-0p-target,$(aapt2_results))
+
 aapt2_results :=
 
 include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tools/aapt2/util/Files.cpp b/tools/aapt2/util/Files.cpp
index be09545..383be56 100644
--- a/tools/aapt2/util/Files.cpp
+++ b/tools/aapt2/util/Files.cpp
@@ -349,7 +349,7 @@
   const std::string root_dir = path.to_string();
   std::unique_ptr<DIR, decltype(closedir)*> d(opendir(root_dir.data()), closedir);
   if (!d) {
-    diag->Error(DiagMessage() << SystemErrorCodeToString(errno));
+    diag->Error(DiagMessage() << SystemErrorCodeToString(errno) << ": " << root_dir);
     return {};
   }
 
diff --git a/tools/apilint/deprecated_at_birth.py b/tools/apilint/deprecated_at_birth.py
old mode 100644
new mode 100755
index 297d9c3b..da9f19f
--- a/tools/apilint/deprecated_at_birth.py
+++ b/tools/apilint/deprecated_at_birth.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 
 # Copyright (C) 2021 The Android Open Source Project
 #
@@ -208,17 +208,17 @@
 
 def _parse_stream_path(path):
     api = {}
-    print "Parsing", path
+    print("Parsing %s" % path)
     for f in os.listdir(path):
         f = os.path.join(path, f)
         if not os.path.isfile(f): continue
         if not f.endswith(".txt"): continue
         if f.endswith("removed.txt"): continue
-        print "\t", f
+        print("\t%s" % f)
         with open(f) as s:
             api = _parse_stream(s, api)
-    print "Parsed", len(api), "APIs"
-    print
+    print("Parsed %d APIs" % len(api))
+    print()
     return api
 
 
@@ -306,8 +306,8 @@
             if "@Deprecated " in i.raw:
                 error(clazz, i, None, "Found API deprecation at birth " + i.ident)
 
-    print "%s Deprecated at birth %s\n" % ((format(fg=WHITE, bg=BLUE, bold=True),
-                                            format(reset=True)))
+    print("%s Deprecated at birth %s\n" % ((format(fg=WHITE, bg=BLUE, bold=True),
+                                            format(reset=True))))
     for f in sorted(failures):
-        print failures[f]
-        print
+        print(failures[f])
+        print()