Merge "Import androidx AppBar changes" into main
diff --git a/api/gen_combined_removed_dex.sh b/api/gen_combined_removed_dex.sh
index 9225fe8..71f366a 100755
--- a/api/gen_combined_removed_dex.sh
+++ b/api/gen_combined_removed_dex.sh
@@ -6,6 +6,6 @@
 
 # Convert each removed.txt to the "dex format" equivalent, and print all output.
 for f in "$@"; do
-    "$metalava_path" --no-banner "$f" --dex-api "${tmp_dir}/tmp"
+    "$metalava_path" "$f" --dex-api "${tmp_dir}/tmp"
     cat "${tmp_dir}/tmp"
 done
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index a8a6eb9..a4cc446 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -50,6 +50,7 @@
     field public static final String SET_AND_VERIFY_LOCKSCREEN_CREDENTIALS = "android.permission.SET_AND_VERIFY_LOCKSCREEN_CREDENTIALS";
     field public static final String SET_GAME_SERVICE = "android.permission.SET_GAME_SERVICE";
     field public static final String SET_KEYBOARD_LAYOUT = "android.permission.SET_KEYBOARD_LAYOUT";
+    field public static final String START_ACTIVITIES_FROM_SDK_SANDBOX = "android.permission.START_ACTIVITIES_FROM_SDK_SANDBOX";
     field public static final String SUSPEND_APPS = "android.permission.SUSPEND_APPS";
     field public static final String TEST_BIOMETRIC = "android.permission.TEST_BIOMETRIC";
     field public static final String TEST_INPUT_METHOD = "android.permission.TEST_INPUT_METHOD";
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 00e546a..0191201 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -3720,7 +3720,19 @@
     /**  Core implementation of activity launch. */
     private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
         ActivityInfo aInfo = r.activityInfo;
-        if (r.packageInfo == null) {
+
+        if (getInstrumentation() != null
+                && getInstrumentation().getContext() != null
+                && getInstrumentation().getContext().getApplicationInfo() != null
+                && getInstrumentation().isSdkSandboxAllowedToStartActivities()) {
+            // Activities launched from CTS-in-sandbox tests use a customized ApplicationInfo. See
+            // also {@link SdkSandboxManagerLocal#getSdkSandboxApplicationInfoForInstrumentation}.
+            r.packageInfo =
+                    getPackageInfo(
+                            getInstrumentation().getContext().getApplicationInfo(),
+                            mCompatibilityInfo,
+                            Context.CONTEXT_INCLUDE_CODE);
+        } else if (r.packageInfo == null) {
             r.packageInfo = getPackageInfo(aInfo.applicationInfo, mCompatibilityInfo,
                     Context.CONTEXT_INCLUDE_CODE);
         }
diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java
index e31486f..10747bb 100644
--- a/core/java/android/app/Instrumentation.java
+++ b/core/java/android/app/Instrumentation.java
@@ -26,6 +26,7 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
 import android.content.res.Configuration;
 import android.hardware.input.InputManager;
 import android.hardware.input.InputManagerGlobal;
@@ -474,6 +475,56 @@
         sr.waitForComplete();
     }
 
+    boolean isSdkSandboxAllowedToStartActivities() {
+        return Process.isSdkSandbox()
+                && mThread != null
+                && mThread.mBoundApplication != null
+                && mThread.mBoundApplication.isSdkInSandbox
+                && getContext() != null
+                && (getContext()
+                                .checkSelfPermission(
+                                        android.Manifest.permission
+                                                .START_ACTIVITIES_FROM_SDK_SANDBOX)
+                        == PackageManager.PERMISSION_GRANTED);
+    }
+
+    /**
+     * Activity name resolution for CTS-in-SdkSandbox tests requires some adjustments. Intents
+     * generated using {@link Context#getPackageName()} use the SDK sandbox package name in the
+     * component field instead of the test package name. An SDK-in-sandbox test attempting to launch
+     * an activity in the test package will encounter name resolution errors when resolving the
+     * activity name in the SDK sandbox package.
+     *
+     * <p>This function replaces the package name of the input intent component to allow activities
+     * belonging to a CTS-in-sandbox test to resolve correctly.
+     *
+     * @param intent the intent to modify to allow CTS-in-sandbox activity resolution.
+     */
+    private void adjustIntentForCtsInSdkSandboxInstrumentation(@NonNull Intent intent) {
+        if (mComponent != null
+                && intent.getComponent() != null
+                && getContext()
+                        .getPackageManager()
+                        .getSdkSandboxPackageName()
+                        .equals(intent.getComponent().getPackageName())) {
+            // Resolve the intent target for the test package, not for the sandbox package.
+            intent.setComponent(
+                    new ComponentName(
+                            mComponent.getPackageName(), intent.getComponent().getClassName()));
+        }
+        // We match the intent identifier against the running instrumentations for the sandbox.
+        intent.setIdentifier(mComponent.getPackageName());
+    }
+
+    private ActivityInfo resolveActivityInfoForCtsInSandbox(@NonNull Intent intent) {
+        adjustIntentForCtsInSdkSandboxInstrumentation(intent);
+        ActivityInfo ai = intent.resolveActivityInfo(getTargetContext().getPackageManager(), 0);
+        if (ai != null) {
+            ai.processName = mThread.getProcessName();
+        }
+        return ai;
+    }
+
     /**
      * Start a new activity and wait for it to begin running before returning.
      * In addition to being synchronous, this method as some semantic
@@ -531,8 +582,10 @@
         synchronized (mSync) {
             intent = new Intent(intent);
 
-            ActivityInfo ai = intent.resolveActivityInfo(
-                getTargetContext().getPackageManager(), 0);
+            ActivityInfo ai =
+                    isSdkSandboxAllowedToStartActivities()
+                            ? resolveActivityInfoForCtsInSandbox(intent)
+                            : intent.resolveActivityInfo(getTargetContext().getPackageManager(), 0);
             if (ai == null) {
                 throw new RuntimeException("Unable to resolve activity for: " + intent);
             }
@@ -1842,6 +1895,9 @@
         if (referrer != null) {
             intent.putExtra(Intent.EXTRA_REFERRER, referrer);
         }
+        if (isSdkSandboxAllowedToStartActivities()) {
+            adjustIntentForCtsInSdkSandboxInstrumentation(intent);
+        }
         if (mActivityMonitors != null) {
             synchronized (mSync) {
                 final int N = mActivityMonitors.size();
@@ -1914,6 +1970,11 @@
             IBinder token, Activity target, Intent[] intents, Bundle options,
             int userId) {
         IApplicationThread whoThread = (IApplicationThread) contextThread;
+        if (isSdkSandboxAllowedToStartActivities()) {
+            for (Intent intent : intents) {
+                adjustIntentForCtsInSdkSandboxInstrumentation(intent);
+            }
+        }
         if (mActivityMonitors != null) {
             synchronized (mSync) {
                 final int N = mActivityMonitors.size();
@@ -1989,6 +2050,9 @@
         Context who, IBinder contextThread, IBinder token, String target,
         Intent intent, int requestCode, Bundle options) {
         IApplicationThread whoThread = (IApplicationThread) contextThread;
+        if (isSdkSandboxAllowedToStartActivities()) {
+            adjustIntentForCtsInSdkSandboxInstrumentation(intent);
+        }
         if (mActivityMonitors != null) {
             synchronized (mSync) {
                 final int N = mActivityMonitors.size();
@@ -2060,6 +2124,9 @@
             Context who, IBinder contextThread, IBinder token, String resultWho,
             Intent intent, int requestCode, Bundle options, UserHandle user) {
         IApplicationThread whoThread = (IApplicationThread) contextThread;
+        if (isSdkSandboxAllowedToStartActivities()) {
+            adjustIntentForCtsInSdkSandboxInstrumentation(intent);
+        }
         if (mActivityMonitors != null) {
             synchronized (mSync) {
                 final int N = mActivityMonitors.size();
@@ -2110,6 +2177,9 @@
             Intent intent, int requestCode, Bundle options,
             boolean ignoreTargetSecurity, int userId) {
         IApplicationThread whoThread = (IApplicationThread) contextThread;
+        if (isSdkSandboxAllowedToStartActivities()) {
+            adjustIntentForCtsInSdkSandboxInstrumentation(intent);
+        }
         if (mActivityMonitors != null) {
             synchronized (mSync) {
                 final int N = mActivityMonitors.size();
@@ -2161,6 +2231,9 @@
             Context who, IBinder contextThread, IAppTask appTask,
             Intent intent, Bundle options) {
         IApplicationThread whoThread = (IApplicationThread) contextThread;
+        if (isSdkSandboxAllowedToStartActivities()) {
+            adjustIntentForCtsInSdkSandboxInstrumentation(intent);
+        }
         if (mActivityMonitors != null) {
             synchronized (mSync) {
                 final int N = mActivityMonitors.size();
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index e9bbed3..7579d99 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -12516,6 +12516,7 @@
         return (mFlags & FLAG_ACTIVITY_NEW_DOCUMENT) == FLAG_ACTIVITY_NEW_DOCUMENT;
     }
 
+    // TODO(b/299109198): Refactor into the {@link SdkSandboxManagerLocal}
     /** @hide */
     public boolean isSandboxActivity(@NonNull Context context) {
         if (mAction != null && mAction.equals(ACTION_START_SANDBOXED_ACTIVITY)) {
diff --git a/core/java/android/content/om/OWNERS b/core/java/android/content/om/OWNERS
index 3669817..72aed2d 100644
--- a/core/java/android/content/om/OWNERS
+++ b/core/java/android/content/om/OWNERS
@@ -1,6 +1,5 @@
 # Bug component: 568631
 
-toddke@android.com
-toddke@google.com
 patb@google.com
 zyy@google.com
+jakmcbane@google.com
\ No newline at end of file
diff --git a/core/java/android/content/pm/ArchivedActivityParcel.aidl b/core/java/android/content/pm/ArchivedActivityParcel.aidl
new file mode 100644
index 0000000..7ab7ed1
--- /dev/null
+++ b/core/java/android/content/pm/ArchivedActivityParcel.aidl
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.pm;
+
+/** @hide */
+parcelable ArchivedActivityParcel {
+    String title;
+    // PNG compressed bitmaps.
+    byte[] iconBitmap;
+    byte[] monochromeIconBitmap;
+}
diff --git a/core/java/android/content/pm/ArchivedPackageParcel.aidl b/core/java/android/content/pm/ArchivedPackageParcel.aidl
index 573e690..d3cd79e 100644
--- a/core/java/android/content/pm/ArchivedPackageParcel.aidl
+++ b/core/java/android/content/pm/ArchivedPackageParcel.aidl
@@ -16,6 +16,7 @@
 
 package android.content.pm;
 
+import android.content.pm.ArchivedActivityParcel;
 import android.content.pm.SigningDetails;
 
 /**
@@ -29,9 +30,8 @@
     int versionCode;
     int versionCodeMajor;
     int targetSdkVersion;
-    String backupAllowed;
     String defaultToDeviceProtectedStorage;
     String requestLegacyExternalStorage;
     String userDataFragile;
-    String clearUserDataOnFailedRestoreAllowed;
+    ArchivedActivityParcel[] archivedActivities;
 }
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 556c794..94c3b52 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -832,5 +832,5 @@
 
     void unregisterPackageMonitorCallback(IRemoteCallback callback);
 
-    ArchivedPackageParcel getArchivedPackage(in String apkPath);
+    ArchivedPackageParcel getArchivedPackage(in String packageName, int userId);
 }
diff --git a/core/java/android/content/pm/RegisteredServicesCache.java b/core/java/android/content/pm/RegisteredServicesCache.java
index 149de7e..0333942 100644
--- a/core/java/android/content/pm/RegisteredServicesCache.java
+++ b/core/java/android/content/pm/RegisteredServicesCache.java
@@ -834,4 +834,11 @@
 
     public abstract V parseServiceAttributes(Resources res,
             String packageName, AttributeSet attrs);
+
+    @VisibleForTesting
+    public void unregisterReceivers() {
+        mContext.unregisterReceiver(mPackageReceiver);
+        mContext.unregisterReceiver(mExternalReceiver);
+        mContext.unregisterReceiver(mUserRemovedReceiver);
+    }
 }
diff --git a/core/java/android/content/pm/parsing/ApkLite.java b/core/java/android/content/pm/parsing/ApkLite.java
index 159b789..f3194be 100644
--- a/core/java/android/content/pm/parsing/ApkLite.java
+++ b/core/java/android/content/pm/parsing/ApkLite.java
@@ -23,11 +23,9 @@
 import android.content.pm.PackageManager;
 import android.content.pm.SigningDetails;
 import android.content.pm.VerifierInfo;
-import android.os.Build;
 
 import com.android.internal.util.CollectionUtils;
 import com.android.internal.util.DataClass;
-import com.android.internal.util.XmlUtils;
 
 import java.util.List;
 import java.util.Set;
@@ -142,32 +140,9 @@
     private final boolean mIsSdkLibrary;
 
     /**
-     *  Set to <code>false</code> if the application does not wish to permit any OS-driven
-     *  backups of its data; <code>true</code> otherwise.
+     * Archival install info.
      */
-    private final boolean mBackupAllowed;
-
-    /**
-     * When set, the default data storage directory for this app is pointed at
-     * the device-protected location.
-     */
-    private final boolean mDefaultToDeviceProtectedStorage;
-
-    /**
-     * If {@code true} this app requests full external storage access.
-     */
-    private final boolean mRequestLegacyExternalStorage;
-
-    /**
-     * Indicates whether this application has declared its user data as fragile, causing the
-     * system to prompt the user on whether to keep the user data on uninstall.
-     */
-    private final boolean mUserDataFragile;
-
-    /**
-     * Indicates whether this application's data will be cleared on a failed restore.
-     */
-    private final boolean mClearUserDataOnFailedRestoreAllowed;
+    private final @Nullable ArchivedPackageParcel mArchivedPackage;
 
     public ApkLite(String path, String packageName, String splitName, boolean isFeatureSplit,
             String configForSplit, String usesSplitName, boolean isSplitRequired, int versionCode,
@@ -179,10 +154,7 @@
             String requiredSystemPropertyName, String requiredSystemPropertyValue,
             int minSdkVersion, int targetSdkVersion, int rollbackDataPolicy,
             Set<String> requiredSplitTypes, Set<String> splitTypes,
-            boolean hasDeviceAdminReceiver, boolean isSdkLibrary, boolean clearUserDataAllowed,
-            boolean backupAllowed, boolean defaultToDeviceProtectedStorage,
-            boolean requestLegacyExternalStorage, boolean userDataFragile,
-            boolean clearUserDataOnFailedRestoreAllowed) {
+            boolean hasDeviceAdminReceiver, boolean isSdkLibrary) {
         mPath = path;
         mPackageName = packageName;
         mSplitName = splitName;
@@ -216,11 +188,7 @@
         mRollbackDataPolicy = rollbackDataPolicy;
         mHasDeviceAdminReceiver = hasDeviceAdminReceiver;
         mIsSdkLibrary = isSdkLibrary;
-        mBackupAllowed = backupAllowed;
-        mDefaultToDeviceProtectedStorage = defaultToDeviceProtectedStorage;
-        mRequestLegacyExternalStorage = requestLegacyExternalStorage;
-        mUserDataFragile = userDataFragile;
-        mClearUserDataOnFailedRestoreAllowed = clearUserDataOnFailedRestoreAllowed;
+        mArchivedPackage = null;
     }
 
     public ApkLite(String path, ArchivedPackageParcel archivedPackage) {
@@ -257,16 +225,7 @@
         mRollbackDataPolicy = 0;
         mHasDeviceAdminReceiver = false;
         mIsSdkLibrary = false;
-        // @see ParsingPackageUtils#parseBaseAppBasicFlags
-        mBackupAllowed = XmlUtils.convertValueToBoolean(archivedPackage.backupAllowed, true);
-        mDefaultToDeviceProtectedStorage = XmlUtils.convertValueToBoolean(
-                archivedPackage.defaultToDeviceProtectedStorage, false);
-        mRequestLegacyExternalStorage = XmlUtils.convertValueToBoolean(
-                archivedPackage.requestLegacyExternalStorage,
-                mTargetSdkVersion < Build.VERSION_CODES.Q);
-        mUserDataFragile = XmlUtils.convertValueToBoolean(archivedPackage.userDataFragile, false);
-        mClearUserDataOnFailedRestoreAllowed = XmlUtils.convertValueToBoolean(
-                archivedPackage.clearUserDataOnFailedRestoreAllowed, true);
+        mArchivedPackage = archivedPackage;
     }
 
     /**
@@ -576,53 +535,18 @@
     }
 
     /**
-     *  Set to <code>false</code> if the application does not wish to permit any OS-driven
-     *  backups of its data; <code>true</code> otherwise.
+     * Archival install info.
      */
     @DataClass.Generated.Member
-    public boolean isBackupAllowed() {
-        return mBackupAllowed;
-    }
-
-    /**
-     * When set, the default data storage directory for this app is pointed at
-     * the device-protected location.
-     */
-    @DataClass.Generated.Member
-    public boolean isDefaultToDeviceProtectedStorage() {
-        return mDefaultToDeviceProtectedStorage;
-    }
-
-    /**
-     * If {@code true} this app requests full external storage access.
-     */
-    @DataClass.Generated.Member
-    public boolean isRequestLegacyExternalStorage() {
-        return mRequestLegacyExternalStorage;
-    }
-
-    /**
-     * Indicates whether this application has declared its user data as fragile, causing the
-     * system to prompt the user on whether to keep the user data on uninstall.
-     */
-    @DataClass.Generated.Member
-    public boolean isUserDataFragile() {
-        return mUserDataFragile;
-    }
-
-    /**
-     * Indicates whether this application's data will be cleared on a failed restore.
-     */
-    @DataClass.Generated.Member
-    public boolean isClearUserDataOnFailedRestoreAllowed() {
-        return mClearUserDataOnFailedRestoreAllowed;
+    public @Nullable ArchivedPackageParcel getArchivedPackage() {
+        return mArchivedPackage;
     }
 
     @DataClass.Generated(
-            time = 1693513509013L,
+            time = 1694792109463L,
             codegenVersion = "1.0.23",
             sourceFile = "frameworks/base/core/java/android/content/pm/parsing/ApkLite.java",
-            inputSignatures = "private final @android.annotation.NonNull java.lang.String mPackageName\nprivate final @android.annotation.NonNull java.lang.String mPath\nprivate final @android.annotation.Nullable java.lang.String mSplitName\nprivate final @android.annotation.Nullable java.lang.String mUsesSplitName\nprivate final @android.annotation.Nullable java.lang.String mConfigForSplit\nprivate final @android.annotation.Nullable java.util.Set<java.lang.String> mRequiredSplitTypes\nprivate final @android.annotation.Nullable java.util.Set<java.lang.String> mSplitTypes\nprivate final  int mVersionCodeMajor\nprivate final  int mVersionCode\nprivate final  int mRevisionCode\nprivate final  int mInstallLocation\nprivate final  int mMinSdkVersion\nprivate final  int mTargetSdkVersion\nprivate final @android.annotation.NonNull android.content.pm.VerifierInfo[] mVerifiers\nprivate final @android.annotation.NonNull android.content.pm.SigningDetails mSigningDetails\nprivate final  boolean mFeatureSplit\nprivate final  boolean mIsolatedSplits\nprivate final  boolean mSplitRequired\nprivate final  boolean mCoreApp\nprivate final  boolean mDebuggable\nprivate final  boolean mProfileableByShell\nprivate final  boolean mMultiArch\nprivate final  boolean mUse32bitAbi\nprivate final  boolean mExtractNativeLibs\nprivate final  boolean mUseEmbeddedDex\nprivate final @android.annotation.Nullable java.lang.String mTargetPackageName\nprivate final  boolean mOverlayIsStatic\nprivate final  int mOverlayPriority\nprivate final @android.annotation.Nullable java.lang.String mRequiredSystemPropertyName\nprivate final @android.annotation.Nullable java.lang.String mRequiredSystemPropertyValue\nprivate final  int mRollbackDataPolicy\nprivate final  boolean mHasDeviceAdminReceiver\nprivate final  boolean mIsSdkLibrary\nprivate final  boolean mBackupAllowed\nprivate final  boolean mDefaultToDeviceProtectedStorage\nprivate final  boolean mRequestLegacyExternalStorage\nprivate final  boolean mUserDataFragile\nprivate final  boolean mClearUserDataOnFailedRestoreAllowed\npublic  long getLongVersionCode()\nprivate  boolean hasAnyRequiredSplitTypes()\nclass ApkLite extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genConstructor=false, genConstDefs=false)")
+            inputSignatures = "private final @android.annotation.NonNull java.lang.String mPackageName\nprivate final @android.annotation.NonNull java.lang.String mPath\nprivate final @android.annotation.Nullable java.lang.String mSplitName\nprivate final @android.annotation.Nullable java.lang.String mUsesSplitName\nprivate final @android.annotation.Nullable java.lang.String mConfigForSplit\nprivate final @android.annotation.Nullable java.util.Set<java.lang.String> mRequiredSplitTypes\nprivate final @android.annotation.Nullable java.util.Set<java.lang.String> mSplitTypes\nprivate final  int mVersionCodeMajor\nprivate final  int mVersionCode\nprivate final  int mRevisionCode\nprivate final  int mInstallLocation\nprivate final  int mMinSdkVersion\nprivate final  int mTargetSdkVersion\nprivate final @android.annotation.NonNull android.content.pm.VerifierInfo[] mVerifiers\nprivate final @android.annotation.NonNull android.content.pm.SigningDetails mSigningDetails\nprivate final  boolean mFeatureSplit\nprivate final  boolean mIsolatedSplits\nprivate final  boolean mSplitRequired\nprivate final  boolean mCoreApp\nprivate final  boolean mDebuggable\nprivate final  boolean mProfileableByShell\nprivate final  boolean mMultiArch\nprivate final  boolean mUse32bitAbi\nprivate final  boolean mExtractNativeLibs\nprivate final  boolean mUseEmbeddedDex\nprivate final @android.annotation.Nullable java.lang.String mTargetPackageName\nprivate final  boolean mOverlayIsStatic\nprivate final  int mOverlayPriority\nprivate final @android.annotation.Nullable java.lang.String mRequiredSystemPropertyName\nprivate final @android.annotation.Nullable java.lang.String mRequiredSystemPropertyValue\nprivate final  int mRollbackDataPolicy\nprivate final  boolean mHasDeviceAdminReceiver\nprivate final  boolean mIsSdkLibrary\nprivate final @android.annotation.Nullable android.content.pm.ArchivedPackageParcel mArchivedPackage\npublic  long getLongVersionCode()\nprivate  boolean hasAnyRequiredSplitTypes()\nclass ApkLite extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genConstructor=false, genConstDefs=false)")
     @Deprecated
     private void __metadata() {}
 
diff --git a/core/java/android/content/pm/parsing/ApkLiteParseUtils.java b/core/java/android/content/pm/parsing/ApkLiteParseUtils.java
index 066ff689..5f86742 100644
--- a/core/java/android/content/pm/parsing/ApkLiteParseUtils.java
+++ b/core/java/android/content/pm/parsing/ApkLiteParseUtils.java
@@ -40,7 +40,6 @@
 import android.util.Slog;
 
 import com.android.internal.util.ArrayUtils;
-import com.android.internal.util.XmlUtils;
 
 import libcore.io.IoUtils;
 
@@ -447,13 +446,6 @@
         int overlayPriority = 0;
         int rollbackDataPolicy = 0;
 
-        boolean clearUserDataAllowed = true;
-        boolean backupAllowed = true;
-        boolean defaultToDeviceProtectedStorage = false;
-        String requestLegacyExternalStorage = null;
-        boolean userDataFragile = false;
-        boolean clearUserDataOnFailedRestoreAllowed = true;
-
         String requiredSystemPropertyName = null;
         String requiredSystemPropertyValue = null;
 
@@ -493,22 +485,6 @@
                 useEmbeddedDex = parser.getAttributeBooleanValue(ANDROID_RES_NAMESPACE,
                         "useEmbeddedDex", false);
 
-                clearUserDataAllowed = parser.getAttributeBooleanValue(ANDROID_RES_NAMESPACE,
-                        "allowClearUserDataOnFailedRestore", true);
-                backupAllowed = parser.getAttributeBooleanValue(ANDROID_RES_NAMESPACE,
-                        "allowBackup", true);
-                defaultToDeviceProtectedStorage = parser.getAttributeBooleanValue(
-                        ANDROID_RES_NAMESPACE,
-                        "defaultToDeviceProtectedStorage", false);
-                userDataFragile = parser.getAttributeBooleanValue(ANDROID_RES_NAMESPACE,
-                        "hasFragileUserData", false);
-                clearUserDataOnFailedRestoreAllowed = parser.getAttributeBooleanValue(
-                        ANDROID_RES_NAMESPACE,
-                        "allowClearUserDataOnFailedRestore", true);
-
-                requestLegacyExternalStorage = parser.getAttributeValue(ANDROID_RES_NAMESPACE,
-                        "requestLegacyExternalStorage");
-
                 rollbackDataPolicy = parser.getAttributeIntValue(ANDROID_RES_NAMESPACE,
                         "rollbackDataPolicy", 0);
                 String permission = parser.getAttributeValue(ANDROID_RES_NAMESPACE,
@@ -629,9 +605,6 @@
             return input.skip(message);
         }
 
-        boolean isRequestLegacyExternalStorage = XmlUtils.convertValueToBoolean(
-                requestLegacyExternalStorage, targetSdkVersion < Build.VERSION_CODES.Q);
-
         return input.success(
                 new ApkLite(codePath, packageSplit.first, packageSplit.second, isFeatureSplit,
                         configForSplit, usesSplitName, isSplitRequired, versionCode,
@@ -641,9 +614,7 @@
                         overlayIsStatic, overlayPriority, requiredSystemPropertyName,
                         requiredSystemPropertyValue, minSdkVersion, targetSdkVersion,
                         rollbackDataPolicy, requiredSplitTypes.first, requiredSplitTypes.second,
-                        hasDeviceAdminReceiver, isSdkLibrary, clearUserDataAllowed, backupAllowed,
-                        defaultToDeviceProtectedStorage, isRequestLegacyExternalStorage,
-                        userDataFragile, clearUserDataOnFailedRestoreAllowed));
+                        hasDeviceAdminReceiver, isSdkLibrary));
     }
 
     private static boolean isDeviceAdminReceiver(
diff --git a/core/java/android/content/pm/parsing/PackageLite.java b/core/java/android/content/pm/parsing/PackageLite.java
index ccef9de..116dd1f 100644
--- a/core/java/android/content/pm/parsing/PackageLite.java
+++ b/core/java/android/content/pm/parsing/PackageLite.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.content.pm.ArchivedPackageParcel;
 import android.content.pm.PackageInfo;
 import android.content.pm.SigningDetails;
 import android.content.pm.VerifierInfo;
@@ -112,29 +113,11 @@
      * Indicates if this package is a sdk.
      */
     private final boolean mIsSdkLibrary;
+
     /**
-     *  Set to <code>false</code> if the application does not wish to permit any OS-driven
-     *  backups of its data; <code>true</code> otherwise.
+     * Archival install info.
      */
-    private final boolean mBackupAllowed;
-    /**
-     * When set, the default data storage directory for this app is pointed at
-     * the device-protected location.
-     */
-    private final boolean mDefaultToDeviceProtectedStorage;
-    /**
-     * If {@code true} this app requests full external storage access.
-     */
-    private final boolean mRequestLegacyExternalStorage;
-    /**
-     * Indicates whether this application has declared its user data as fragile, causing the
-     * system to prompt the user on whether to keep the user data on uninstall.
-     */
-    private final boolean mUserDataFragile;
-    /**
-     * Indicates whether this application's data will be cleared on a failed restore.
-     */
-    private final boolean mClearUserDataOnFailedRestoreAllowed;
+    private final @Nullable ArchivedPackageParcel mArchivedPackage;
 
     public PackageLite(String path, String baseApkPath, ApkLite baseApk,
             String[] splitNames, boolean[] isFeatureSplits, String[] usesSplitNames,
@@ -171,11 +154,7 @@
         mSplitApkPaths = splitApkPaths;
         mSplitRevisionCodes = splitRevisionCodes;
         mTargetSdk = targetSdk;
-        mBackupAllowed = baseApk.isBackupAllowed();
-        mDefaultToDeviceProtectedStorage = baseApk.isDefaultToDeviceProtectedStorage();
-        mRequestLegacyExternalStorage = baseApk.isRequestLegacyExternalStorage();
-        mUserDataFragile = baseApk.isUserDataFragile();
-        mClearUserDataOnFailedRestoreAllowed = baseApk.isClearUserDataOnFailedRestoreAllowed();
+        mArchivedPackage = baseApk.getArchivedPackage();
     }
 
     /**
@@ -455,53 +434,18 @@
     }
 
     /**
-     *  Set to <code>false</code> if the application does not wish to permit any OS-driven
-     *  backups of its data; <code>true</code> otherwise.
+     * Archival install info.
      */
     @DataClass.Generated.Member
-    public boolean isBackupAllowed() {
-        return mBackupAllowed;
-    }
-
-    /**
-     * When set, the default data storage directory for this app is pointed at
-     * the device-protected location.
-     */
-    @DataClass.Generated.Member
-    public boolean isDefaultToDeviceProtectedStorage() {
-        return mDefaultToDeviceProtectedStorage;
-    }
-
-    /**
-     * If {@code true} this app requests full external storage access.
-     */
-    @DataClass.Generated.Member
-    public boolean isRequestLegacyExternalStorage() {
-        return mRequestLegacyExternalStorage;
-    }
-
-    /**
-     * Indicates whether this application has declared its user data as fragile, causing the
-     * system to prompt the user on whether to keep the user data on uninstall.
-     */
-    @DataClass.Generated.Member
-    public boolean isUserDataFragile() {
-        return mUserDataFragile;
-    }
-
-    /**
-     * Indicates whether this application's data will be cleared on a failed restore.
-     */
-    @DataClass.Generated.Member
-    public boolean isClearUserDataOnFailedRestoreAllowed() {
-        return mClearUserDataOnFailedRestoreAllowed;
+    public @Nullable ArchivedPackageParcel getArchivedPackage() {
+        return mArchivedPackage;
     }
 
     @DataClass.Generated(
-            time = 1693513525097L,
+            time = 1694792176268L,
             codegenVersion = "1.0.23",
             sourceFile = "frameworks/base/core/java/android/content/pm/parsing/PackageLite.java",
-            inputSignatures = "private final @android.annotation.NonNull java.lang.String mPackageName\nprivate final @android.annotation.NonNull java.lang.String mPath\nprivate final @android.annotation.NonNull java.lang.String mBaseApkPath\nprivate final @android.annotation.Nullable java.lang.String[] mSplitApkPaths\nprivate final @android.annotation.Nullable java.lang.String[] mSplitNames\nprivate final @android.annotation.Nullable java.lang.String[] mUsesSplitNames\nprivate final @android.annotation.Nullable java.lang.String[] mConfigForSplit\nprivate final @android.annotation.Nullable java.util.Set<java.lang.String> mBaseRequiredSplitTypes\nprivate final @android.annotation.Nullable java.util.Set<java.lang.String>[] mRequiredSplitTypes\nprivate final @android.annotation.Nullable java.util.Set<java.lang.String>[] mSplitTypes\nprivate final  int mVersionCodeMajor\nprivate final  int mVersionCode\nprivate final  int mTargetSdk\nprivate final  int mBaseRevisionCode\nprivate final @android.annotation.Nullable int[] mSplitRevisionCodes\nprivate final  int mInstallLocation\nprivate final @android.annotation.NonNull android.content.pm.VerifierInfo[] mVerifiers\nprivate final @android.annotation.NonNull android.content.pm.SigningDetails mSigningDetails\nprivate final @android.annotation.Nullable boolean[] mIsFeatureSplits\nprivate final  boolean mIsolatedSplits\nprivate final  boolean mSplitRequired\nprivate final  boolean mCoreApp\nprivate final  boolean mDebuggable\nprivate final  boolean mMultiArch\nprivate final  boolean mUse32bitAbi\nprivate final  boolean mExtractNativeLibs\nprivate final  boolean mProfileableByShell\nprivate final  boolean mUseEmbeddedDex\nprivate final  boolean mIsSdkLibrary\nprivate final  boolean mBackupAllowed\nprivate final  boolean mDefaultToDeviceProtectedStorage\nprivate final  boolean mRequestLegacyExternalStorage\nprivate final  boolean mUserDataFragile\nprivate final  boolean mClearUserDataOnFailedRestoreAllowed\npublic  java.util.List<java.lang.String> getAllApkPaths()\npublic  long getLongVersionCode()\nprivate  boolean hasAnyRequiredSplitTypes()\nclass PackageLite extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genConstructor=false, genConstDefs=false)")
+            inputSignatures = "private final @android.annotation.NonNull java.lang.String mPackageName\nprivate final @android.annotation.NonNull java.lang.String mPath\nprivate final @android.annotation.NonNull java.lang.String mBaseApkPath\nprivate final @android.annotation.Nullable java.lang.String[] mSplitApkPaths\nprivate final @android.annotation.Nullable java.lang.String[] mSplitNames\nprivate final @android.annotation.Nullable java.lang.String[] mUsesSplitNames\nprivate final @android.annotation.Nullable java.lang.String[] mConfigForSplit\nprivate final @android.annotation.Nullable java.util.Set<java.lang.String> mBaseRequiredSplitTypes\nprivate final @android.annotation.Nullable java.util.Set<java.lang.String>[] mRequiredSplitTypes\nprivate final @android.annotation.Nullable java.util.Set<java.lang.String>[] mSplitTypes\nprivate final  int mVersionCodeMajor\nprivate final  int mVersionCode\nprivate final  int mTargetSdk\nprivate final  int mBaseRevisionCode\nprivate final @android.annotation.Nullable int[] mSplitRevisionCodes\nprivate final  int mInstallLocation\nprivate final @android.annotation.NonNull android.content.pm.VerifierInfo[] mVerifiers\nprivate final @android.annotation.NonNull android.content.pm.SigningDetails mSigningDetails\nprivate final @android.annotation.Nullable boolean[] mIsFeatureSplits\nprivate final  boolean mIsolatedSplits\nprivate final  boolean mSplitRequired\nprivate final  boolean mCoreApp\nprivate final  boolean mDebuggable\nprivate final  boolean mMultiArch\nprivate final  boolean mUse32bitAbi\nprivate final  boolean mExtractNativeLibs\nprivate final  boolean mProfileableByShell\nprivate final  boolean mUseEmbeddedDex\nprivate final  boolean mIsSdkLibrary\nprivate final @android.annotation.Nullable android.content.pm.ArchivedPackageParcel mArchivedPackage\npublic  java.util.List<java.lang.String> getAllApkPaths()\npublic  long getLongVersionCode()\nprivate  boolean hasAnyRequiredSplitTypes()\nclass PackageLite extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genConstructor=false, genConstDefs=false)")
     @Deprecated
     private void __metadata() {}
 
diff --git a/core/java/android/content/res/OWNERS b/core/java/android/content/res/OWNERS
index a7bce12..141d58d 100644
--- a/core/java/android/content/res/OWNERS
+++ b/core/java/android/content/res/OWNERS
@@ -1,8 +1,7 @@
 # Bug component: 568761
 
-toddke@android.com
-toddke@google.com
 patb@google.com
 zyy@google.com
+branliu@google.com
 
 per-file FontScaleConverter*=fuego@google.com
\ No newline at end of file
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 85d7c10..fe515cd 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -4437,7 +4437,7 @@
      * @param drawingPosition the drawing order position.
      * @return the container position of a child for this drawing order position.
      *
-     * @see #getChildDrawingOrder(int, int)}
+     * @see #getChildDrawingOrder(int, int)
      */
     public final int getChildDrawingOrder(int drawingPosition) {
         return getChildDrawingOrder(getChildCount(), drawingPosition);
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 59344b0..05063365 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -15143,6 +15143,9 @@
 
         final ClipDescription description =
                 getClipboardManagerForUser().getPrimaryClipDescription();
+        if (description == null) {
+            return false;
+        }
         final boolean isPlainType = description.hasMimeType(ClipDescription.MIMETYPE_TEXT_PLAIN);
         return (isPlainType && description.isStyledText())
                 || description.hasMimeType(ClipDescription.MIMETYPE_TEXT_HTML);
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index d000b23..c09f0a3 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -7663,6 +7663,10 @@
     <permission android:name="android.permission.DELETE_STAGED_HEALTH_CONNECT_REMOTE_DATA"
                 android:protectionLevel="signature" />
 
+    <!-- @hide @TestApi Allows tests running in CTS-in-sandbox mode to launch activities -->
+    <permission android:name="android.permission.START_ACTIVITIES_FROM_SDK_SANDBOX"
+                android:protectionLevel="signature" />
+
     <!-- @SystemApi Allows the holder to call health connect migration APIs.
         @hide -->
     <permission android:name="android.permission.MIGRATE_HEALTH_CONNECT_DATA"
diff --git a/core/tests/coretests/src/android/content/pm/RegisteredServicesCacheTest.java b/core/tests/coretests/src/android/content/pm/RegisteredServicesCacheTest.java
index 5553902..37ef6cb 100644
--- a/core/tests/coretests/src/android/content/pm/RegisteredServicesCacheTest.java
+++ b/core/tests/coretests/src/android/content/pm/RegisteredServicesCacheTest.java
@@ -85,9 +85,11 @@
         assertEquals(2, cache.getAllServicesSize(U0));
         assertEquals(2, cache.getPersistentServicesSize(U0));
         assertNotEmptyFileCreated(cache, U0);
+        cache.unregisterReceivers();
         // Make sure all services can be loaded from xml
         cache = new TestServicesCache();
         assertEquals(2, cache.getPersistentServicesSize(U0));
+        cache.unregisterReceivers();
     }
 
     public void testGetAllServicesReplaceUid() {
@@ -110,6 +112,7 @@
         assertTrue("UID must be updated to the new value",
                 uids.contains(SYSTEM_IMAGE_UID));
         assertFalse("UID must be updated to the new value", uids.contains(UID2));
+        cache.unregisterReceivers();
     }
 
     public void testGetAllServicesServiceRemoved() {
@@ -118,6 +121,7 @@
         cache.addServiceForQuerying(U0, r2, newServiceInfo(t2, UID2));
         assertEquals(2, cache.getAllServicesSize(U0));
         assertEquals(2, cache.getPersistentServicesSize(U0));
+        cache.unregisterReceivers();
         // Re-read data from disk and verify services were saved
         cache = new TestServicesCache();
         assertEquals(2, cache.getPersistentServicesSize(U0));
@@ -125,6 +129,7 @@
         cache.addServiceForQuerying(U0, r1, newServiceInfo(t1, UID1));
         assertEquals(1, cache.getAllServicesSize(U0));
         assertEquals(1, cache.getPersistentServicesSize(U0));
+        cache.unregisterReceivers();
     }
 
     public void testGetAllServicesMultiUser() {
@@ -137,12 +142,14 @@
         assertEquals(1, cache.getAllServicesSize(U1));
         assertEquals(1, cache.getPersistentServicesSize(U1));
         assertEquals("No services should be available for user 3", 0, cache.getAllServicesSize(3));
+        cache.unregisterReceivers();
         // Re-read data from disk and verify services were saved
         cache = new TestServicesCache();
         assertEquals(1, cache.getPersistentServicesSize(U0));
         assertEquals(1, cache.getPersistentServicesSize(U1));
         assertNotEmptyFileCreated(cache, U0);
         assertNotEmptyFileCreated(cache, U1);
+        cache.unregisterReceivers();
     }
 
     public void testOnRemove() {
@@ -158,6 +165,7 @@
         cache.clearServicesForQuerying();
         assertEquals(1, cache.getAllServicesSize(U0));
         assertEquals(0, cache.getAllServicesSize(U1));
+        cache.unregisterReceivers();
     }
 
     public void testMigration() {
@@ -186,10 +194,12 @@
         cache.addServiceForQuerying(0, r2, newServiceInfo(t2, 2));
         assertEquals(2, cache.getAllServicesSize(u0));
         assertEquals(0, cache.getAllServicesSize(u1));
+        cache.unregisterReceivers();
         // Re-read data from disk. Verify that services were saved and old file was ignored
         cache = new TestServicesCache();
         assertEquals(2, cache.getPersistentServicesSize(u0));
         assertEquals(0, cache.getPersistentServicesSize(u1));
+        cache.unregisterReceivers();
     }
 
     private static RegisteredServicesCache.ServiceInfo<TestServiceType> newServiceInfo(
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreECDSASignatureSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreECDSASignatureSpi.java
index ace2053..9d3fca8 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreECDSASignatureSpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreECDSASignatureSpi.java
@@ -195,7 +195,7 @@
     protected final void initKey(AndroidKeyStoreKey key) throws InvalidKeyException {
         if (!ACCEPTED_SIGNING_SCHEMES.contains(key.getAlgorithm().toLowerCase())) {
             throw new InvalidKeyException("Unsupported key algorithm: " + key.getAlgorithm()
-                    + ". Only" + Arrays.toString(ACCEPTED_SIGNING_SCHEMES.stream().toArray())
+                    + ". Only " + Arrays.toString(ACCEPTED_SIGNING_SCHEMES.stream().toArray())
                     + " supported");
         }
 
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreRSASignatureSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreRSASignatureSpi.java
index 931c2f8..d5fb49a 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreRSASignatureSpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreRSASignatureSpi.java
@@ -189,7 +189,7 @@
     protected final void initKey(AndroidKeyStoreKey key) throws InvalidKeyException {
         if (!KeyProperties.KEY_ALGORITHM_RSA.equalsIgnoreCase(key.getAlgorithm())) {
             throw new InvalidKeyException("Unsupported key algorithm: " + key.getAlgorithm()
-                    + ". Only" + KeyProperties.KEY_ALGORITHM_RSA + " supported");
+                    + ". Only " + KeyProperties.KEY_ALGORITHM_RSA + " supported");
         }
         super.initKey(key);
     }
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/area/WindowAreaComponentImpl.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/area/WindowAreaComponentImpl.java
index 0112e32..15d14e8 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/area/WindowAreaComponentImpl.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/area/WindowAreaComponentImpl.java
@@ -213,9 +213,6 @@
             if (mRearDisplayStateRequest != null || isRearDisplayActive()) {
                 mRearDisplayStateRequest = null;
                 mDeviceStateManager.cancelStateRequest();
-            } else {
-                throw new IllegalStateException(
-                        "Unable to cancel a rear display session as there is no active session");
             }
         }
     }
@@ -432,10 +429,6 @@
         synchronized (mLock) {
             if (mRearDisplayPresentationController != null) {
                 mDeviceStateManager.cancelStateRequest();
-            } else {
-                throw new IllegalStateException(
-                        "Unable to cancel a rear display presentation session as there is no "
-                                + "active session");
             }
         }
     }
diff --git a/libs/androidfw/OWNERS b/libs/androidfw/OWNERS
index 436f107..ef4cc46 100644
--- a/libs/androidfw/OWNERS
+++ b/libs/androidfw/OWNERS
@@ -1,5 +1,4 @@
 set noparent
-toddke@google.com
 zyy@google.com
 patb@google.com
 
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index d267d80..15620b7 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -853,6 +853,9 @@
     <!-- Permission required for accessing all content provider mime types -->
     <uses-permission android:name="android.permission.GET_ANY_PROVIDER_TYPE" />
 
+    <!-- Permission required for CTS-in-sandbox tests -->
+    <uses-permission android:name="android.permission.START_ACTIVITIES_FROM_SDK_SANDBOX" />
+
     <!-- Permission required for CTS test - CtsWallpaperTestCases -->
     <uses-permission android:name="android.permission.ALWAYS_UPDATE_WALLPAPER" />
 
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index ba1f84a..4c70db8 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -15877,7 +15877,15 @@
         activeInstr.mWatcher = watcher;
         activeInstr.mUiAutomationConnection = uiAutomationConnection;
         activeInstr.mResultClass = className;
-        activeInstr.mHasBackgroundActivityStartsPermission = false;
+        activeInstr.mHasBackgroundActivityStartsPermission =
+                isSdkInSandbox
+                        // TODO(b/261864298): consider using START_ACTIVITIES_FROM_BACKGROUND.
+                        && checkPermission(
+                                        android.Manifest.permission
+                                                .START_ACTIVITIES_FROM_SDK_SANDBOX,
+                                        Binder.getCallingPid(),
+                                        Binder.getCallingUid())
+                                == PackageManager.PERMISSION_GRANTED;
         activeInstr.mHasBackgroundForegroundServiceStartsPermission = false;
         // Instrumenting sdk sandbox without a restart is not supported
         activeInstr.mNoRestart = false;
diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java
index 2ee0706..e1e5e6d 100644
--- a/services/core/java/com/android/server/pm/InstallPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java
@@ -44,6 +44,7 @@
 import static android.os.storage.StorageManager.FLAG_STORAGE_CE;
 import static android.os.storage.StorageManager.FLAG_STORAGE_DE;
 import static android.os.storage.StorageManager.FLAG_STORAGE_EXTERNAL;
+
 import static com.android.server.pm.DexOptHelper.useArtService;
 import static com.android.server.pm.InstructionSets.getAppDexInstructionSets;
 import static com.android.server.pm.InstructionSets.getDexCodeInstructionSet;
@@ -111,6 +112,7 @@
 import android.content.IntentFilter;
 import android.content.IntentSender;
 import android.content.pm.ApplicationInfo;
+import android.content.pm.ArchivedPackageParcel;
 import android.content.pm.DataLoaderType;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageInfoLite;
@@ -1142,15 +1144,18 @@
 
         Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parsePackage");
         final ParsedPackage parsedPackage;
+        final ArchivedPackageParcel archivedPackage;
         try (PackageParser2 pp = mPm.mInjector.getPreparingPackageParser()) {
             if (request.getPackageLite() == null || !request.isArchived()) {
                 // TODO: pass packageLite from install request instead of reparsing the package
                 parsedPackage = pp.parsePackage(tmpPackageFile, parseFlags, false);
                 AndroidPackageUtils.validatePackageDexMetadata(parsedPackage);
+                archivedPackage = null;
             } else {
                 // Archived install mode, no APK.
                 parsedPackage = pp.parsePackageFromPackageLite(request.getPackageLite(),
                         parseFlags);
+                archivedPackage = request.getPackageLite().getArchivedPackage();
             }
         } catch (PackageManagerException e) {
             throw new PrepareFailure("Failed parse during installPackageLI", e);
@@ -1833,7 +1838,7 @@
             shouldCloseFreezerBeforeReturn = false;
 
             request.setPrepareResult(replace, targetScanFlags, targetParseFlags,
-                    oldPackageState, parsedPackage,
+                    oldPackageState, parsedPackage, archivedPackage,
                     replace /* clearCodeCache */, sysPkg, ps, disabledPs);
         } finally {
             request.setFreezer(freezer);
@@ -2164,6 +2169,9 @@
                 }
             }
             if (installRequest.getReturnCode() == PackageManager.INSTALL_SUCCEEDED) {
+                mPm.createArchiveStateIfNeeded(ps,
+                        installRequest.getArchivedPackage(),
+                        installRequest.getNewUsers());
                 mPm.updateSequenceNumberLP(ps, installRequest.getNewUsers());
                 mPm.updateInstantAppInstallerLocked(packageName);
             }
diff --git a/services/core/java/com/android/server/pm/InstallRequest.java b/services/core/java/com/android/server/pm/InstallRequest.java
index 3a6d423..ff347ac 100644
--- a/services/core/java/com/android/server/pm/InstallRequest.java
+++ b/services/core/java/com/android/server/pm/InstallRequest.java
@@ -21,6 +21,7 @@
 import static android.content.pm.PackageManager.INSTALL_SCENARIO_DEFAULT;
 import static android.content.pm.PackageManager.INSTALL_SUCCEEDED;
 import static android.os.Process.INVALID_UID;
+
 import static com.android.server.pm.PackageManagerService.EMPTY_INT_ARRAY;
 import static com.android.server.pm.PackageManagerService.SCAN_AS_INSTANT_APP;
 import static com.android.server.pm.PackageManagerService.TAG;
@@ -29,6 +30,7 @@
 import android.annotation.Nullable;
 import android.apex.ApexInfo;
 import android.app.AppOpsManager;
+import android.content.pm.ArchivedPackageParcel;
 import android.content.pm.DataLoaderType;
 import android.content.pm.IPackageInstallObserver2;
 import android.content.pm.PackageInstaller;
@@ -77,6 +79,8 @@
     /** parsed package to be scanned */
     @Nullable
     private ParsedPackage mParsedPackage;
+    @Nullable
+    private ArchivedPackageParcel mArchivedPackage;
     private boolean mClearCodeCache;
     private boolean mSystem;
     @Nullable
@@ -189,6 +193,7 @@
         }
         mInstallArgs = null;
         mParsedPackage = parsedPackage;
+        mArchivedPackage = null;
         mParseFlags = parseFlags;
         mScanFlags = scanFlags;
         mScanResult = scanResult;
@@ -448,6 +453,9 @@
         return mParsedPackage;
     }
 
+    @Nullable
+    public ArchivedPackageParcel getArchivedPackage() { return mArchivedPackage; }
+
     @ParsingPackageUtils.ParseFlags
     public int getParseFlags() {
         return mParseFlags;
@@ -753,7 +761,8 @@
 
     public void setPrepareResult(boolean replace, int scanFlags,
             int parseFlags, PackageState existingPackageState,
-            ParsedPackage packageToScan, boolean clearCodeCache, boolean system,
+            ParsedPackage packageToScan, ArchivedPackageParcel archivedPackage,
+            boolean clearCodeCache, boolean system,
             PackageSetting originalPs, PackageSetting disabledPs) {
         mReplace = replace;
         mScanFlags = scanFlags;
@@ -761,6 +770,7 @@
         mExistingPackageName =
                 existingPackageState != null ? existingPackageState.getPackageName() : null;
         mParsedPackage = packageToScan;
+        mArchivedPackage = archivedPackage;
         mClearCodeCache = clearCodeCache;
         mSystem = system;
         mOriginalPs = originalPs;
diff --git a/services/core/java/com/android/server/pm/PackageArchiver.java b/services/core/java/com/android/server/pm/PackageArchiver.java
index 64cdca3..551b1ae 100644
--- a/services/core/java/com/android/server/pm/PackageArchiver.java
+++ b/services/core/java/com/android/server/pm/PackageArchiver.java
@@ -31,12 +31,15 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentSender;
+import android.content.pm.ArchivedActivityParcel;
+import android.content.pm.ArchivedPackageParcel;
 import android.content.pm.LauncherActivityInfo;
 import android.content.pm.LauncherApps;
 import android.content.pm.PackageInstaller;
 import android.content.pm.PackageManager;
 import android.content.pm.VersionedPackage;
 import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
 import android.graphics.Canvas;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
@@ -56,6 +59,7 @@
 import com.android.server.pm.pkg.PackageStateInternal;
 import com.android.server.pm.pkg.PackageUserStateInternal;
 
+import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
@@ -158,7 +162,8 @@
         String responsibleInstallerPackage = getResponsibleInstallerPackage(ps);
         verifyInstaller(responsibleInstallerPackage);
 
-        List<LauncherActivityInfo> mainActivities = getLauncherActivityInfos(ps, userId);
+        List<LauncherActivityInfo> mainActivities = getLauncherActivityInfos(ps.getPackageName(),
+                userId);
         final CompletableFuture<ArchiveState> archiveState = new CompletableFuture<>();
         mPm.mHandler.post(() -> {
             try {
@@ -172,13 +177,34 @@
         return archiveState;
     }
 
-    private ArchiveState createArchiveStateInternal(String packageName, int userId,
+    static ArchiveState createArchiveState(@NonNull ArchivedPackageParcel archivedPackage,
+            int userId, String installerPackage) {
+        try {
+            var packageName = archivedPackage.packageName;
+            var mainActivities = archivedPackage.archivedActivities;
+            List<ArchiveActivityInfo> archiveActivityInfos = new ArrayList<>(mainActivities.length);
+            for (int i = 0, size = mainActivities.length; i < size; ++i) {
+                var mainActivity = mainActivities[i];
+                Path iconPath = storeIconForParcel(packageName, mainActivity, userId, i);
+                ArchiveActivityInfo activityInfo = new ArchiveActivityInfo(
+                        mainActivity.title, iconPath, null);
+                archiveActivityInfos.add(activityInfo);
+            }
+
+            return new ArchiveState(archiveActivityInfos, installerPackage);
+        } catch (IOException e) {
+            Slog.e(TAG, "Failed to create archive state", e);
+            return null;
+        }
+    }
+
+    ArchiveState createArchiveStateInternal(String packageName, int userId,
             List<LauncherActivityInfo> mainActivities, String installerPackage)
             throws IOException {
-        List<ArchiveActivityInfo> archiveActivityInfos = new ArrayList<>();
-        for (int i = 0; i < mainActivities.size(); i++) {
+        List<ArchiveActivityInfo> archiveActivityInfos = new ArrayList<>(mainActivities.size());
+        for (int i = 0, size = mainActivities.size(); i < size; i++) {
             LauncherActivityInfo mainActivity = mainActivities.get(i);
-            Path iconPath = storeIcon(packageName, mainActivity, userId);
+            Path iconPath = storeIcon(packageName, mainActivity, userId, i);
             ArchiveActivityInfo activityInfo = new ArchiveActivityInfo(
                     mainActivity.getLabel().toString(), iconPath, null);
             archiveActivityInfos.add(activityInfo);
@@ -188,17 +214,30 @@
     }
 
     // TODO(b/298452477) Handle monochrome icons.
+    private static Path storeIconForParcel(String packageName, ArchivedActivityParcel mainActivity,
+            @UserIdInt int userId, int index) throws IOException {
+        if (mainActivity.iconBitmap == null) {
+            return null;
+        }
+        File iconsDir = createIconsDir(userId);
+        File iconFile = new File(iconsDir, packageName + "-" + index + ".png");
+        try (FileOutputStream out = new FileOutputStream(iconFile)) {
+            out.write(mainActivity.iconBitmap);
+            out.flush();
+        }
+        return iconFile.toPath();
+    }
+
     @VisibleForTesting
     Path storeIcon(String packageName, LauncherActivityInfo mainActivity,
-            @UserIdInt int userId)
-            throws IOException {
+            @UserIdInt int userId, int index) throws IOException {
         int iconResourceId = mainActivity.getActivityInfo().getIconResource();
         if (iconResourceId == 0) {
             // The app doesn't define an icon. No need to store anything.
             return null;
         }
         File iconsDir = createIconsDir(userId);
-        File iconFile = new File(iconsDir, packageName + "-" + mainActivity.getName() + ".png");
+        File iconFile = new File(iconsDir, packageName + "-" + index + ".png");
         Bitmap icon = drawableToBitmap(mainActivity.getIcon(/* density= */ 0));
         try (FileOutputStream out = new FileOutputStream(iconFile)) {
             // Note: Quality is ignored for PNGs.
@@ -228,6 +267,9 @@
      */
     public boolean verifySupportsUnarchival(String installerPackage) {
         // TODO(b/278553670) Check if installerPackage supports unarchival.
+        if (TextUtils.isEmpty(installerPackage)) {
+            return false;
+        }
         return true;
     }
 
@@ -310,16 +352,16 @@
                 /* initialExtras= */ null);
     }
 
-    private List<LauncherActivityInfo> getLauncherActivityInfos(PackageStateInternal ps,
+    List<LauncherActivityInfo> getLauncherActivityInfos(String packageName,
             int userId) throws PackageManager.NameNotFoundException {
         List<LauncherActivityInfo> mainActivities =
                 Binder.withCleanCallingIdentity(() -> getLauncherApps().getActivityList(
-                        ps.getPackageName(),
+                        packageName,
                         new UserHandle(userId)));
         if (mainActivities.isEmpty()) {
             throw new PackageManager.NameNotFoundException(
                     TextUtils.formatSimple("The app %s does not have a main activity.",
-                            ps.getPackageName()));
+                            packageName));
         }
 
         return mainActivities;
@@ -340,7 +382,7 @@
         return DEFAULT_UNARCHIVE_FOREGROUND_TIMEOUT_MS;
     }
 
-    private String getResponsibleInstallerPackage(PackageStateInternal ps) {
+    static String getResponsibleInstallerPackage(PackageStateInternal ps) {
         return TextUtils.isEmpty(ps.getInstallSource().mUpdateOwnerPackageName)
                 ? ps.getInstallSource().mInstallerPackageName
                 : ps.getInstallSource().mUpdateOwnerPackageName;
@@ -423,7 +465,7 @@
         }
     }
 
-    private File createIconsDir(@UserIdInt int userId) throws IOException {
+    private static File createIconsDir(@UserIdInt int userId) throws IOException {
         File iconsDir = getIconsDir(userId);
         if (!iconsDir.isDirectory()) {
             iconsDir.delete();
@@ -436,7 +478,7 @@
         return iconsDir;
     }
 
-    private File getIconsDir(int userId) {
+    private static File getIconsDir(int userId) {
         return new File(Environment.getDataSystemCeDirectory(userId), ARCHIVE_ICONS_DIR);
     }
 
@@ -462,4 +504,90 @@
         drawable.draw(canvas);
         return bitmap;
     }
+
+    private static byte[] bytesFromBitmapFile(Path path) throws IOException {
+        if (path == null) {
+            return null;
+        }
+        // Technically we could just read the bytes, but we want to be sure we store the
+        // right format.
+        return bytesFromBitmap(BitmapFactory.decodeFile(path.toString()));
+    }
+
+    private static byte[] bytesFromBitmap(Bitmap bitmap) throws IOException {
+        if (bitmap == null) {
+            return null;
+        }
+
+        try (ByteArrayOutputStream baos = new ByteArrayOutputStream(
+                bitmap.getByteCount())) {
+            bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);
+            return baos.toByteArray();
+        }
+    }
+
+    /**
+     * Creates serializable archived activities from existing ArchiveState.
+     */
+    static ArchivedActivityParcel[] createArchivedActivities(ArchiveState archiveState)
+            throws IOException {
+        var infos = archiveState.getActivityInfos();
+        if (infos == null || infos.isEmpty()) {
+            throw new IllegalArgumentException("No activities in archive state");
+        }
+
+        List<ArchivedActivityParcel> activities = new ArrayList<>(infos.size());
+        for (int i = 0, size = infos.size(); i < size; ++i) {
+            var info = infos.get(i);
+            if (info == null) {
+                continue;
+            }
+            var archivedActivity = new ArchivedActivityParcel();
+            archivedActivity.title = info.getTitle();
+            archivedActivity.iconBitmap = bytesFromBitmapFile(info.getIconBitmap());
+            archivedActivity.monochromeIconBitmap = bytesFromBitmapFile(
+                    info.getMonochromeIconBitmap());
+            activities.add(archivedActivity);
+        }
+
+        if (activities.isEmpty()) {
+            throw new IllegalArgumentException(
+                    "Failed to extract title and icon of main activities");
+        }
+
+        return activities.toArray(new ArchivedActivityParcel[activities.size()]);
+    }
+
+    /**
+     * Creates serializable archived activities from launcher activities.
+     */
+    static ArchivedActivityParcel[] createArchivedActivities(List<LauncherActivityInfo> infos)
+            throws IOException {
+        if (infos == null || infos.isEmpty()) {
+            throw new IllegalArgumentException("No launcher activities");
+        }
+
+        List<ArchivedActivityParcel> activities = new ArrayList<>(infos.size());
+        for (int i = 0, size = infos.size(); i < size; ++i) {
+            var info = infos.get(i);
+            if (info == null) {
+                continue;
+            }
+            var archivedActivity = new ArchivedActivityParcel();
+            archivedActivity.title = info.getLabel().toString();
+            archivedActivity.iconBitmap =
+                    info.getActivityInfo().getIconResource() == 0 ? null : bytesFromBitmap(
+                            drawableToBitmap(info.getIcon(/* density= */ 0)));
+            // TODO(b/298452477) Handle monochrome icons.
+            archivedActivity.monochromeIconBitmap = null;
+            activities.add(archivedActivity);
+        }
+
+        if (activities.isEmpty()) {
+            throw new IllegalArgumentException(
+                    "Failed to extract title and icon of main activities");
+        }
+
+        return activities.toArray(new ArchivedActivityParcel[activities.size()]);
+    }
 }
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 2e9da09..512d338 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -40,6 +40,7 @@
 import static android.system.OsConstants.O_CREAT;
 import static android.system.OsConstants.O_RDONLY;
 import static android.system.OsConstants.O_WRONLY;
+
 import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE;
 import static com.android.internal.util.XmlUtils.readBitmapAttribute;
 import static com.android.internal.util.XmlUtils.readByteArrayAttribute;
@@ -1165,11 +1166,6 @@
                 throw new IllegalArgumentException(
                         "Archived installation can only use Streaming System DataLoader.");
             }
-            if (!TextUtils.isEmpty(params.appPackageName) && !isArchivedInstallationAllowed(
-                    params.appPackageName)) {
-                throw new IllegalArgumentException(
-                        "Archived installation of this package is not allowed.");
-            }
         }
     }
 
@@ -1548,6 +1544,10 @@
             }
 
             var archPkg = metadata.getArchivedPackage();
+            if (archPkg == null) {
+                throw new PackageManagerException(INSTALL_FAILED_VERIFICATION_FAILURE,
+                        "Metadata does not contain ArchivedPackage: " + file);
+            }
             if (archPkg.packageName == null || archPkg.signingDetails == null) {
                 throw new PackageManagerException(INSTALL_FAILED_VERIFICATION_FAILURE,
                         "ArchivedPackage does not contain required info: " + file);
@@ -3395,8 +3395,7 @@
                         "Archived installation of this package is not allowed.");
             }
 
-            if (!isInstalledByAdb(getInstallSource().mInitiatingPackageName)
-                    && !mPm.mInstallerService.mPackageArchiver.verifySupportsUnarchival(
+            if (!mPm.mInstallerService.mPackageArchiver.verifySupportsUnarchival(
                     getInstallSource().mInstallerPackageName)) {
                 throw new PackageManagerException(
                         PackageManager.INSTALL_FAILED_SESSION_INVALID,
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index d23dcbc..b5b6ce0 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -36,6 +36,7 @@
 import static android.os.storage.StorageManager.FLAG_STORAGE_DE;
 import static android.os.storage.StorageManager.FLAG_STORAGE_EXTERNAL;
 import static android.provider.DeviceConfig.NAMESPACE_PACKAGE_MANAGER_SERVICE;
+
 import static com.android.internal.annotations.VisibleForTesting.Visibility;
 import static com.android.internal.util.FrameworkStatsLog.BOOT_TIME_EVENT_DURATION__EVENT__OTA_PACKAGE_MANAGER_INIT_TIME;
 import static com.android.server.pm.DexOptHelper.useArtService;
@@ -116,11 +117,7 @@
 import android.content.pm.VerifierDeviceIdentity;
 import android.content.pm.VersionedPackage;
 import android.content.pm.overlay.OverlayPaths;
-import android.content.pm.parsing.ApkLite;
-import android.content.pm.parsing.ApkLiteParseUtils;
 import android.content.pm.parsing.PackageLite;
-import android.content.pm.parsing.result.ParseResult;
-import android.content.pm.parsing.result.ParseTypeImpl;
 import android.content.res.Resources;
 import android.database.ContentObserver;
 import android.graphics.Bitmap;
@@ -228,6 +225,7 @@
 import com.android.server.pm.permission.PermissionManagerService;
 import com.android.server.pm.permission.PermissionManagerServiceInternal;
 import com.android.server.pm.pkg.AndroidPackage;
+import com.android.server.pm.pkg.ArchiveState;
 import com.android.server.pm.pkg.PackageState;
 import com.android.server.pm.pkg.PackageStateInternal;
 import com.android.server.pm.pkg.PackageUserState;
@@ -1438,6 +1436,92 @@
         return extras;
     }
 
+    ArchivedPackageParcel getArchivedPackageInternal(@NonNull String packageName, int userId) {
+        Objects.requireNonNull(packageName);
+        int binderUid = Binder.getCallingUid();
+
+        Computer snapshot = snapshotComputer();
+        snapshot.enforceCrossUserPermission(binderUid, userId, true, true,
+                "getArchivedPackage");
+
+        ArchivedPackageParcel archPkg = new ArchivedPackageParcel();
+        archPkg.packageName = packageName;
+
+        ArchiveState archiveState;
+        synchronized (mLock) {
+            PackageSetting ps = mSettings.getPackageLPr(packageName);
+            if (ps == null) {
+                return null;
+            }
+            var psi = ps.getUserStateOrDefault(userId);
+            archiveState = psi.getArchiveState();
+            if (archiveState == null && !psi.isInstalled()) {
+                return null;
+            }
+
+            archPkg.signingDetails = ps.getSigningDetails();
+
+            long longVersionCode = ps.getVersionCode();
+            archPkg.versionCodeMajor = (int) (longVersionCode >> 32);
+            archPkg.versionCode = (int) longVersionCode;
+
+            // TODO(b/297916136): extract target sdk version.
+            archPkg.targetSdkVersion = MIN_INSTALLABLE_TARGET_SDK;
+
+            // These get translated in flags important for user data management.
+            archPkg.defaultToDeviceProtectedStorage = String.valueOf(
+                    ps.isDefaultToDeviceProtectedStorage());
+            archPkg.requestLegacyExternalStorage = String.valueOf(
+                    ps.isRequestLegacyExternalStorage());
+            archPkg.userDataFragile = String.valueOf(ps.isUserDataFragile());
+        }
+
+        try {
+            if (archiveState != null) {
+                archPkg.archivedActivities = PackageArchiver.createArchivedActivities(
+                        archiveState);
+            } else {
+                var mainActivities =
+                        mInstallerService.mPackageArchiver.getLauncherActivityInfos(packageName,
+                                userId);
+                archPkg.archivedActivities = PackageArchiver.createArchivedActivities(
+                        mainActivities);
+            }
+        } catch (Exception e) {
+            throw new IllegalArgumentException("Package does not have a main activity", e);
+        }
+
+        return archPkg;
+    }
+
+    void createArchiveStateIfNeeded(PackageSetting pkgSetting, ArchivedPackageParcel archivePackage,
+            int[] userIds) {
+        if (pkgSetting == null || archivePackage == null
+                || archivePackage.archivedActivities == null || userIds == null
+                || userIds.length == 0) {
+            return;
+        }
+
+        String responsibleInstallerPackage = PackageArchiver.getResponsibleInstallerPackage(
+                pkgSetting);
+        // TODO(b/278553670) Check if responsibleInstallerPackage supports unarchival.
+        if (TextUtils.isEmpty(responsibleInstallerPackage)) {
+            Slog.e(TAG, "Can't create archive state: responsible installer is empty");
+            return;
+        }
+        for (int userId : userIds) {
+            var archiveState = PackageArchiver.createArchiveState(archivePackage, userId,
+                    responsibleInstallerPackage);
+            if (archiveState == null) {
+                continue;
+            }
+            pkgSetting
+                    .modifyUserState(userId)
+                    .setArchiveState(archiveState);
+        }
+    }
+
+
     void scheduleWriteSettings() {
         // We normally invalidate when we write settings, but in cases where we delay and
         // coalesce settings writes, this strategy would have us invalidate the cache too late.
@@ -6301,35 +6385,8 @@
         }
 
         @Override
-        public ArchivedPackageParcel getArchivedPackage(String apkPath) {
-            ParseTypeImpl input = ParseTypeImpl.forDefaultParsing();
-            ParseResult<ApkLite> result = ApkLiteParseUtils.parseApkLite(input.reset(),
-                    new File(apkPath), ParsingPackageUtils.PARSE_COLLECT_CERTIFICATES);
-            if (result.isError()) {
-                throw new IllegalArgumentException(result.getErrorMessage(), result.getException());
-            }
-            final ApkLite apk = result.getResult();
-
-            ArchivedPackageParcel archPkg = new ArchivedPackageParcel();
-            archPkg.packageName = apk.getPackageName();
-            archPkg.signingDetails = apk.getSigningDetails();
-
-            archPkg.versionCodeMajor = apk.getVersionCodeMajor();
-            archPkg.versionCode = apk.getVersionCode();
-
-            archPkg.targetSdkVersion = apk.getTargetSdkVersion();
-
-            // These get translated in flags important for user data management.
-            archPkg.backupAllowed = String.valueOf(apk.isBackupAllowed());
-            archPkg.defaultToDeviceProtectedStorage = String.valueOf(
-                    apk.isDefaultToDeviceProtectedStorage());
-            archPkg.requestLegacyExternalStorage = String.valueOf(
-                    apk.isRequestLegacyExternalStorage());
-            archPkg.userDataFragile = String.valueOf(apk.isUserDataFragile());
-            archPkg.clearUserDataOnFailedRestoreAllowed = String.valueOf(
-                    apk.isClearUserDataOnFailedRestoreAllowed());
-
-            return archPkg;
+        public ArchivedPackageParcel getArchivedPackage(@NonNull String packageName, int userId) {
+            return getArchivedPackageInternal(packageName, userId);
         }
 
         /**
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 8d82085..1b30c4b 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -26,6 +26,7 @@
 import static android.content.pm.PackageManager.RESTRICTION_HIDE_FROM_SUGGESTIONS;
 import static android.content.pm.PackageManager.RESTRICTION_HIDE_NOTIFICATIONS;
 import static android.content.pm.PackageManager.RESTRICTION_NONE;
+
 import static com.android.server.LocalManagerRegistry.ManagerNotFoundException;
 import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
 
@@ -82,9 +83,9 @@
 import android.os.Binder;
 import android.os.Build;
 import android.os.Bundle;
-import android.os.Environment;
 import android.os.IBinder;
 import android.os.IUserManager;
+import android.os.Parcel;
 import android.os.ParcelFileDescriptor;
 import android.os.ParcelFileDescriptor.AutoCloseInputStream;
 import android.os.PersistableBundle;
@@ -130,6 +131,7 @@
 
 import libcore.io.IoUtils;
 import libcore.io.Streams;
+import libcore.util.HexEncoding;
 
 import java.io.BufferedReader;
 import java.io.File;
@@ -248,8 +250,6 @@
                     return runStreamingInstall();
                 case "install-incremental":
                     return runIncrementalInstall();
-                case "install-archived":
-                    return runArchivedInstall();
                 case "install-abandon":
                 case "install-destroy":
                     return runInstallAbandon();
@@ -277,6 +277,10 @@
                     return runUninstall();
                 case "clear":
                     return runClear();
+                case "get-archived-package-metadata":
+                    return runGetArchivedPackageMetadata();
+                case "install-archived":
+                    return runArchivedInstall();
                 case "enable":
                     return runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
                 case "disable":
@@ -1808,6 +1812,56 @@
         return doRemoveSplits(sessionId, splitNames, true /*logSuccess*/);
     }
 
+    private int runGetArchivedPackageMetadata() throws RemoteException {
+        final PrintWriter pw = getOutPrintWriter();
+        int userId = UserHandle.USER_CURRENT;
+
+        String opt;
+        while ((opt = getNextOption()) != null) {
+            switch (opt) {
+                case "--user":
+                    userId = UserHandle.parseUserArg(getNextArgRequired());
+                    break;
+                default:
+                    pw.println("Error: Unknown option: " + opt);
+                    return 1;
+            }
+        }
+
+        final String packageName = getNextArg();
+        if (packageName == null) {
+            pw.println("Error: package name not specified");
+            return 1;
+        }
+        final int translatedUserId = translateUserId(userId, UserHandle.USER_NULL,
+                "runGetArchivedPackageMetadata");
+
+        try {
+            var archivedPackage = mInterface.getArchivedPackage(packageName, translatedUserId);
+            if (archivedPackage == null) {
+                pw.write("Package not found " + packageName);
+                return -1;
+            }
+
+            Parcel parcel = Parcel.obtain();
+            byte[] bytes;
+            try {
+                parcel.writeParcelable(archivedPackage, 0);
+                bytes = parcel.marshall();
+            } finally {
+                parcel.recycle();
+            }
+
+            String encoded = HexEncoding.encodeToString(bytes);
+            pw.write(encoded);
+        } catch (Exception e) {
+            getErrPrintWriter().println("Failed to get archived package, reason: " + e);
+            pw.println("Failure [failed to get archived package], reason: " + e);
+            return -1;
+        }
+        return 0;
+    }
+
     private int runInstallExisting() throws RemoteException {
         final PrintWriter pw = getOutPrintWriter();
         int userId = UserHandle.USER_CURRENT;
@@ -4146,28 +4200,24 @@
             throw new IllegalArgumentException("Error: Can't open file: " + inPath);
         }
 
-        File tmpFile = null;
+        final String encoded;
         final ParcelFileDescriptor fd = fdWithSize.first;
+        final int size = (int) (long) fdWithSize.second;
         try (InputStream inStream = new AutoCloseInputStream(fd)) {
-            final long identity = Binder.clearCallingIdentity();
-            try {
-                File tmpStagingDir = Environment.getDataAppDirectory(null);
-                tmpFile = new File(tmpStagingDir, "tmdl" + RANDOM.nextInt() + ".tmp");
-
-                try (OutputStream outStream = new FileOutputStream(tmpFile)) {
-                    Streams.copy(inStream, outStream);
-                }
-
-                return mInterface.getArchivedPackage(tmpFile.getAbsolutePath());
-            } finally {
-                if (tmpFile != null) {
-                    tmpFile.delete();
-                }
-                Binder.restoreCallingIdentity(identity);
-            }
+            byte[] bytes = new byte[size];
+            Streams.readFully(inStream, bytes);
+            encoded = new String(bytes);
         } catch (IOException e) {
-            throw new IllegalArgumentException("Error: Can't stage file: " + inPath, e);
+            throw new IllegalArgumentException("Error: Can't load archived package from: " + inPath,
+                    e);
         }
+
+        var result = Metadata.readArchivedPackageParcel(HexEncoding.decode(encoded));
+        if (result == null) {
+            throw new IllegalArgumentException(
+                    "Error: Can't parse archived package from: " + inPath);
+        }
+        return result;
     }
 
     private void processArgForLocalFile(String arg, PackageInstaller.Session session,
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommandDataLoader.java b/services/core/java/com/android/server/pm/PackageManagerShellCommandDataLoader.java
index fbe5a51..9e7f043 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommandDataLoader.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommandDataLoader.java
@@ -166,16 +166,7 @@
         /** @hide */
         @VisibleForTesting
         public static Metadata forArchived(ArchivedPackageParcel archivedPackage) {
-            Parcel parcel = Parcel.obtain();
-            byte[] bytes;
-            try {
-                parcel.writeParcelable(archivedPackage, 0);
-                bytes = parcel.marshall();
-            } finally {
-                parcel.recycle();
-            }
-
-            return new Metadata(ARCHIVED, bytes, null);
+            return new Metadata(ARCHIVED, writeArchivedPackageParcel(archivedPackage), null);
         }
 
         static Metadata forDataOnlyStreaming(String fileId) {
@@ -270,11 +261,14 @@
             if (getMode() != ARCHIVED) {
                 throw new IllegalStateException("Not an archived package metadata.");
             }
+            return readArchivedPackageParcel(this.mData);
+        }
 
+        static ArchivedPackageParcel readArchivedPackageParcel(byte[] bytes) {
             Parcel parcel = Parcel.obtain();
             ArchivedPackageParcel result;
             try {
-                parcel.unmarshall(this.mData, 0, this.mData.length);
+                parcel.unmarshall(bytes, 0, bytes.length);
                 parcel.setDataPosition(0);
                 result = parcel.readParcelable(ArchivedPackageParcel.class.getClassLoader());
             } finally {
@@ -282,6 +276,16 @@
             }
             return result;
         }
+
+        static byte[] writeArchivedPackageParcel(ArchivedPackageParcel archivedPackage) {
+            Parcel parcel = Parcel.obtain();
+            try {
+                parcel.writeParcelable(archivedPackage, 0);
+                return parcel.marshall();
+            } finally {
+                parcel.recycle();
+            }
+        }
     }
 
     private static class DataLoader implements DataLoaderService.DataLoader {
diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java
index 1884caf..2e60064 100644
--- a/services/core/java/com/android/server/pm/PackageSetting.java
+++ b/services/core/java/com/android/server/pm/PackageSetting.java
@@ -654,6 +654,16 @@
         return (getFlags() & ApplicationInfo.FLAG_SYSTEM) != 0;
     }
 
+    public boolean isRequestLegacyExternalStorage() {
+        return (getPrivateFlags() & ApplicationInfo.PRIVATE_FLAG_REQUEST_LEGACY_EXTERNAL_STORAGE)
+                != 0;
+    }
+
+    public boolean isUserDataFragile() {
+        return (getPrivateFlags() & ApplicationInfo.PRIVATE_FLAG_HAS_FRAGILE_USER_DATA)
+                != 0;
+    }
+
     public SigningDetails getSigningDetails() {
         return signatures.mSigningDetails;
     }
diff --git a/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java b/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java
index 812e228..f14941b 100644
--- a/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java
+++ b/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java
@@ -28,6 +28,7 @@
 import static android.os.Build.VERSION_CODES.DONUT;
 import static android.os.Build.VERSION_CODES.O;
 import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
+
 import static com.android.server.pm.pkg.parsing.ParsingUtils.parseKnownActivityEmbeddingCerts;
 
 import android.annotation.AnyRes;
@@ -509,24 +510,33 @@
                 /* Set the global "on SD card" flag */
                 .setExternalStorage((flags & PARSE_EXTERNAL_STORAGE) != 0);
 
+        var archivedPackage = lite.getArchivedPackage();
+        if (archivedPackage == null) {
+            return input.error(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
+                    "archivePackage is missing");
+        }
+
         // parseBaseAppBasicFlags
         pkg
                 // Default true
-                .setBackupAllowed(lite.isBackupAllowed())
+                .setBackupAllowed(true)
                 .setClearUserDataAllowed(true)
-                .setClearUserDataOnFailedRestoreAllowed(
-                        lite.isClearUserDataOnFailedRestoreAllowed())
+                .setClearUserDataOnFailedRestoreAllowed(true)
                 .setAllowNativeHeapPointerTagging(true)
                 .setEnabled(true)
                 .setExtractNativeLibrariesRequested(true)
                 // targetSdkVersion gated
                 .setAllowAudioPlaybackCapture(targetSdk >= Build.VERSION_CODES.Q)
                 .setHardwareAccelerated(targetSdk >= Build.VERSION_CODES.ICE_CREAM_SANDWICH)
-                .setRequestLegacyExternalStorage(lite.isRequestLegacyExternalStorage())
+                .setRequestLegacyExternalStorage(
+                        XmlUtils.convertValueToBoolean(archivedPackage.requestLegacyExternalStorage,
+                                targetSdk < Build.VERSION_CODES.Q))
                 .setCleartextTrafficAllowed(targetSdk < Build.VERSION_CODES.P)
                 // Default false
-                .setDefaultToDeviceProtectedStorage(lite.isDefaultToDeviceProtectedStorage())
-                .setUserDataFragile(lite.isUserDataFragile())
+                .setDefaultToDeviceProtectedStorage(XmlUtils.convertValueToBoolean(
+                        archivedPackage.defaultToDeviceProtectedStorage, false))
+                .setUserDataFragile(
+                        XmlUtils.convertValueToBoolean(archivedPackage.userDataFragile, false))
                 // Ints
                 .setCategory(ApplicationInfo.CATEGORY_UNDEFINED)
                 // Floats Default 0f
diff --git a/services/core/java/com/android/server/wm/ActivityStartInterceptor.java b/services/core/java/com/android/server/wm/ActivityStartInterceptor.java
index a5b1132..25c42b4 100644
--- a/services/core/java/com/android/server/wm/ActivityStartInterceptor.java
+++ b/services/core/java/com/android/server/wm/ActivityStartInterceptor.java
@@ -33,9 +33,7 @@
 import static android.content.pm.ApplicationInfo.FLAG_SUSPENDED;
 
 import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
-import static com.android.server.wm.ActivityInterceptorCallback.MAINLINE_SDK_SANDBOX_ORDER_ID;
 
-import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.ActivityOptions;
 import android.app.KeyguardManager;
@@ -240,11 +238,6 @@
                 getInterceptorInfo(null /* clearOptionsAnimation */);
 
         for (int i = 0; i < callbacks.size(); i++) {
-            final int orderId = callbacks.keyAt(i);
-            if (!shouldInterceptActivityLaunch(orderId, interceptorInfo)) {
-                continue;
-            }
-
             final ActivityInterceptorCallback callback = callbacks.valueAt(i);
             final ActivityInterceptResult interceptResult = callback.onInterceptActivityLaunch(
                     interceptorInfo);
@@ -543,11 +536,6 @@
         ActivityInterceptorCallback.ActivityInterceptorInfo info = getInterceptorInfo(
                 r::clearOptionsAnimationForSiblings);
         for (int i = 0; i < callbacks.size(); i++) {
-            final int orderId = callbacks.keyAt(i);
-            if (!shouldNotifyOnActivityLaunch(orderId, info)) {
-                continue;
-            }
-
             final ActivityInterceptorCallback callback = callbacks.valueAt(i);
             callback.onActivityLaunched(taskInfo, r.info, info);
         }
@@ -565,21 +553,4 @@
                 .build();
     }
 
-    private boolean shouldInterceptActivityLaunch(
-            @ActivityInterceptorCallback.OrderedId int orderId,
-            @NonNull ActivityInterceptorCallback.ActivityInterceptorInfo info) {
-        if (orderId == MAINLINE_SDK_SANDBOX_ORDER_ID) {
-            return info.getIntent() != null && info.getIntent().isSandboxActivity(mServiceContext);
-        }
-        return true;
-    }
-
-    private boolean shouldNotifyOnActivityLaunch(
-            @ActivityInterceptorCallback.OrderedId int orderId,
-            @NonNull ActivityInterceptorCallback.ActivityInterceptorInfo info) {
-        if (orderId == MAINLINE_SDK_SANDBOX_ORDER_ID) {
-            return info.getIntent() != null && info.getIntent().isSandboxActivity(mServiceContext);
-        }
-        return true;
-    }
 }
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/PackageArchiverTest.java b/services/tests/mockingservicestests/src/com/android/server/pm/PackageArchiverTest.java
index d988063..5555c19 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/PackageArchiverTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/PackageArchiverTest.java
@@ -18,7 +18,9 @@
 
 import static android.content.Intent.FLAG_RECEIVER_FOREGROUND;
 import static android.content.pm.PackageManager.DELETE_KEEP_DATA;
+
 import static com.google.common.truth.Truth.assertThat;
+
 import static org.junit.Assert.assertThrows;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
@@ -161,7 +163,7 @@
 
         mArchiveManager = spy(new PackageArchiver(mContext, pm));
         doReturn(ICON_PATH).when(mArchiveManager).storeIcon(eq(PACKAGE),
-                any(LauncherActivityInfo.class), eq(mUserId));
+                any(LauncherActivityInfo.class), eq(mUserId), anyInt());
     }
 
     @Test
@@ -249,7 +251,7 @@
     public void archiveApp_storeIconFails() throws IntentSender.SendIntentException, IOException {
         IOException e = new IOException("IO");
         doThrow(e).when(mArchiveManager).storeIcon(eq(PACKAGE),
-                any(LauncherActivityInfo.class), eq(mUserId));
+                any(LauncherActivityInfo.class), eq(mUserId), anyInt());
 
         mArchiveManager.requestArchive(PACKAGE, CALLER_PACKAGE, mIntentSender, UserHandle.CURRENT);
         rule.mocks().getHandler().flush();
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java
index 0989db4..568471d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java
@@ -16,7 +16,6 @@
 
 package com.android.server.wm;
 
-import static android.app.sdksandbox.SdkSandboxManager.ACTION_START_SANDBOXED_ACTIVITY;
 import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_DEFAULT;
 import static android.content.pm.ApplicationInfo.FLAG_SUSPENDED;
 
@@ -26,7 +25,6 @@
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
 import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
-import static com.android.server.wm.ActivityInterceptorCallback.MAINLINE_SDK_SANDBOX_ORDER_ID;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -36,7 +34,6 @@
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.ArgumentMatchers.nullable;
 import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -44,13 +41,11 @@
 import android.app.ActivityOptions;
 import android.app.KeyguardManager;
 import android.app.admin.DevicePolicyManagerInternal;
-import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.IPackageManager;
-import android.content.pm.PackageManager;
 import android.content.pm.PackageManagerInternal;
 import android.content.pm.SuspendDialogInfo;
 import android.content.pm.UserInfo;
@@ -76,7 +71,6 @@
 import org.junit.Rule;
 import org.junit.Test;
 import org.mockito.Mock;
-import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
 
 /**
@@ -509,88 +503,4 @@
 
         verify(callback, times(1)).onActivityLaunched(any(), any(), any());
     }
-
-    @Test
-    public void testSandboxServiceInterceptionHappensToIntentWithSandboxActivityAction() {
-        ActivityInterceptorCallback spyCallback = Mockito.spy(info -> null);
-        mActivityInterceptorCallbacks.put(MAINLINE_SDK_SANDBOX_ORDER_ID, spyCallback);
-
-        PackageManager packageManagerMock = mock(PackageManager.class);
-        String sandboxPackageNameMock = "com.sandbox.mock";
-        when(mContext.getPackageManager()).thenReturn(packageManagerMock);
-        when(packageManagerMock.getSdkSandboxPackageName()).thenReturn(sandboxPackageNameMock);
-
-        Intent intent = new Intent().setAction(ACTION_START_SANDBOXED_ACTIVITY);
-        mInterceptor.intercept(intent, null, mAInfo, null, null, null, 0, 0, null, null);
-
-        verify(spyCallback, times(1)).onInterceptActivityLaunch(
-                any(ActivityInterceptorCallback.ActivityInterceptorInfo.class));
-    }
-
-    @Test
-    public void testSandboxServiceInterceptionHappensToIntentWithSandboxPackage() {
-        ActivityInterceptorCallback spyCallback = Mockito.spy(info -> null);
-        mActivityInterceptorCallbacks.put(MAINLINE_SDK_SANDBOX_ORDER_ID, spyCallback);
-
-        PackageManager packageManagerMock = mock(PackageManager.class);
-        String sandboxPackageNameMock = "com.sandbox.mock";
-        when(mContext.getPackageManager()).thenReturn(packageManagerMock);
-        when(packageManagerMock.getSdkSandboxPackageName()).thenReturn(sandboxPackageNameMock);
-
-        Intent intent = new Intent().setPackage(sandboxPackageNameMock);
-        mInterceptor.intercept(intent, null, mAInfo, null, null, null, 0, 0, null, null);
-
-        verify(spyCallback, times(1)).onInterceptActivityLaunch(
-                any(ActivityInterceptorCallback.ActivityInterceptorInfo.class));
-    }
-
-    @Test
-    public void testSandboxServiceInterceptionHappensToIntentWithComponentNameWithSandboxPackage() {
-        ActivityInterceptorCallback spyCallback = Mockito.spy(info -> null);
-        mActivityInterceptorCallbacks.put(MAINLINE_SDK_SANDBOX_ORDER_ID, spyCallback);
-
-        PackageManager packageManagerMock = mock(PackageManager.class);
-        String sandboxPackageNameMock = "com.sandbox.mock";
-        when(mContext.getPackageManager()).thenReturn(packageManagerMock);
-        when(packageManagerMock.getSdkSandboxPackageName()).thenReturn(sandboxPackageNameMock);
-
-        Intent intent = new Intent().setComponent(new ComponentName(sandboxPackageNameMock, ""));
-        mInterceptor.intercept(intent, null, mAInfo, null, null, null, 0, 0, null, null);
-
-        verify(spyCallback, times(1)).onInterceptActivityLaunch(
-                any(ActivityInterceptorCallback.ActivityInterceptorInfo.class));
-    }
-
-    @Test
-    public void testSandboxServiceInterceptionNotCalledWhenIntentNotRelatedToSandbox() {
-        ActivityInterceptorCallback spyCallback = Mockito.spy(info -> null);
-        mActivityInterceptorCallbacks.put(MAINLINE_SDK_SANDBOX_ORDER_ID, spyCallback);
-
-        PackageManager packageManagerMock = mock(PackageManager.class);
-        String sandboxPackageNameMock = "com.sandbox.mock";
-        when(mContext.getPackageManager()).thenReturn(packageManagerMock);
-        when(packageManagerMock.getSdkSandboxPackageName()).thenReturn(sandboxPackageNameMock);
-
-        // Intent: null
-        mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null, null);
-
-        // Action: null, Package: null, ComponentName: null
-        Intent intent = new Intent();
-        mInterceptor.intercept(intent, null, mAInfo, null, null, null, 0, 0, null, null);
-
-        // Wrong Action
-        intent = new Intent().setAction(Intent.ACTION_VIEW);
-        mInterceptor.intercept(intent, null, mAInfo, null, null, null, 0, 0, null, null);
-
-        // Wrong Package
-        intent = new Intent().setPackage("Random");
-        mInterceptor.intercept(intent, null, mAInfo, null, null, null, 0, 0, null, null);
-
-        // Wrong ComponentName's package
-        intent = new Intent().setComponent(new ComponentName("Random", ""));
-        mInterceptor.intercept(intent, null, mAInfo, null, null, null, 0, 0, null, null);
-
-        verify(spyCallback, never()).onInterceptActivityLaunch(
-                any(ActivityInterceptorCallback.ActivityInterceptorInfo.class));
-    }
 }
diff --git a/tools/aapt2/OWNERS b/tools/aapt2/OWNERS
index 4f655e5..55bab7d 100644
--- a/tools/aapt2/OWNERS
+++ b/tools/aapt2/OWNERS
@@ -1,4 +1,4 @@
 set noparent
-toddke@google.com
 zyy@google.com
-patb@google.com
\ No newline at end of file
+patb@google.com
+markpun@google.com