Add API to enable/disable auto dependency installer

Installers should be able to turn off the auto installation behavior if
desired - add new a new setter in SessionParams that will be used to
control this behavior, along with a getter in SessionInfo.

While installing an app, check if this value is enabled before
proceeding.

Bug: 372861776
Flag: android.content.pm.sdk_dependency_installer
Test: atest InstallSessionParamsUnitTest
Test: atest PackageManagerShellCommandInstallTest
Change-Id: I609ff819346b35319cae92cd20076c3faf76bda9
diff --git a/core/api/current.txt b/core/api/current.txt
index fda66fa..5d40882 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -13029,6 +13029,7 @@
     method public boolean hasParentSessionId();
     method public boolean isActive();
     method public boolean isApplicationEnabledSettingPersistent();
+    method @FlaggedApi("android.content.pm.sdk_dependency_installer") public boolean isAutoInstallDependenciesEnabled();
     method public boolean isCommitted();
     method public boolean isMultiPackage();
     method public boolean isPreApprovalRequested();
@@ -13064,6 +13065,7 @@
     method public void setApplicationEnabledSettingPersistent();
     method @Deprecated public void setAutoRevokePermissionsMode(boolean);
     method public void setDontKillApp(boolean);
+    method @FlaggedApi("android.content.pm.sdk_dependency_installer") public void setEnableAutoInstallDependencies(boolean);
     method public void setInstallLocation(int);
     method public void setInstallReason(int);
     method public void setInstallScenario(int);
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 54c5596..63279af 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -2936,6 +2936,8 @@
         public @Nullable String dexoptCompilerFilter = null;
         /** {@hide} */
         public boolean forceVerification;
+        /** {@hide} */
+        public boolean isAutoInstallDependenciesEnabled = true;
 
         private final ArrayMap<String, Integer> mPermissionStates;
 
@@ -2991,6 +2993,7 @@
             unarchiveId = source.readInt();
             dexoptCompilerFilter = source.readString();
             forceVerification = source.readBoolean();
+            isAutoInstallDependenciesEnabled = source.readBoolean();
         }
 
         /** {@hide} */
@@ -3028,6 +3031,7 @@
             ret.unarchiveId = unarchiveId;
             ret.dexoptCompilerFilter = dexoptCompilerFilter;
             ret.forceVerification = forceVerification;
+            ret.isAutoInstallDependenciesEnabled = isAutoInstallDependenciesEnabled;
             return ret;
         }
 
@@ -3744,6 +3748,23 @@
             this.forceVerification = true;
         }
 
+        /**
+         * Optionally indicate whether missing SDK or static shared library dependencies should be
+         * automatically fetched and installed when installing an app that wants to use these
+         * dependencies.
+         *
+         * <p> This feature is enabled by default.
+         *
+         * @param enableAutoInstallDependencies {@code true} to enable auto-installation of missing
+         *                                      SDK or static shared library dependencies,
+         *                                      {@code false} to disable and fail immediately if
+         *                                      dependencies aren't already installed.
+         */
+        @FlaggedApi(Flags.FLAG_SDK_DEPENDENCY_INSTALLER)
+        public void setEnableAutoInstallDependencies(boolean enableAutoInstallDependencies) {
+            isAutoInstallDependenciesEnabled = enableAutoInstallDependencies;
+        }
+
         /** {@hide} */
         public void dump(IndentingPrintWriter pw) {
             pw.printPair("mode", mode);
@@ -3780,6 +3801,7 @@
             pw.printPair("unarchiveId", unarchiveId);
             pw.printPair("dexoptCompilerFilter", dexoptCompilerFilter);
             pw.printPair("forceVerification", forceVerification);
+            pw.printPair("isAutoInstallDependenciesEnabled", isAutoInstallDependenciesEnabled);
             pw.println();
         }
 
@@ -3827,6 +3849,7 @@
             dest.writeInt(unarchiveId);
             dest.writeString(dexoptCompilerFilter);
             dest.writeBoolean(forceVerification);
+            dest.writeBoolean(isAutoInstallDependenciesEnabled);
         }
 
         public static final Parcelable.Creator<SessionParams>
@@ -4005,6 +4028,9 @@
         private String mSessionErrorMessage;
 
         /** {@hide} */
+        public boolean isAutoInstallingDependenciesEnabled;
+
+        /** {@hide} */
         public boolean isCommitted;
 
         /** {@hide} */
@@ -4097,6 +4123,7 @@
             packageSource = source.readInt();
             applicationEnabledSettingPersistent = source.readBoolean();
             pendingUserActionReason = source.readInt();
+            isAutoInstallingDependenciesEnabled = source.readBoolean();
         }
 
         /**
@@ -4681,6 +4708,16 @@
             return (installFlags & PackageManager.INSTALL_UNARCHIVE) != 0;
         }
 
+        /**
+         * Check whether missing SDK or static shared library dependencies should be automatically
+         * fetched and installed when installing an app that wants to use these dependencies.
+         *
+         * @return true if the dependencies will be auto-installed, false otherwise.
+         */
+        @FlaggedApi(Flags.FLAG_SDK_DEPENDENCY_INSTALLER)
+        public boolean isAutoInstallDependenciesEnabled() {
+            return isAutoInstallingDependenciesEnabled;
+        }
 
         @Override
         public int describeContents() {
@@ -4735,6 +4772,7 @@
             dest.writeInt(packageSource);
             dest.writeBoolean(applicationEnabledSettingPersistent);
             dest.writeInt(pendingUserActionReason);
+            dest.writeBoolean(isAutoInstallingDependenciesEnabled);
         }
 
         public static final Parcelable.Creator<SessionInfo>
diff --git a/core/java/android/content/pm/flags.aconfig b/core/java/android/content/pm/flags.aconfig
index c424229..b4b5a7f 100644
--- a/core/java/android/content/pm/flags.aconfig
+++ b/core/java/android/content/pm/flags.aconfig
@@ -321,6 +321,7 @@
 
 flag {
     name: "sdk_dependency_installer"
+    is_exported: true
     namespace: "package_manager_service"
     description: "Feature flag to enable installation of missing sdk dependency of app"
     bug: "370822870"
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index bad1201..e156b31 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -1429,6 +1429,7 @@
             info.packageSource = params.packageSource;
             info.applicationEnabledSettingPersistent = params.applicationEnabledSettingPersistent;
             info.pendingUserActionReason = userActionRequirementToReason(mUserActionRequirement);
+            info.isAutoInstallingDependenciesEnabled = params.isAutoInstallDependenciesEnabled;
         }
         return info;
     }
@@ -3415,7 +3416,9 @@
             return;
         }
 
-        if (Flags.sdkDependencyInstaller() && !isMultiPackage()) {
+        if (Flags.sdkDependencyInstaller()
+                && params.isAutoInstallDependenciesEnabled
+                && !isMultiPackage()) {
             resolveLibraryDependenciesIfNeeded();
         } else {
             install();