Merge "Remove app metadata if data is null or empty"
diff --git a/core/java/android/content/pm/IPackageInstallerSession.aidl b/core/java/android/content/pm/IPackageInstallerSession.aidl
index 9c1318e..081f263 100644
--- a/core/java/android/content/pm/IPackageInstallerSession.aidl
+++ b/core/java/android/content/pm/IPackageInstallerSession.aidl
@@ -69,4 +69,5 @@
 
     ParcelFileDescriptor getAppMetadataFd();
     ParcelFileDescriptor openWriteAppMetadata();
+    void removeAppMetadata();
 }
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 45100be..c2b047a 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -1956,16 +1956,22 @@
         /**
          * Optionally set the app metadata. The size of this data cannot exceed the maximum allowed.
          * Any existing data from the previous install will not be retained even if no data is set
-         * for the current install session.
+         * for the current install session. Setting data to null or an empty PersistableBundle will
+         * remove any metadata that has previously been set in the same session.
          *
-         * @param data a PersistableBundle containing the app metadata. If this is set to null then
-         *     any existing app metadata will be removed.
+         * @param data a PersistableBundle containing the app metadata.
          * @throws IOException if writing the data fails.
          */
         public void setAppMetadata(@Nullable PersistableBundle data) throws IOException {
-            if (data == null) {
+            if (data == null || data.isEmpty()) {
+                try {
+                    mSession.removeAppMetadata();
+                } catch (RemoteException e) {
+                    throw e.rethrowFromSystemServer();
+                }
                 return;
             }
+            Objects.requireNonNull(data);
             try (OutputStream outputStream = openWriteAppMetadata()) {
                 data.writeToStream(outputStream);
             }
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 55dcaf6..e5e87af 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -1521,7 +1521,10 @@
     public ParcelFileDescriptor getAppMetadataFd() {
         assertCallerIsOwnerOrRoot();
         synchronized (mLock) {
-            assertPreparedAndNotCommittedOrDestroyedLocked("openRead");
+            assertPreparedAndNotCommittedOrDestroyedLocked("getAppMetadataFd");
+            if (getStagedAppMetadataFile() == null) {
+                return null;
+            }
             try {
                 return openReadInternalLocked(APP_METADATA_FILE_NAME);
             } catch (IOException e) {
@@ -1530,6 +1533,14 @@
         }
     }
 
+    @Override
+    public void removeAppMetadata() {
+        File file = getStagedAppMetadataFile();
+        if (file != null) {
+            file.delete();
+        }
+    }
+
     private static long getAppMetadataSizeLimit() {
         final long token = Binder.clearCallingIdentity();
         try {