Merge "[RFC media]: refactoring several functions to C++ style"
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index 6b6bc97..27dadda 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -107,6 +107,7 @@
 static const char DISPLAYS_PROP_NAME[] = "persist.service.bootanim.displays";
 static const char CLOCK_ENABLED_PROP_NAME[] = "persist.sys.bootanim.clock.enabled";
 static const int ANIM_ENTRY_NAME_MAX = ANIM_PATH_MAX + 1;
+static const int MAX_CHECK_EXIT_INTERVAL_US = 50000;
 static constexpr size_t TEXT_POS_LEN_MAX = 16;
 static const int DYNAMIC_COLOR_COUNT = 4;
 static const char U_TEXTURE[] = "uTexture";
@@ -1680,7 +1681,17 @@
                 checkExit();
             }
 
-            usleep(part.pause * ns2us(frameDuration));
+            int pauseDuration = part.pause * ns2us(frameDuration);
+            while(pauseDuration > 0 && !exitPending()){
+                if (pauseDuration > MAX_CHECK_EXIT_INTERVAL_US) {
+                    usleep(MAX_CHECK_EXIT_INTERVAL_US);
+                    pauseDuration -= MAX_CHECK_EXIT_INTERVAL_US;
+                } else {
+                    usleep(pauseDuration);
+                    break;
+                }
+                checkExit();
+            }
 
             if (exitPending() && !part.count && mCurrentInset >= mTargetInset &&
                 !part.hasFadingPhase()) {
diff --git a/core/java/android/permission/OWNERS b/core/java/android/permission/OWNERS
index d34b45b..4603e43f 100644
--- a/core/java/android/permission/OWNERS
+++ b/core/java/android/permission/OWNERS
@@ -1,18 +1,19 @@
 # Bug component: 137825
 
-evanseverson@google.com
-evanxinchen@google.com
 ashfall@google.com
-guojing@google.com
+augale@google.com
+evanseverson@google.com
+fayey@google.com
 jaysullivan@google.com
+joecastro@google.com
 kvakil@google.com
 mrulhania@google.com
 narayan@google.com
 ntmyren@google.com
 olekarg@google.com
 pyuli@google.com
-raphk@google.com
 rmacgregor@google.com
 sergeynv@google.com
 theianchen@google.com
+yutingfang@google.com
 zhanghai@google.com
diff --git a/core/proto/android/server/activitymanagerservice.proto b/core/proto/android/server/activitymanagerservice.proto
index 7205dd8..c596c54 100644
--- a/core/proto/android/server/activitymanagerservice.proto
+++ b/core/proto/android/server/activitymanagerservice.proto
@@ -1008,6 +1008,7 @@
 
             optional int32 uid = 1;
             repeated .android.app.ApplicationExitInfoProto app_exit_info = 2;
+            repeated .android.app.ApplicationExitInfoProto app_recoverable_crash = 3;
         }
         repeated User users = 2;
     }
diff --git a/identity/java/android/security/identity/CredstoreIdentityCredentialStore.java b/identity/java/android/security/identity/CredstoreIdentityCredentialStore.java
index d785c3c..f26b50e 100644
--- a/identity/java/android/security/identity/CredstoreIdentityCredentialStore.java
+++ b/identity/java/android/security/identity/CredstoreIdentityCredentialStore.java
@@ -21,10 +21,7 @@
 import android.content.Context;
 import android.content.pm.FeatureInfo;
 import android.content.pm.PackageManager;
-import android.os.RemoteException;
 import android.os.ServiceManager;
-import android.security.GenerateRkpKey;
-import android.security.keymaster.KeymasterDefs;
 
 class CredstoreIdentityCredentialStore extends IdentityCredentialStore {
 
@@ -125,18 +122,7 @@
             @NonNull String docType) throws AlreadyPersonalizedException,
             DocTypeNotSupportedException {
         try {
-            IWritableCredential wc;
-            wc = mStore.createCredential(credentialName, docType);
-            try {
-                GenerateRkpKey keyGen = new GenerateRkpKey(mContext);
-                // We don't know what the security level is for the backing keymint, so go ahead and
-                // poke the provisioner for both TEE and SB.
-                keyGen.notifyKeyGenerated(KeymasterDefs.KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT);
-                keyGen.notifyKeyGenerated(KeymasterDefs.KM_SECURITY_LEVEL_STRONGBOX);
-            } catch (RemoteException e) {
-                // Not really an error state. Does not apply at all if RKP is unsupported or
-                // disabled on a given device.
-            }
+            IWritableCredential wc = mStore.createCredential(credentialName, docType);
             return new CredstoreWritableIdentityCredential(mContext, credentialName, docType, wc);
         } catch (android.os.RemoteException e) {
             throw new RuntimeException("Unexpected RemoteException ", e);
diff --git a/keystore/java/android/security/GenerateRkpKey.java b/keystore/java/android/security/GenerateRkpKey.java
deleted file mode 100644
index 6981332..0000000
--- a/keystore/java/android/security/GenerateRkpKey.java
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * Copyright (C) 2021 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.security;
-
-import android.annotation.CheckResult;
-import android.annotation.IntDef;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.Log;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.Executor;
-import java.util.concurrent.Executors;
-import java.util.concurrent.TimeUnit;
-
-/**
- * GenerateKey is a helper class to handle interactions between Keystore and the RemoteProvisioner
- * app. There are two cases where Keystore should use this class.
- *
- * (1) : An app generates a new attested key pair, so Keystore calls notifyKeyGenerated to let the
- *       RemoteProvisioner app check if the state of the attestation key pool is getting low enough
- *       to warrant provisioning more attestation certificates early.
- *
- * (2) : An app attempts to generate a new key pair, but the keystore service discovers it is out of
- *       attestation key pairs and cannot provide one for the given application. Keystore can then
- *       make a blocking call on notifyEmpty to allow the RemoteProvisioner app to get another
- *       attestation certificate chain provisioned.
- *
- * In most cases, the proper usage of (1) should preclude the need for (2).
- *
- * @hide
- */
-public class GenerateRkpKey {
-    private static final String TAG = "GenerateRkpKey";
-
-    private static final int NOTIFY_EMPTY = 0;
-    private static final int NOTIFY_KEY_GENERATED = 1;
-    private static final int TIMEOUT_MS = 1000;
-
-    private IGenerateRkpKeyService mBinder;
-    private Context mContext;
-    private CountDownLatch mCountDownLatch;
-
-    /** @hide */
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef(flag = true, value = {
-            IGenerateRkpKeyService.Status.OK,
-            IGenerateRkpKeyService.Status.NO_NETWORK_CONNECTIVITY,
-            IGenerateRkpKeyService.Status.NETWORK_COMMUNICATION_ERROR,
-            IGenerateRkpKeyService.Status.DEVICE_NOT_REGISTERED,
-            IGenerateRkpKeyService.Status.HTTP_CLIENT_ERROR,
-            IGenerateRkpKeyService.Status.HTTP_SERVER_ERROR,
-            IGenerateRkpKeyService.Status.HTTP_UNKNOWN_ERROR,
-            IGenerateRkpKeyService.Status.INTERNAL_ERROR,
-    })
-    public @interface Status {
-    }
-
-    private ServiceConnection mConnection = new ServiceConnection() {
-        @Override
-        public void onServiceConnected(ComponentName className, IBinder service) {
-            mBinder = IGenerateRkpKeyService.Stub.asInterface(service);
-            mCountDownLatch.countDown();
-        }
-
-        @Override public void onBindingDied(ComponentName className) {
-            mCountDownLatch.countDown();
-        }
-
-        @Override
-        public void onServiceDisconnected(ComponentName className) {
-            mBinder = null;
-        }
-    };
-
-    /**
-     * Constructor which takes a Context object.
-     */
-    public GenerateRkpKey(Context context) {
-        mContext = context;
-    }
-
-    @Status
-    private int bindAndSendCommand(int command, int securityLevel) throws RemoteException {
-        Intent intent = new Intent(IGenerateRkpKeyService.class.getName());
-        ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
-        int returnCode = IGenerateRkpKeyService.Status.OK;
-        if (comp == null) {
-            // On a system that does not use RKP, the RemoteProvisioner app won't be installed.
-            return returnCode;
-        }
-        intent.setComponent(comp);
-        mCountDownLatch = new CountDownLatch(1);
-        Executor executor = Executors.newCachedThreadPool();
-        if (!mContext.bindService(intent, Context.BIND_AUTO_CREATE, executor, mConnection)) {
-            throw new RemoteException("Failed to bind to GenerateRkpKeyService");
-        }
-        try {
-            mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS);
-        } catch (InterruptedException e) {
-            Log.e(TAG, "Interrupted: ", e);
-        }
-        if (mBinder != null) {
-            switch (command) {
-                case NOTIFY_EMPTY:
-                    returnCode = mBinder.generateKey(securityLevel);
-                    break;
-                case NOTIFY_KEY_GENERATED:
-                    mBinder.notifyKeyGenerated(securityLevel);
-                    break;
-                default:
-                    Log.e(TAG, "Invalid case for command");
-            }
-        } else {
-            Log.e(TAG, "Binder object is null; failed to bind to GenerateRkpKeyService.");
-            returnCode = IGenerateRkpKeyService.Status.INTERNAL_ERROR;
-        }
-        mContext.unbindService(mConnection);
-        return returnCode;
-    }
-
-    /**
-     * Fulfills the use case of (2) described in the class documentation. Blocks until the
-     * RemoteProvisioner application can get new attestation keys signed by the server.
-     * @return the status of the key generation
-     */
-    @CheckResult
-    @Status
-    public int notifyEmpty(int securityLevel) throws RemoteException {
-        return bindAndSendCommand(NOTIFY_EMPTY, securityLevel);
-    }
-
-    /**
-     * Fulfills the use case of (1) described in the class documentation. Non blocking call.
-     */
-    public void notifyKeyGenerated(int securityLevel) throws RemoteException {
-        bindAndSendCommand(NOTIFY_KEY_GENERATED, securityLevel);
-    }
-}
diff --git a/keystore/java/android/security/GenerateRkpKeyException.java b/keystore/java/android/security/GenerateRkpKeyException.java
deleted file mode 100644
index a2d65e4..0000000
--- a/keystore/java/android/security/GenerateRkpKeyException.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2021 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.security;
-
-/**
- * Thrown on problems in attempting to attest to a key using a remotely provisioned key.
- *
- * @hide
- */
-public class GenerateRkpKeyException extends Exception {
-
-    /**
-     * Constructs a new {@code GenerateRkpKeyException}.
-     */
-    public GenerateRkpKeyException() {
-    }
-}
diff --git a/keystore/java/android/security/IGenerateRkpKeyService.aidl b/keystore/java/android/security/IGenerateRkpKeyService.aidl
deleted file mode 100644
index eeaeb27..0000000
--- a/keystore/java/android/security/IGenerateRkpKeyService.aidl
+++ /dev/null
@@ -1,60 +0,0 @@
-/**
- * Copyright (C) 2021 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.security;
-
-/**
- * Interface to allow the framework to notify the RemoteProvisioner app when keys are empty. This
- * will be used if Keystore replies with an error code NO_KEYS_AVAILABLE in response to an
- * attestation request. The framework can then synchronously call generateKey() to get more
- * attestation keys generated and signed. Upon return, the caller can be certain an attestation key
- * is available.
- *
- * @hide
- */
-interface IGenerateRkpKeyService {
-    @JavaDerive(toString=true)
-    @Backing(type="int")
-    enum Status {
-        /** No error(s) occurred */
-        OK = 0,
-        /** Unable to provision keys due to a lack of internet connectivity. */
-        NO_NETWORK_CONNECTIVITY = 1,
-        /** An error occurred while communicating with the RKP server. */
-        NETWORK_COMMUNICATION_ERROR = 2,
-        /** The given device was not registered with the RKP backend. */
-        DEVICE_NOT_REGISTERED = 4,
-        /** The RKP server returned an HTTP client error, indicating a misbehaving client. */
-        HTTP_CLIENT_ERROR = 5,
-        /** The RKP server returned an HTTP server error, indicating something went wrong on the server. */
-        HTTP_SERVER_ERROR = 6,
-        /** The RKP server returned an HTTP status that is unknown. This should never happen. */
-        HTTP_UNKNOWN_ERROR = 7,
-        /** An unexpected internal error occurred. This should never happen. */
-        INTERNAL_ERROR = 8,
-    }
-
-    /**
-     * Ping the provisioner service to let it know an app generated a key. This may or may not have
-     * consumed a remotely provisioned attestation key, so the RemoteProvisioner app should check.
-     */
-    oneway void notifyKeyGenerated(in int securityLevel);
-
-    /**
-     * Ping the provisioner service to indicate there are no remaining attestation keys left.
-     */
-    Status generateKey(in int securityLevel);
-}
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java
index c3b0f9b..474b7ea 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java
@@ -20,7 +20,6 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.app.ActivityThread;
 import android.content.Context;
 import android.hardware.security.keymint.EcCurve;
 import android.hardware.security.keymint.KeyParameter;
@@ -28,9 +27,6 @@
 import android.hardware.security.keymint.SecurityLevel;
 import android.hardware.security.keymint.Tag;
 import android.os.Build;
-import android.os.RemoteException;
-import android.security.GenerateRkpKey;
-import android.security.IGenerateRkpKeyService;
 import android.security.KeyPairGeneratorSpec;
 import android.security.KeyStore2;
 import android.security.KeyStoreException;
@@ -621,45 +617,6 @@
 
     @Override
     public KeyPair generateKeyPair() {
-        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 && result.keyPair != null) {
-                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}
-        // {@link android.security.KeyStoreException#RKP_FETCHING_PENDING_SOFTWARE_REBOOT}
-        public final int rkpStatus;
-        @Nullable
-        public final KeyPair keyPair;
-
-        private GenerateKeyPairHelperResult(int rkpStatus, KeyPair keyPair) {
-            this.rkpStatus = rkpStatus;
-            this.keyPair = keyPair;
-        }
-    }
-
-    private GenerateKeyPairHelperResult generateKeyPairHelper() {
         if (mKeyStore == null || mSpec == null) {
             throw new IllegalStateException("Not initialized");
         }
@@ -697,26 +654,12 @@
             AndroidKeyStorePublicKey publicKey =
                     AndroidKeyStoreProvider.makeAndroidKeyStorePublicKeyFromKeyEntryResponse(
                             descriptor, metadata, iSecurityLevel, mKeymasterAlgorithm);
-            GenerateRkpKey keyGen = new GenerateRkpKey(ActivityThread
-                    .currentApplication());
-            try {
-                if (mSpec.getAttestationChallenge() != null) {
-                    keyGen.notifyKeyGenerated(securityLevel);
-                }
-            } catch (RemoteException e) {
-                // This is not really an error state, and necessarily does not apply to non RKP
-                // systems or hybrid systems where RKP is not currently turned on.
-                Log.d(TAG, "Couldn't connect to the RemoteProvisioner backend.", e);
-            }
             success = true;
-            KeyPair kp = new KeyPair(publicKey, publicKey.getPrivateKey());
-            return new GenerateKeyPairHelperResult(0, kp);
+            return new KeyPair(publicKey, publicKey.getPrivateKey());
         } catch (KeyStoreException e) {
             switch (e.getErrorCode()) {
                 case KeymasterDefs.KM_ERROR_HARDWARE_TYPE_UNAVAILABLE:
                     throw new StrongBoxUnavailableException("Failed to generated key pair.", e);
-                case ResponseCode.OUT_OF_KEYS:
-                    return checkIfRetryableOrThrow(e, securityLevel);
                 default:
                     ProviderException p = new ProviderException("Failed to generate key pair.", e);
                     if ((mSpec.getPurposes() & KeyProperties.PURPOSE_WRAP_KEY) != 0) {
@@ -742,55 +685,6 @@
         }
     }
 
-    // In case keystore reports OUT_OF_KEYS, call this handler in an attempt to remotely provision
-    // some keys.
-    GenerateKeyPairHelperResult checkIfRetryableOrThrow(KeyStoreException e, int securityLevel) {
-        GenerateRkpKey keyGen = new GenerateRkpKey(ActivityThread
-                .currentApplication());
-        KeyStoreException ksException;
-        try {
-            final int keyGenStatus = keyGen.notifyEmpty(securityLevel);
-            // Default stance: temporary error. This is a hint to the caller to try again with
-            // exponential back-off.
-            int rkpStatus;
-            switch (keyGenStatus) {
-                case IGenerateRkpKeyService.Status.NO_NETWORK_CONNECTIVITY:
-                    rkpStatus = KeyStoreException.RKP_FETCHING_PENDING_CONNECTIVITY;
-                    break;
-                case IGenerateRkpKeyService.Status.DEVICE_NOT_REGISTERED:
-                    rkpStatus = KeyStoreException.RKP_SERVER_REFUSED_ISSUANCE;
-                    break;
-                case IGenerateRkpKeyService.Status.OK:
-                    // Explicitly return not-OK here so we retry in generateKeyPair. All other cases
-                    // should throw because a retry doesn't make sense if we didn't actually
-                    // provision fresh keys.
-                    return new GenerateKeyPairHelperResult(
-                            KeyStoreException.RKP_TEMPORARILY_UNAVAILABLE, null);
-                case IGenerateRkpKeyService.Status.NETWORK_COMMUNICATION_ERROR:
-                case IGenerateRkpKeyService.Status.HTTP_CLIENT_ERROR:
-                case IGenerateRkpKeyService.Status.HTTP_SERVER_ERROR:
-                case IGenerateRkpKeyService.Status.HTTP_UNKNOWN_ERROR:
-                case IGenerateRkpKeyService.Status.INTERNAL_ERROR:
-                default:
-                    // These errors really should never happen. The best we can do is assume they
-                    // are transient and hint to the caller to retry with back-off.
-                    rkpStatus = KeyStoreException.RKP_TEMPORARILY_UNAVAILABLE;
-                    break;
-            }
-            ksException = new KeyStoreException(
-                    ResponseCode.OUT_OF_KEYS,
-                    "Out of RKP keys due to IGenerateRkpKeyService status: " + keyGenStatus,
-                    rkpStatus);
-        } catch (RemoteException f) {
-            ksException = new KeyStoreException(
-                    ResponseCode.OUT_OF_KEYS,
-                    "Remote exception: " + f.getMessage(),
-                    KeyStoreException.RKP_TEMPORARILY_UNAVAILABLE);
-        }
-        ksException.initCause(e);
-        throw new ProviderException("Failed to provision new attestation keys.", ksException);
-    }
-
     private void addAttestationParameters(@NonNull List<KeyParameter> params)
             throws ProviderException, IllegalArgumentException, DeviceIdAttestationException {
         byte[] challenge = mSpec.getAttestationChallenge();
diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
index 8e350d5..63c36f8 100644
--- a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
@@ -53,6 +53,8 @@
 }
 
 MakeCurrentResult SkiaOpenGLPipeline::makeCurrent() {
+    bool wasSurfaceless = mEglManager.isCurrent(EGL_NO_SURFACE);
+
     // In case the surface was destroyed (e.g. a previous trimMemory call) we
     // need to recreate it here.
     if (!isSurfaceReady() && mNativeWindow) {
@@ -63,6 +65,37 @@
     if (!mEglManager.makeCurrent(mEglSurface, &error)) {
         return MakeCurrentResult::AlreadyCurrent;
     }
+
+    // Make sure read/draw buffer state of default framebuffer is GL_BACK. Vendor implementations
+    // disagree on the draw/read buffer state if the default framebuffer transitions from a surface
+    // to EGL_NO_SURFACE and vice-versa. There was a related discussion within Khronos on this topic.
+    // See https://cvs.khronos.org/bugzilla/show_bug.cgi?id=13534.
+    // The discussion was not resolved with a clear consensus
+    if (error == 0 && wasSurfaceless && mEglSurface != EGL_NO_SURFACE) {
+        GLint curReadFB = 0;
+        GLint curDrawFB = 0;
+        glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &curReadFB);
+        glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &curDrawFB);
+
+        GLint buffer = GL_NONE;
+        glBindFramebuffer(GL_FRAMEBUFFER, 0);
+        glGetIntegerv(GL_DRAW_BUFFER0, &buffer);
+        if (buffer == GL_NONE) {
+            const GLenum drawBuffer = GL_BACK;
+            glDrawBuffers(1, &drawBuffer);
+        }
+
+        glGetIntegerv(GL_READ_BUFFER, &buffer);
+        if (buffer == GL_NONE) {
+            glReadBuffer(GL_BACK);
+        }
+
+        glBindFramebuffer(GL_READ_FRAMEBUFFER, curReadFB);
+        glBindFramebuffer(GL_DRAW_FRAMEBUFFER, curDrawFB);
+
+        GL_CHECKPOINT(LOW);
+    }
+
     return error ? MakeCurrentResult::Failed : MakeCurrentResult::Succeeded;
 }
 
diff --git a/media/jni/android_media_MediaCodecLinearBlock.h b/media/jni/android_media_MediaCodecLinearBlock.h
index c753020..060abfd 100644
--- a/media/jni/android_media_MediaCodecLinearBlock.h
+++ b/media/jni/android_media_MediaCodecLinearBlock.h
@@ -44,12 +44,19 @@
 
     std::shared_ptr<C2Buffer> toC2Buffer(size_t offset, size_t size) const {
         if (mBuffer) {
+            // TODO: if returned C2Buffer is different from mBuffer, we should
+            // find a way to connect the life cycle between this C2Buffer and
+            // mBuffer.
             if (mBuffer->data().type() != C2BufferData::LINEAR) {
                 return nullptr;
             }
             C2ConstLinearBlock block = mBuffer->data().linearBlocks().front();
             if (offset == 0 && size == block.capacity()) {
-                return mBuffer;
+                // Let C2Buffer be new one to queue to MediaCodec. It will allow
+                // the related input slot to be released by onWorkDone from C2
+                // Component. Currently, the life cycle of mBuffer should be
+                // protected by different flows.
+                return std::make_shared<C2Buffer>(*mBuffer);
             }
 
             std::shared_ptr<C2Buffer> buffer =
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 99f1863..37db031 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -8496,7 +8496,9 @@
         // 'recoverable' is that the app doesn't crash). Normally, for nonrecoreable native crashes,
         // debuggerd will terminate the process, but there's a backup where ActivityManager will
         // also kill it. Avoid that.
-        if (!recoverable) {
+        if (recoverable) {
+            mAppErrors.sendRecoverableCrashToAppExitInfo(r, crashInfo);
+        } else {
             mAppErrors.crashApplication(r, crashInfo);
         }
     }
diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java
index 08c1de6..c475f00 100644
--- a/services/core/java/com/android/server/am/AppErrors.java
+++ b/services/core/java/com/android/server/am/AppErrors.java
@@ -553,6 +553,15 @@
         }
     }
 
+    void sendRecoverableCrashToAppExitInfo(
+            ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
+        if (r == null || crashInfo == null
+                || !"Native crash".equals(crashInfo.exceptionClassName)) return;
+        synchronized (mService) {
+            mService.mProcessList.noteAppRecoverableCrash(r);
+        }
+    }
+
     /**
      * Bring up the "unexpected error" dialog box for a crashing app.
      * Deal with edge cases (intercepts from instrumented applications,
diff --git a/services/core/java/com/android/server/am/AppExitInfoTracker.java b/services/core/java/com/android/server/am/AppExitInfoTracker.java
index 32d2071..df1f3c7 100644
--- a/services/core/java/com/android/server/am/AppExitInfoTracker.java
+++ b/services/core/java/com/android/server/am/AppExitInfoTracker.java
@@ -308,6 +308,16 @@
         mKillHandler.obtainMessage(KillHandler.MSG_APP_KILL, raw).sendToTarget();
     }
 
+    void scheduleNoteAppRecoverableCrash(final ProcessRecord app) {
+        if (!mAppExitInfoLoaded.get() || app == null || app.info == null) return;
+
+        ApplicationExitInfo raw = obtainRawRecord(app, System.currentTimeMillis());
+        raw.setReason(ApplicationExitInfo.REASON_CRASH_NATIVE);
+        raw.setSubReason(ApplicationExitInfo.SUBREASON_UNKNOWN);
+        raw.setDescription("recoverable_crash");
+        mKillHandler.obtainMessage(KillHandler.MSG_APP_RECOVERABLE_CRASH, raw).sendToTarget();
+    }
+
     void scheduleNoteAppKill(final int pid, final int uid, final @Reason int reason,
             final @SubReason int subReason, final String msg) {
         if (!mAppExitInfoLoaded.get()) {
@@ -421,8 +431,24 @@
         scheduleLogToStatsdLocked(info, true);
     }
 
+    /**
+     * Make note when ActivityManagerService gets a recoverable native crash, as the process isn't
+     * being killed but the crash should still be added to AppExitInfo. Also, because we're not
+     * crashing, don't log out to statsd.
+     */
+    @VisibleForTesting
+    @GuardedBy("mLock")
+    void handleNoteAppRecoverableCrashLocked(final ApplicationExitInfo raw) {
+        addExitInfoLocked(raw, /* recoverable */ true);
+    }
+
     @GuardedBy("mLock")
     private ApplicationExitInfo addExitInfoLocked(ApplicationExitInfo raw) {
+        return addExitInfoLocked(raw, /* recoverable */ false);
+    }
+
+    @GuardedBy("mLock")
+    private ApplicationExitInfo addExitInfoLocked(ApplicationExitInfo raw, boolean recoverable) {
         if (!mAppExitInfoLoaded.get()) {
             Slog.w(TAG, "Skipping saving the exit info due to ongoing loading from storage");
             return null;
@@ -438,7 +464,7 @@
             }
         }
         for (int i = 0; i < packages.length; i++) {
-            addExitInfoInnerLocked(packages[i], uid, info);
+            addExitInfoInnerLocked(packages[i], uid, info, recoverable);
         }
 
         schedulePersistProcessExitInfo(false);
@@ -845,7 +871,8 @@
     }
 
     @GuardedBy("mLock")
-    private void addExitInfoInnerLocked(String packageName, int uid, ApplicationExitInfo info) {
+    private void addExitInfoInnerLocked(String packageName, int uid, ApplicationExitInfo info,
+            boolean recoverable) {
         AppExitInfoContainer container = mData.get(packageName, uid);
         if (container == null) {
             container = new AppExitInfoContainer(mAppExitInfoHistoryListSize);
@@ -859,7 +886,11 @@
             }
             mData.put(packageName, uid, container);
         }
-        container.addExitInfoLocked(info);
+        if (recoverable) {
+            container.addRecoverableCrashLocked(info);
+        } else {
+            container.addExitInfoLocked(info);
+        }
     }
 
     @GuardedBy("mLock")
@@ -1284,38 +1315,40 @@
      * A container class of {@link android.app.ApplicationExitInfo}
      */
     final class AppExitInfoContainer {
-        private SparseArray<ApplicationExitInfo> mInfos; // index is pid
+        private SparseArray<ApplicationExitInfo> mInfos; // index is a pid
+        private SparseArray<ApplicationExitInfo> mRecoverableCrashes; // index is a pid
         private int mMaxCapacity;
         private int mUid; // Application uid, not isolated uid.
 
         AppExitInfoContainer(final int maxCapacity) {
             mInfos = new SparseArray<ApplicationExitInfo>();
+            mRecoverableCrashes = new SparseArray<ApplicationExitInfo>();
             mMaxCapacity = maxCapacity;
         }
 
         @GuardedBy("mLock")
-        void getExitInfoLocked(final int filterPid, final int maxNum,
-                ArrayList<ApplicationExitInfo> results) {
+        void getInfosLocked(SparseArray<ApplicationExitInfo> map, final int filterPid,
+                final int maxNum, ArrayList<ApplicationExitInfo> results) {
             if (filterPid > 0) {
-                ApplicationExitInfo r = mInfos.get(filterPid);
+                ApplicationExitInfo r = map.get(filterPid);
                 if (r != null) {
                     results.add(r);
                 }
             } else {
-                final int numRep = mInfos.size();
+                final int numRep = map.size();
                 if (maxNum <= 0 || numRep <= maxNum) {
                     // Return all records.
                     for (int i = 0; i < numRep; i++) {
-                        results.add(mInfos.valueAt(i));
+                        results.add(map.valueAt(i));
                     }
                     Collections.sort(results,
                             (a, b) -> Long.compare(b.getTimestamp(), a.getTimestamp()));
                 } else {
                     if (maxNum == 1) {
                         // Most of the caller might be only interested with the most recent one
-                        ApplicationExitInfo r = mInfos.valueAt(0);
+                        ApplicationExitInfo r = map.valueAt(0);
                         for (int i = 1; i < numRep; i++) {
-                            ApplicationExitInfo t = mInfos.valueAt(i);
+                            ApplicationExitInfo t = map.valueAt(i);
                             if (r.getTimestamp() < t.getTimestamp()) {
                                 r = t;
                             }
@@ -1326,7 +1359,7 @@
                         ArrayList<ApplicationExitInfo> list = mTmpInfoList2;
                         list.clear();
                         for (int i = 0; i < numRep; i++) {
-                            list.add(mInfos.valueAt(i));
+                            list.add(map.valueAt(i));
                         }
                         Collections.sort(list,
                                 (a, b) -> Long.compare(b.getTimestamp(), a.getTimestamp()));
@@ -1340,24 +1373,30 @@
         }
 
         @GuardedBy("mLock")
-        void addExitInfoLocked(ApplicationExitInfo info) {
+        void getExitInfoLocked(final int filterPid, final int maxNum,
+                ArrayList<ApplicationExitInfo> results) {
+            getInfosLocked(mInfos, filterPid, maxNum, results);
+        }
+
+        @GuardedBy("mLock")
+        void addInfoLocked(SparseArray<ApplicationExitInfo> map, ApplicationExitInfo info) {
             int size;
-            if ((size = mInfos.size()) >= mMaxCapacity) {
+            if ((size = map.size()) >= mMaxCapacity) {
                 int oldestIndex = -1;
                 long oldestTimeStamp = Long.MAX_VALUE;
                 for (int i = 0; i < size; i++) {
-                    ApplicationExitInfo r = mInfos.valueAt(i);
+                    ApplicationExitInfo r = map.valueAt(i);
                     if (r.getTimestamp() < oldestTimeStamp) {
                         oldestTimeStamp = r.getTimestamp();
                         oldestIndex = i;
                     }
                 }
                 if (oldestIndex >= 0) {
-                    final File traceFile = mInfos.valueAt(oldestIndex).getTraceFile();
+                    final File traceFile = map.valueAt(oldestIndex).getTraceFile();
                     if (traceFile != null) {
                         traceFile.delete();
                     }
-                    mInfos.removeAt(oldestIndex);
+                    map.removeAt(oldestIndex);
                 }
             }
             // Claim the state information if there is any
@@ -1367,7 +1406,17 @@
                     mActiveAppStateSummary, uid, pid));
             info.setTraceFile(findAndRemoveFromSparse2dArray(mActiveAppTraces, uid, pid));
             info.setAppTraceRetriever(mAppTraceRetriever);
-            mInfos.append(pid, info);
+            map.append(pid, info);
+        }
+
+        @GuardedBy("mLock")
+        void addExitInfoLocked(ApplicationExitInfo info) {
+            addInfoLocked(mInfos, info);
+        }
+
+        @GuardedBy("mLock")
+        void addRecoverableCrashLocked(ApplicationExitInfo info) {
+            addInfoLocked(mRecoverableCrashes, info);
         }
 
         @GuardedBy("mLock")
@@ -1382,9 +1431,9 @@
         }
 
         @GuardedBy("mLock")
-        void destroyLocked() {
-            for (int i = mInfos.size() - 1; i >= 0; i--) {
-                ApplicationExitInfo ai = mInfos.valueAt(i);
+        void destroyLocked(SparseArray<ApplicationExitInfo> map) {
+            for (int i = map.size() - 1; i >= 0; i--) {
+                ApplicationExitInfo ai = map.valueAt(i);
                 final File traceFile = ai.getTraceFile();
                 if (traceFile != null) {
                     traceFile.delete();
@@ -1395,24 +1444,37 @@
         }
 
         @GuardedBy("mLock")
+        void destroyLocked() {
+            destroyLocked(mInfos);
+            destroyLocked(mRecoverableCrashes);
+        }
+
+        @GuardedBy("mLock")
         void forEachRecordLocked(final BiFunction<Integer, ApplicationExitInfo, Integer> callback) {
-            if (callback != null) {
-                for (int i = mInfos.size() - 1; i >= 0; i--) {
-                    switch (callback.apply(mInfos.keyAt(i), mInfos.valueAt(i))) {
-                        case FOREACH_ACTION_REMOVE_ITEM:
-                            final File traceFile = mInfos.valueAt(i).getTraceFile();
-                            if (traceFile != null) {
-                                traceFile.delete();
-                            }
-                            mInfos.removeAt(i);
-                            break;
-                        case FOREACH_ACTION_STOP_ITERATION:
-                            i = 0;
-                            break;
-                        case FOREACH_ACTION_NONE:
-                        default:
-                            break;
-                    }
+            if (callback == null) return;
+            for (int i = mInfos.size() - 1; i >= 0; i--) {
+                switch (callback.apply(mInfos.keyAt(i), mInfos.valueAt(i))) {
+                    case FOREACH_ACTION_STOP_ITERATION: return;
+                    case FOREACH_ACTION_REMOVE_ITEM:
+                        final File traceFile = mInfos.valueAt(i).getTraceFile();
+                        if (traceFile != null) {
+                            traceFile.delete();
+                        }
+                        mInfos.removeAt(i);
+                        break;
+                }
+            }
+            for (int i = mRecoverableCrashes.size() - 1; i >= 0; i--) {
+                switch (callback.apply(
+                        mRecoverableCrashes.keyAt(i), mRecoverableCrashes.valueAt(i))) {
+                    case FOREACH_ACTION_STOP_ITERATION: return;
+                    case FOREACH_ACTION_REMOVE_ITEM:
+                        final File traceFile = mRecoverableCrashes.valueAt(i).getTraceFile();
+                        if (traceFile != null) {
+                            traceFile.delete();
+                        }
+                        mRecoverableCrashes.removeAt(i);
+                        break;
                 }
             }
         }
@@ -1423,6 +1485,9 @@
             for (int i = mInfos.size() - 1; i >= 0; i--) {
                 list.add(mInfos.valueAt(i));
             }
+            for (int i = mRecoverableCrashes.size() - 1; i >= 0; i--) {
+                list.add(mRecoverableCrashes.valueAt(i));
+            }
             Collections.sort(list, (a, b) -> Long.compare(b.getTimestamp(), a.getTimestamp()));
             int size = list.size();
             for (int i = 0; i < size; i++) {
@@ -1434,10 +1499,13 @@
         void writeToProto(ProtoOutputStream proto, long fieldId) {
             long token = proto.start(fieldId);
             proto.write(AppsExitInfoProto.Package.User.UID, mUid);
-            int size = mInfos.size();
-            for (int i = 0; i < size; i++) {
+            for (int i = 0; i < mInfos.size(); i++) {
                 mInfos.valueAt(i).writeToProto(proto, AppsExitInfoProto.Package.User.APP_EXIT_INFO);
             }
+            for (int i = 0; i < mRecoverableCrashes.size(); i++) {
+                mRecoverableCrashes.valueAt(i).writeToProto(
+                        proto, AppsExitInfoProto.Package.User.APP_RECOVERABLE_CRASH);
+            }
             proto.end(token);
         }
 
@@ -1448,14 +1516,23 @@
                     next != ProtoInputStream.NO_MORE_FIELDS;
                     next = proto.nextField()) {
                 switch (next) {
-                    case (int) AppsExitInfoProto.Package.User.UID:
+                    case (int) AppsExitInfoProto.Package.User.UID: {
                         mUid = proto.readInt(AppsExitInfoProto.Package.User.UID);
                         break;
-                    case (int) AppsExitInfoProto.Package.User.APP_EXIT_INFO:
+                    }
+                    case (int) AppsExitInfoProto.Package.User.APP_EXIT_INFO: {
                         ApplicationExitInfo info = new ApplicationExitInfo();
                         info.readFromProto(proto, AppsExitInfoProto.Package.User.APP_EXIT_INFO);
                         mInfos.put(info.getPid(), info);
                         break;
+                    }
+                    case (int) AppsExitInfoProto.Package.User.APP_RECOVERABLE_CRASH: {
+                        ApplicationExitInfo info = new ApplicationExitInfo();
+                        info.readFromProto(
+                                proto, AppsExitInfoProto.Package.User.APP_RECOVERABLE_CRASH);
+                        mRecoverableCrashes.put(info.getPid(), info);
+                        break;
+                    }
                 }
             }
             proto.end(token);
@@ -1472,6 +1549,11 @@
                     list.add(mInfos.valueAt(i));
                 }
             }
+            for (int i = mRecoverableCrashes.size() - 1; i >= 0; i--) {
+                if (filterPid == 0 || filterPid == mRecoverableCrashes.keyAt(i)) {
+                    list.add(mRecoverableCrashes.valueAt(i));
+                }
+            }
             return list;
         }
     }
@@ -1610,6 +1692,7 @@
         static final int MSG_PROC_DIED = 4103;
         static final int MSG_APP_KILL = 4104;
         static final int MSG_STATSD_LOG = 4105;
+        static final int MSG_APP_RECOVERABLE_CRASH = 4106;
 
         KillHandler(Looper looper) {
             super(looper, null, true);
@@ -1648,6 +1731,14 @@
                     }
                 }
                 break;
+                case MSG_APP_RECOVERABLE_CRASH: {
+                    ApplicationExitInfo raw = (ApplicationExitInfo) msg.obj;
+                    synchronized (mLock) {
+                        handleNoteAppRecoverableCrashLocked(raw);
+                    }
+                    recycleRawRecord(raw);
+                }
+                break;
                 default:
                     super.handleMessage(msg);
             }
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 256df98..6c7803b 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -5086,6 +5086,17 @@
     }
 
     /**
+     * Called by ActivityManagerService when a recoverable native crash occurs.
+     */
+    @GuardedBy("mService")
+    void noteAppRecoverableCrash(final ProcessRecord app) {
+        if (DEBUG_PROCESSES) {
+            Slog.i(TAG, "note: " + app + " has a recoverable native crash");
+        }
+        mAppExitInfoTracker.scheduleNoteAppRecoverableCrash(app);
+    }
+
+    /**
      * Called by ActivityManagerService when it decides to kill an application process.
      */
     @GuardedBy("mService")
diff --git a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
index 8886f0a..b8ff26e 100644
--- a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
+++ b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
@@ -98,7 +98,6 @@
         DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT,
         DeviceConfig.NAMESPACE_SURFACE_FLINGER_NATIVE_BOOT,
         DeviceConfig.NAMESPACE_SWCODEC_NATIVE,
-        DeviceConfig.NAMESPACE_TETHERING,
         DeviceConfig.NAMESPACE_VENDOR_SYSTEM_NATIVE,
         DeviceConfig.NAMESPACE_VENDOR_SYSTEM_NATIVE_BOOT,
         DeviceConfig.NAMESPACE_VIRTUALIZATION_FRAMEWORK_NATIVE,
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index b25206d..7e48f68 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -3391,6 +3391,7 @@
          * consistency of the Ikev2VpnRunner fields.
          */
         public void onDefaultNetworkChanged(@NonNull Network network) {
+            mEventChanges.log("[UnderlyingNW] Default network changed to " + network);
             Log.d(TAG, "onDefaultNetworkChanged: " + network);
 
             // If there is a new default network brought up, cancel the retry task to prevent
@@ -3628,6 +3629,7 @@
                 mNetworkCapabilities = new NetworkCapabilities.Builder(mNetworkCapabilities)
                         .setTransportInfo(info)
                         .build();
+                mEventChanges.log("[VPNRunner] Update agent caps " + mNetworkCapabilities);
                 doSendNetworkCapabilities(mNetworkAgent, mNetworkCapabilities);
             }
         }
@@ -3664,6 +3666,7 @@
 
         private void startIkeSession(@NonNull Network underlyingNetwork) {
             Log.d(TAG, "Start new IKE session on network " + underlyingNetwork);
+            mEventChanges.log("[IKE] Start IKE session over " + underlyingNetwork);
 
             try {
                 // Clear mInterface to prevent Ikev2VpnRunner being cleared when
@@ -3778,6 +3781,7 @@
         }
 
         public void onValidationStatus(int status) {
+            mEventChanges.log("[Validation] validation status " + status);
             if (status == NetworkAgent.VALIDATION_STATUS_VALID) {
                 // No data stall now. Reset it.
                 mExecutor.execute(() -> {
@@ -3818,6 +3822,7 @@
          * consistency of the Ikev2VpnRunner fields.
          */
         public void onDefaultNetworkLost(@NonNull Network network) {
+            mEventChanges.log("[UnderlyingNW] Network lost " + network);
             // If the default network is torn down, there is no need to call
             // startOrMigrateIkeSession() since it will always check if there is an active network
             // can be used or not.
@@ -3936,6 +3941,8 @@
          * consistency of the Ikev2VpnRunner fields.
          */
         public void onSessionLost(int token, @Nullable Exception exception) {
+            mEventChanges.log("[IKE] Session lost on network " + mActiveNetwork
+                    + (null == exception ? "" : " reason " + exception.getMessage()));
             Log.d(TAG, "onSessionLost() called for token " + token);
 
             if (!isActiveToken(token)) {
@@ -4092,6 +4099,7 @@
          * consistency of the Ikev2VpnRunner fields.
          */
         private void disconnectVpnRunner() {
+            mEventChanges.log("[VPNRunner] Disconnect runner, underlying network" + mActiveNetwork);
             mActiveNetwork = null;
             mUnderlyingNetworkCapabilities = null;
             mUnderlyingLinkProperties = null;
diff --git a/services/core/java/com/android/server/pm/DynamicCodeLoggingService.java b/services/core/java/com/android/server/pm/DynamicCodeLoggingService.java
index b4bcd5b..5de1559 100644
--- a/services/core/java/com/android/server/pm/DynamicCodeLoggingService.java
+++ b/services/core/java/com/android/server/pm/DynamicCodeLoggingService.java
@@ -61,7 +61,7 @@
     private static final String AVC_PREFIX = "type=" + AUDIT_AVC + " ";
 
     private static final Pattern EXECUTE_NATIVE_AUDIT_PATTERN =
-            Pattern.compile(".*\\bavc: granted \\{ execute(?:_no_trans|) \\} .*"
+            Pattern.compile(".*\\bavc: +granted +\\{ execute(?:_no_trans|) \\} .*"
                     + "\\bpath=(?:\"([^\" ]*)\"|([0-9A-F]+)) .*"
                     + "\\bscontext=u:r:untrusted_app(?:_25|_27)?:.*"
                     + "\\btcontext=u:object_r:app_data_file:.*"
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 329849b..c90b94d 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -3708,13 +3708,12 @@
      * NR_SA - NR SA is unmetered for sub-6 frequencies
      * NR_SA_MMWAVE - NR SA is unmetered for mmwave frequencies
      *
-     * Note that this config only applies if an unmetered SubscriptionPlan is set via
-     * {@link SubscriptionManager#setSubscriptionPlans(int, List)} or an unmetered override is set
+     * Note that this config only applies if an unmetered SubscriptionPlan is set via {@link
+     * SubscriptionManager#setSubscriptionPlans(int, List, long)} or an unmetered override is set
      * via {@link SubscriptionManager#setSubscriptionOverrideUnmetered(int, boolean, int[], long)}
      * or {@link SubscriptionManager#setSubscriptionOverrideUnmetered(int, boolean, long)}.
      * If neither SubscriptionPlans nor an override are set, then no network types can be unmetered
      * regardless of the value of this config.
-     * TODO: remove other unmetered keys and replace with this
      * @hide
      */
     public static final String KEY_UNMETERED_NETWORK_TYPES_STRING_ARRAY =
@@ -3729,73 +3728,18 @@
      * NR_SA - NR SA is unmetered when roaming for sub-6 frequencies
      * NR_SA_MMWAVE - NR SA is unmetered when roaming for mmwave frequencies
      *
-     * Note that this config only applies if an unmetered SubscriptionPlan is set via
-     * {@link SubscriptionManager#setSubscriptionPlans(int, List)} or an unmetered override is set
+     * Note that this config only applies if an unmetered SubscriptionPlan is set via {@link
+     * SubscriptionManager#setSubscriptionPlans(int, List, long)} or an unmetered override is set
      * via {@link SubscriptionManager#setSubscriptionOverrideUnmetered(int, boolean, int[], long)}
      * or {@link SubscriptionManager#setSubscriptionOverrideUnmetered(int, boolean, long)}.
      * If neither SubscriptionPlans nor an override are set, then no network types can be unmetered
      * when roaming regardless of the value of this config.
-     * TODO: remove KEY_UNMETERED_NR_NSA_WHEN_ROAMING_BOOL and replace with this
      * @hide
      */
     public static final String KEY_ROAMING_UNMETERED_NETWORK_TYPES_STRING_ARRAY =
             "roaming_unmetered_network_types_string_array";
 
     /**
-     * Whether NR (non-standalone) should be unmetered for all frequencies.
-     * If either {@link #KEY_UNMETERED_NR_NSA_MMWAVE_BOOL} or
-     * {@link #KEY_UNMETERED_NR_NSA_SUB6_BOOL} are true, then this value will be ignored.
-     * @hide
-     */
-    public static final String KEY_UNMETERED_NR_NSA_BOOL = "unmetered_nr_nsa_bool";
-
-    /**
-     * Whether NR (non-standalone) frequencies above 6GHz (millimeter wave) should be unmetered.
-     * If this is true, then the value for {@link #KEY_UNMETERED_NR_NSA_BOOL} will be ignored.
-     * @hide
-     */
-    public static final String KEY_UNMETERED_NR_NSA_MMWAVE_BOOL = "unmetered_nr_nsa_mmwave_bool";
-
-    /**
-     * Whether NR (non-standalone) frequencies below 6GHz (sub6) should be unmetered.
-     * If this is true, then the value for {@link #KEY_UNMETERED_NR_NSA_BOOL} will be ignored.
-     * @hide
-     */
-    public static final String KEY_UNMETERED_NR_NSA_SUB6_BOOL = "unmetered_nr_nsa_sub6_bool";
-
-    /**
-     * Whether NR (non-standalone) should be unmetered when the device is roaming.
-     * If false, then the values for {@link #KEY_UNMETERED_NR_NSA_BOOL},
-     * {@link #KEY_UNMETERED_NR_NSA_MMWAVE_BOOL}, {@link #KEY_UNMETERED_NR_NSA_SUB6_BOOL},
-     * and unmetered {@link SubscriptionPlan} will be ignored.
-     * @hide
-     */
-    public static final String KEY_UNMETERED_NR_NSA_WHEN_ROAMING_BOOL =
-            "unmetered_nr_nsa_when_roaming_bool";
-
-    /**
-     * Whether NR (standalone) should be unmetered for all frequencies.
-     * If either {@link #KEY_UNMETERED_NR_SA_MMWAVE_BOOL} or
-     * {@link #KEY_UNMETERED_NR_SA_SUB6_BOOL} are true, then this value will be ignored.
-     * @hide
-     */
-    public static final String KEY_UNMETERED_NR_SA_BOOL = "unmetered_nr_sa_bool";
-
-    /**
-     * Whether NR (standalone) frequencies above 6GHz (millimeter wave) should be unmetered.
-     * If this is true, then the value for {@link #KEY_UNMETERED_NR_SA_BOOL} will be ignored.
-     * @hide
-     */
-    public static final String KEY_UNMETERED_NR_SA_MMWAVE_BOOL = "unmetered_nr_sa_mmwave_bool";
-
-    /**
-     * Whether NR (standalone) frequencies below 6GHz (sub6) should be unmetered.
-     * If this is true, then the value for {@link #KEY_UNMETERED_NR_SA_BOOL} will be ignored.
-     * @hide
-     */
-    public static final String KEY_UNMETERED_NR_SA_SUB6_BOOL = "unmetered_nr_sa_sub6_bool";
-
-    /**
      * Support ASCII 7-BIT encoding for long SMS. This carrier config is used to enable
      * this feature.
      * @hide
@@ -9255,13 +9199,6 @@
         sDefaults.putStringArray(KEY_UNMETERED_NETWORK_TYPES_STRING_ARRAY, new String[] {
                 "NR_NSA", "NR_NSA_MMWAVE", "NR_SA", "NR_SA_MMWAVE"});
         sDefaults.putStringArray(KEY_ROAMING_UNMETERED_NETWORK_TYPES_STRING_ARRAY, new String[0]);
-        sDefaults.putBoolean(KEY_UNMETERED_NR_NSA_BOOL, false);
-        sDefaults.putBoolean(KEY_UNMETERED_NR_NSA_MMWAVE_BOOL, false);
-        sDefaults.putBoolean(KEY_UNMETERED_NR_NSA_SUB6_BOOL, false);
-        sDefaults.putBoolean(KEY_UNMETERED_NR_NSA_WHEN_ROAMING_BOOL, false);
-        sDefaults.putBoolean(KEY_UNMETERED_NR_SA_BOOL, false);
-        sDefaults.putBoolean(KEY_UNMETERED_NR_SA_MMWAVE_BOOL, false);
-        sDefaults.putBoolean(KEY_UNMETERED_NR_SA_SUB6_BOOL, false);
         sDefaults.putBoolean(KEY_ASCII_7_BIT_SUPPORT_FOR_LONG_MESSAGE_BOOL, false);
         sDefaults.putBoolean(KEY_SHOW_WIFI_CALLING_ICON_IN_STATUS_BAR_BOOL, false);
         sDefaults.putBoolean(KEY_CARRIER_SUPPORTS_OPP_DATA_AUTO_PROVISIONING_BOOL, false);
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index d590ce2..45c092e 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -160,6 +160,10 @@
     private static final String CACHE_KEY_SUBSCRIPTION_MANAGER_SERVICE_PROPERTY =
             "cache_key.telephony.subscription_manager_service";
 
+    /** The temporarily cache key to indicate whether subscription manager service is enabled. */
+    private static final String CACHE_KEY_SUBSCRIPTION_MANAGER_SERVICE_ENABLED_PROPERTY =
+            "cache_key.telephony.subscription_manager_service_enabled";
+
     /** @hide */
     public static final String GET_SIM_SPECIFIC_SETTINGS_METHOD_NAME = "getSimSpecificSettings";
 
@@ -317,6 +321,12 @@
                     CACHE_KEY_SUBSCRIPTION_MANAGER_SERVICE_PROPERTY,
                     INVALID_PHONE_INDEX);
 
+    //TODO: Removed before U AOSP public release.
+    private static VoidPropertyInvalidatedCache<Boolean> sIsSubscriptionManagerServiceEnabled =
+            new VoidPropertyInvalidatedCache<>(ISub::isSubscriptionManagerServiceEnabled,
+                    CACHE_KEY_SUBSCRIPTION_MANAGER_SERVICE_ENABLED_PROPERTY,
+                    false);
+
     /**
      * Generates a content {@link Uri} used to receive updates on simInfo change
      * on the given subscriptionId
@@ -1335,8 +1345,6 @@
 
     private final Context mContext;
 
-    private static boolean sIsSubscriptionManagerServiceEnabled = false;
-
     // Cache of Resource that has been created in getResourcesForSubId. Key is a Pair containing
     // the Context and subId.
     private static final Map<Pair<Context, Integer>, Resources> sResourcesCache =
@@ -1422,9 +1430,6 @@
     public SubscriptionManager(Context context) {
         if (DBG) logd("SubscriptionManager created");
         mContext = context;
-
-        sIsSubscriptionManagerServiceEnabled = mContext.getResources().getBoolean(
-                com.android.internal.R.bool.config_using_subscription_manager_service);
     }
 
     /**
@@ -1433,8 +1438,9 @@
      *
      * @hide
      */
+    //TODO: Removed before U AOSP public release.
     public static boolean isSubscriptionManagerServiceEnabled() {
-        return sIsSubscriptionManagerServiceEnabled;
+        return sIsSubscriptionManagerServiceEnabled.query(null);
     }
 
     private NetworkPolicyManager getNetworkPolicyManager() {
@@ -3947,6 +3953,13 @@
         PropertyInvalidatedCache.invalidateCache(CACHE_KEY_SUBSCRIPTION_MANAGER_SERVICE_PROPERTY);
     }
 
+    /** @hide */
+    //TODO: Removed before U AOSP public release.
+    public static void invalidateSubscriptionManagerServiceEnabledCaches() {
+        PropertyInvalidatedCache.invalidateCache(
+                CACHE_KEY_SUBSCRIPTION_MANAGER_SERVICE_ENABLED_PROPERTY);
+    }
+
     /**
      * Allows a test process to disable client-side caching operations.
      *
@@ -3968,6 +3981,8 @@
         sGetSlotIndexCache.disableLocal();
         sGetSubIdCache.disableLocal();
         sGetPhoneIdCache.disableLocal();
+
+        sIsSubscriptionManagerServiceEnabled.disableLocal();
     }
 
     /**
@@ -3990,6 +4005,8 @@
         sGetSlotIndexCache.clear();
         sGetSubIdCache.clear();
         sGetPhoneIdCache.clear();
+
+        sIsSubscriptionManagerServiceEnabled.clear();
     }
 
     /**
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index fd5ec25..fa60031 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -311,6 +311,31 @@
     public static final int SRVCC_STATE_HANDOVER_CANCELED  = 3;
 
     /**
+     * Convert srvcc handover state to string.
+     *
+     * @param state The srvcc handover state.
+     * @return The srvcc handover state in string format.
+     *
+     * @hide
+     */
+    public static @NonNull String srvccStateToString(int state) {
+        switch (state) {
+            case TelephonyManager.SRVCC_STATE_HANDOVER_NONE:
+                return "NONE";
+            case TelephonyManager.SRVCC_STATE_HANDOVER_STARTED:
+                return "STARTED";
+            case TelephonyManager.SRVCC_STATE_HANDOVER_COMPLETED:
+                return "COMPLETED";
+            case TelephonyManager.SRVCC_STATE_HANDOVER_FAILED:
+                return "FAILED";
+            case TelephonyManager.SRVCC_STATE_HANDOVER_CANCELED:
+                return "CANCELED";
+            default:
+                return "UNKNOWN(" + state + ")";
+        }
+    }
+
+    /**
      * A UICC card identifier used if the device does not support the operation.
      * For example, {@link #getCardIdForDefaultEuicc()} returns this value if the device has no
      * eUICC, or the eUICC cannot be read.
diff --git a/telephony/java/com/android/internal/telephony/ISub.aidl b/telephony/java/com/android/internal/telephony/ISub.aidl
index 25a714a..defa046 100644
--- a/telephony/java/com/android/internal/telephony/ISub.aidl
+++ b/telephony/java/com/android/internal/telephony/ISub.aidl
@@ -356,4 +356,11 @@
        * @hide
        */
        List<SubscriptionInfo> getSubscriptionInfoListAssociatedWithUser(in UserHandle userHandle);
+
+       /**
+        * @return {@code true} if using SubscriptionManagerService instead of
+        * SubscriptionController.
+        */
+       //TODO: Removed before U AOSP public release.
+       boolean isSubscriptionManagerServiceEnabled();
 }
diff --git a/tests/DynamicCodeLoggerIntegrationTests/src/com/android/server/pm/dex/DynamicCodeLoggerIntegrationTests.java b/tests/DynamicCodeLoggerIntegrationTests/src/com/android/server/pm/dex/DynamicCodeLoggerIntegrationTests.java
index 5430dee..afa4ff8 100644
--- a/tests/DynamicCodeLoggerIntegrationTests/src/com/android/server/pm/dex/DynamicCodeLoggerIntegrationTests.java
+++ b/tests/DynamicCodeLoggerIntegrationTests/src/com/android/server/pm/dex/DynamicCodeLoggerIntegrationTests.java
@@ -84,7 +84,7 @@
     // avoid flakiness we run these tests multiple times, allowing progressively longer between
     // code loading and checking the logs on each try.)
     private static final int AUDIT_LOG_RETRIES = 10;
-    private static final int RETRY_DELAY_MS = 2_000;
+    private static final int RETRY_DELAY_MS = 500;
 
     private static Context sContext;
     private static int sMyUid;
@@ -245,7 +245,7 @@
                 "/DynamicCodeLoggerNativeExecutable", privateCopyFile);
 
         EventLog.writeEvent(EventLog.getTagCode("auditd"),
-                "type=1400 avc: granted { execute_no_trans } "
+                "type=1400 avc:  granted  { execute_no_trans } "
                         + "path=\"" + privateCopyFile + "\" "
                         + "scontext=u:r:untrusted_app: "
                         + "tcontext=u:object_r:app_data_file: "