Expose new APIs required by Package Installer.
This change contains those constants and methods that were exposed to
@SystemApi or public, with appropriate documentation and permission enforcements.
This allows Package Installer become an updatable module.
Test: atest CtsContentTestCases:PackageManagerTest CtsPackageInstallTestCases:SessionInfoTest CtsPackageInstallTestCases:InstallPromptDetailsTest PackageManagerServiceUnitTests:UninstallCompleteCallbackTest CtsPackageUninstallTestCases
Bug: 241139604
Bug: 239722738
Change-Id: I938d87fc266ff4268aa3fef1cd1405c1598d5ca8
diff --git a/core/api/current.txt b/core/api/current.txt
index 5bb6652..19f04d4 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -11765,6 +11765,7 @@
method public void registerSessionCallback(@NonNull android.content.pm.PackageInstaller.SessionCallback, @NonNull android.os.Handler);
method @RequiresPermission(anyOf={android.Manifest.permission.DELETE_PACKAGES, android.Manifest.permission.REQUEST_DELETE_PACKAGES}) public void uninstall(@NonNull String, @NonNull android.content.IntentSender);
method @RequiresPermission(anyOf={android.Manifest.permission.DELETE_PACKAGES, android.Manifest.permission.REQUEST_DELETE_PACKAGES}) public void uninstall(@NonNull android.content.pm.VersionedPackage, @NonNull android.content.IntentSender);
+ method @RequiresPermission(anyOf={android.Manifest.permission.DELETE_PACKAGES, android.Manifest.permission.REQUEST_DELETE_PACKAGES}) public void uninstall(@NonNull android.content.pm.VersionedPackage, int, @NonNull android.content.IntentSender);
method @RequiresPermission(android.Manifest.permission.DELETE_PACKAGES) public void uninstallExistingPackage(@NonNull String, @Nullable android.content.IntentSender);
method public void unregisterSessionCallback(@NonNull android.content.pm.PackageInstaller.SessionCallback);
method public void updateSessionAppIcon(int, @Nullable android.graphics.Bitmap);
@@ -11893,6 +11894,8 @@
method public int getInstallReason();
method @Nullable public String getInstallerAttributionTag();
method @Nullable public String getInstallerPackageName();
+ method public int getInstallerUid();
+ method @NonNull public boolean getIsPreApprovalRequested();
method public int getMode();
method public int getOriginatingUid();
method @Nullable public android.net.Uri getOriginatingUri();
@@ -11943,6 +11946,7 @@
method public void setInstallLocation(int);
method public void setInstallReason(int);
method public void setInstallScenario(int);
+ method public void setInstallerPackageName(@Nullable String);
method public void setKeepApplicationEnabledSetting();
method public void setMultiPackage();
method public void setOriginatingUid(int);
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index ac5c54d..74b603e 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -3331,6 +3331,7 @@
field public static final String CATEGORY_LEANBACK_SETTINGS = "android.intent.category.LEANBACK_SETTINGS";
field public static final String EXTRA_CALLING_PACKAGE = "android.intent.extra.CALLING_PACKAGE";
field public static final String EXTRA_FORCE_FACTORY_RESET = "android.intent.extra.FORCE_FACTORY_RESET";
+ field public static final String EXTRA_INSTALL_RESULT = "android.intent.extra.INSTALL_RESULT";
field public static final String EXTRA_INSTANT_APP_ACTION = "android.intent.extra.INSTANT_APP_ACTION";
field public static final String EXTRA_INSTANT_APP_BUNDLES = "android.intent.extra.INSTANT_APP_BUNDLES";
field public static final String EXTRA_INSTANT_APP_EXTRAS = "android.intent.extra.INSTANT_APP_EXTRAS";
@@ -3346,6 +3347,7 @@
field public static final String EXTRA_RESULT_NEEDED = "android.intent.extra.RESULT_NEEDED";
field public static final String EXTRA_ROLE_NAME = "android.intent.extra.ROLE_NAME";
field public static final String EXTRA_SHOWING_ATTRIBUTION = "android.intent.extra.SHOWING_ATTRIBUTION";
+ field public static final String EXTRA_UNINSTALL_ALL_USERS = "android.intent.extra.UNINSTALL_ALL_USERS";
field public static final String EXTRA_UNKNOWN_INSTANT_APP = "android.intent.extra.UNKNOWN_INSTANT_APP";
field public static final String EXTRA_USER_HANDLE = "android.intent.extra.user_handle";
field public static final String EXTRA_VERIFICATION_BUNDLE = "android.intent.extra.VERIFICATION_BUNDLE";
@@ -3452,9 +3454,11 @@
package android.content.pm {
public class ApplicationInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable {
+ method @RequiresPermission(android.Manifest.permission.DELETE_PACKAGES) public boolean hasFragileUserData();
method public boolean isEncryptionAware();
method public boolean isInstantApp();
method public boolean isOem();
+ method @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES) public boolean isPrivilegedApp();
method public boolean isProduct();
method public boolean isVendor();
field public String credentialProtectedDataDir;
@@ -3572,16 +3576,32 @@
}
public class PackageInstaller {
+ method @NonNull public android.content.pm.PackageInstaller.InstallInfo getInstallInfo(@NonNull java.io.File, int) throws android.content.pm.PackageInstaller.PackageParsingException;
method @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES) public void setPermissionsResult(int, boolean);
+ field public static final String ACTION_CONFIRM_INSTALL = "android.content.pm.action.CONFIRM_INSTALL";
+ field public static final String ACTION_CONFIRM_PRE_APPROVAL = "android.content.pm.action.CONFIRM_PRE_APPROVAL";
field public static final int DATA_LOADER_TYPE_INCREMENTAL = 2; // 0x2
field public static final int DATA_LOADER_TYPE_NONE = 0; // 0x0
field public static final int DATA_LOADER_TYPE_STREAMING = 1; // 0x1
+ field public static final String EXTRA_CALLBACK = "android.content.pm.extra.CALLBACK";
field public static final String EXTRA_DATA_LOADER_TYPE = "android.content.pm.extra.DATA_LOADER_TYPE";
+ field public static final String EXTRA_LEGACY_STATUS = "android.content.pm.extra.LEGACY_STATUS";
+ field public static final String EXTRA_RESOLVED_BASE_PATH = "android.content.pm.extra.RESOLVED_BASE_PATH";
field public static final int LOCATION_DATA_APP = 0; // 0x0
field public static final int LOCATION_MEDIA_DATA = 2; // 0x2
field public static final int LOCATION_MEDIA_OBB = 1; // 0x1
}
+ public static class PackageInstaller.InstallInfo {
+ method public long calculateInstalledSize(@NonNull android.content.pm.PackageInstaller.SessionParams) throws java.io.IOException;
+ method public int getInstallLocation();
+ method @NonNull public String getPackageName();
+ }
+
+ public static class PackageInstaller.PackageParsingException extends java.lang.Exception {
+ method public int getErrorCode();
+ }
+
public static class PackageInstaller.Session implements java.io.Closeable {
method @RequiresPermission("com.android.permission.USE_INSTALLER_V2") public void addFile(int, @NonNull String, long, @NonNull byte[], @Nullable byte[]);
method @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES) public void commitTransferred(@NonNull android.content.IntentSender);
@@ -3628,6 +3648,7 @@
public abstract class PackageManager {
method @RequiresPermission("android.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS") public abstract void addOnPermissionsChangeListener(@NonNull android.content.pm.PackageManager.OnPermissionsChangedListener);
method public abstract boolean arePermissionsIndividuallyControlled();
+ method @NonNull public boolean canUserUninstall(@NonNull String, @NonNull android.os.UserHandle);
method @NonNull public abstract java.util.List<android.content.IntentFilter> getAllIntentFilters(@NonNull String);
method @NonNull @RequiresPermission("android.permission.GET_APP_METADATA") public android.os.PersistableBundle getAppMetadata(@NonNull String) throws android.content.pm.PackageManager.NameNotFoundException;
method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public android.content.pm.ApplicationInfo getApplicationInfoAsUser(@NonNull String, int, @NonNull android.os.UserHandle) throws android.content.pm.PackageManager.NameNotFoundException;
@@ -3646,6 +3667,7 @@
method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_INSTANT_APPS) public abstract java.util.List<android.content.pm.InstantAppInfo> getInstantApps();
method @Deprecated @NonNull public abstract java.util.List<android.content.pm.IntentFilterVerificationInfo> getIntentFilterVerifications(@NonNull String);
method @Deprecated @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) public abstract int getIntentVerificationStatusAsUser(@NonNull String, int);
+ method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) public int getPackageUidAsUser(@NonNull String, @NonNull android.content.pm.PackageManager.PackageInfoFlags, int) throws android.content.pm.PackageManager.NameNotFoundException;
method @android.content.pm.PackageManager.PermissionFlags @RequiresPermission(anyOf={android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS, android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS, android.Manifest.permission.GET_RUNTIME_PERMISSIONS}) public abstract int getPermissionFlags(@NonNull String, @NonNull String, @NonNull android.os.UserHandle);
method @NonNull @RequiresPermission(android.Manifest.permission.SUSPEND_APPS) public String[] getUnsuspendablePackages(@NonNull String[]);
method @RequiresPermission(android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS) public abstract void grantRuntimePermission(@NonNull String, @NonNull String, @NonNull android.os.UserHandle);
@@ -3673,11 +3695,19 @@
method @RequiresPermission(value=android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE, conditional=true) public void setSyntheticAppDetailsActivityEnabled(@NonNull String, boolean);
method public void setSystemAppState(@NonNull String, int);
method @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES) public abstract void setUpdateAvailable(@NonNull String, boolean);
+ method @NonNull public boolean shouldShowNewAppInstalledNotification();
method @Deprecated @RequiresPermission(android.Manifest.permission.SET_PREFERRED_APPLICATIONS) public abstract boolean updateIntentVerificationStatusAsUser(@NonNull String, int, int);
method @RequiresPermission(anyOf={android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS, android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS}) public abstract void updatePermissionFlags(@NonNull String, @NonNull String, @android.content.pm.PackageManager.PermissionFlags int, @android.content.pm.PackageManager.PermissionFlags int, @NonNull android.os.UserHandle);
method @Deprecated @RequiresPermission(android.Manifest.permission.INTENT_FILTER_VERIFICATION_AGENT) public abstract void verifyIntentFilter(int, int, @NonNull java.util.List<java.lang.String>);
field public static final String ACTION_REQUEST_PERMISSIONS = "android.content.pm.action.REQUEST_PERMISSIONS";
field public static final String ACTION_REQUEST_PERMISSIONS_FOR_OTHER = "android.content.pm.action.REQUEST_PERMISSIONS_FOR_OTHER";
+ field public static final int DELETE_ALL_USERS = 2; // 0x2
+ field public static final int DELETE_FAILED_ABORTED = -5; // 0xfffffffb
+ field public static final int DELETE_FAILED_DEVICE_POLICY_MANAGER = -2; // 0xfffffffe
+ field public static final int DELETE_FAILED_INTERNAL_ERROR = -1; // 0xffffffff
+ field public static final int DELETE_FAILED_OWNER_BLOCKED = -4; // 0xfffffffc
+ field public static final int DELETE_KEEP_DATA = 1; // 0x1
+ field public static final int DELETE_SUCCEEDED = 1; // 0x1
field public static final String EXTRA_REQUEST_PERMISSIONS_LEGACY_ACCESS_PERMISSION_NAMES = "android.content.pm.extra.REQUEST_PERMISSIONS_LEGACY_ACCESS_PERMISSION_NAMES";
field public static final String EXTRA_REQUEST_PERMISSIONS_NAMES = "android.content.pm.extra.REQUEST_PERMISSIONS_NAMES";
field public static final String EXTRA_REQUEST_PERMISSIONS_RESULTS = "android.content.pm.extra.REQUEST_PERMISSIONS_RESULTS";
@@ -3785,6 +3815,11 @@
@IntDef(prefix={"FLAG_PERMISSION_"}, value={android.content.pm.PackageManager.FLAG_PERMISSION_USER_SET, android.content.pm.PackageManager.FLAG_PERMISSION_USER_FIXED, android.content.pm.PackageManager.FLAG_PERMISSION_POLICY_FIXED, android.content.pm.PackageManager.FLAG_PERMISSION_REVOKE_ON_UPGRADE, android.content.pm.PackageManager.FLAG_PERMISSION_SYSTEM_FIXED, android.content.pm.PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT, android.content.pm.PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED, android.content.pm.PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_DENIED, android.content.pm.PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT, android.content.pm.PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT, android.content.pm.PackageManager.FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT, android.content.pm.PackageManager.FLAG_PERMISSION_APPLY_RESTRICTION, android.content.pm.PackageManager.FLAG_PERMISSION_GRANTED_BY_ROLE, android.content.pm.PackageManager.FLAG_PERMISSION_REVOKED_COMPAT, android.content.pm.PackageManager.FLAG_PERMISSION_ONE_TIME, android.content.pm.PackageManager.FLAG_PERMISSION_AUTO_REVOKED}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface PackageManager.PermissionFlags {
}
+ public static final class PackageManager.UninstallCompleteCallback implements android.os.Parcelable {
+ method public void onUninstallComplete(@NonNull String, int, @Nullable String);
+ field @NonNull public static final android.os.Parcelable.Creator<android.content.pm.PackageManager.UninstallCompleteCallback> CREATOR;
+ }
+
public class PermissionGroupInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable {
field @StringRes public final int backgroundRequestDetailResourceId;
field @StringRes public final int backgroundRequestResourceId;
@@ -10924,6 +10959,7 @@
field public static final String ACTION_TETHER_PROVISIONING_UI = "android.settings.TETHER_PROVISIONING_UI";
field public static final String ACTION_TETHER_SETTINGS = "android.settings.TETHER_SETTINGS";
field public static final String ACTION_TETHER_UNSUPPORTED_CARRIER_UI = "android.settings.TETHER_UNSUPPORTED_CARRIER_UI";
+ field public static final String ACTION_USER_SETTINGS = "android.settings.USER_SETTINGS";
}
public static final class Settings.Global extends android.provider.Settings.NameValueTable {
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 42acc22..9a0195d 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -814,7 +814,7 @@
public class ApplicationInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable {
method public boolean hasRequestForegroundServiceExemption();
method public boolean isOnBackInvokedCallbackEnabled();
- method public boolean isPrivilegedApp();
+ method @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES) public boolean isPrivilegedApp();
method public boolean isSystemApp();
method public void setEnableOnBackInvokedCallback(boolean);
field public static final int PRIVATE_FLAG_PRIVILEGED = 8; // 0x8
@@ -831,7 +831,6 @@
public static class PackageInstaller.SessionParams implements android.os.Parcelable {
method public void setInstallFlagAllowTest();
- method public void setInstallerPackageName(@Nullable String);
}
public abstract class PackageManager {
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 309b253..a7a4b35 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -3875,4 +3875,19 @@
throw e.rethrowAsRuntimeException();
}
}
+
+ @Override
+ public boolean canUserUninstall(String packageName, UserHandle user) {
+ try {
+ return mPM.getBlockUninstallForUser(packageName, user.getIdentifier());
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
+ }
+
+ @Override
+ public boolean shouldShowNewAppInstalledNotification() {
+ return Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.SHOW_NEW_APP_INSTALLED_NOTIFICATION_ENABLED, 0) == 1;
+ }
}
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 8aa0454..265e02a 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1814,8 +1814,8 @@
* Package manager install result code. @hide because result codes are not
* yet ready to be exposed.
*/
- public static final String EXTRA_INSTALL_RESULT
- = "android.intent.extra.INSTALL_RESULT";
+ @SystemApi
+ public static final String EXTRA_INSTALL_RESULT = "android.intent.extra.INSTALL_RESULT";
/**
* Activity Action: Launch application uninstaller.
@@ -1841,6 +1841,7 @@
* Specify whether the package should be uninstalled for all users.
* @hide because these should not be part of normal application flow.
*/
+ @SystemApi
public static final String EXTRA_UNINSTALL_ALL_USERS
= "android.intent.extra.UNINSTALL_ALL_USERS";
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 84811ea..94c5e25 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -18,9 +18,11 @@
import static android.os.Build.VERSION_CODES.DONUT;
+import android.Manifest;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
@@ -2253,6 +2255,8 @@
*
* @hide
*/
+ @SystemApi
+ @RequiresPermission(Manifest.permission.DELETE_PACKAGES)
public boolean hasFragileUserData() {
return (privateFlags & PRIVATE_FLAG_HAS_FRAGILE_USER_DATA) != 0;
}
@@ -2487,8 +2491,13 @@
return (privateFlags & ApplicationInfo.PRIVATE_FLAG_SIGNED_WITH_PLATFORM_KEY) != 0;
}
- /** @hide */
+ /**
+ * @return {@code true} if the application is permitted to hold privileged permissions.
+ *
+ * @hide */
@TestApi
+ @SystemApi
+ @RequiresPermission(Manifest.permission.INSTALL_PACKAGES)
public boolean isPrivilegedApp() {
return (privateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0;
}
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index febdaed..703a9252 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -26,6 +26,9 @@
import static android.content.pm.Checksum.TYPE_WHOLE_SHA1;
import static android.content.pm.Checksum.TYPE_WHOLE_SHA256;
import static android.content.pm.Checksum.TYPE_WHOLE_SHA512;
+import static android.content.pm.PackageInfo.INSTALL_LOCATION_AUTO;
+import static android.content.pm.PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY;
+import static android.content.pm.PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL;
import android.Manifest;
import android.annotation.CallbackExecutor;
@@ -48,6 +51,10 @@
import android.content.pm.PackageManager.DeleteFlags;
import android.content.pm.PackageManager.InstallReason;
import android.content.pm.PackageManager.InstallScenario;
+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.graphics.Bitmap;
import android.icu.util.ULocale;
import android.net.Uri;
@@ -70,12 +77,14 @@
import android.util.ArraySet;
import android.util.ExceptionUtils;
+import com.android.internal.content.InstallLocationUtils;
import com.android.internal.util.DataClass;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Preconditions;
import com.android.internal.util.function.pooled.PooledLambda;
import java.io.Closeable;
+import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
@@ -172,10 +181,22 @@
public static final String ACTION_SESSION_UPDATED =
"android.content.pm.action.SESSION_UPDATED";
- /** {@hide} */
+ /**
+ * Intent action to indicate that user action is required for current install. This action can
+ * be used only by system apps.
+ *
+ * @hide
+ */
+ @SystemApi
public static final String ACTION_CONFIRM_INSTALL = "android.content.pm.action.CONFIRM_INSTALL";
- /** @hide */
+ /**
+ * Activity Action: Intent sent to the installer when a session for requesting
+ * user pre-approval, and user needs to confirm the installation.
+ *
+ * @hide
+ */
+ @SystemApi
public static final String ACTION_CONFIRM_PRE_APPROVAL =
"android.content.pm.action.CONFIRM_PRE_APPROVAL";
@@ -272,11 +293,23 @@
@Deprecated
public static final String EXTRA_PACKAGE_NAMES = "android.content.pm.extra.PACKAGE_NAMES";
- /** {@hide} */
+ /**
+ * The status as used internally in the package manager. Refer to {@link PackageManager} for
+ * a list of all valid legacy statuses.
+ *
+ * @hide
+ */
+ @SystemApi
public static final String EXTRA_LEGACY_STATUS = "android.content.pm.extra.LEGACY_STATUS";
/** {@hide} */
public static final String EXTRA_LEGACY_BUNDLE = "android.content.pm.extra.LEGACY_BUNDLE";
- /** {@hide} */
+ /**
+ * The callback to execute once an uninstall is completed (used for both successful and
+ * unsuccessful uninstalls).
+ *
+ * @hide
+ */
+ @SystemApi
public static final String EXTRA_CALLBACK = "android.content.pm.extra.CALLBACK";
/**
@@ -293,6 +326,17 @@
public static final String EXTRA_DATA_LOADER_TYPE = "android.content.pm.extra.DATA_LOADER_TYPE";
/**
+ * Path to the validated base APK for this session, which may point at an
+ * APK inside the session (when the session defines the base), or it may
+ * point at the existing base APK (when adding splits to an existing app).
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final String EXTRA_RESOLVED_BASE_PATH =
+ "android.content.pm.extra.RESOLVED_BASE_PATH";
+
+ /**
* Streaming installation pending.
* Caller should make sure DataLoader is able to prepare image and reinitiate the operation.
*
@@ -796,8 +840,6 @@
* @param statusReceiver Where to deliver the result of the operation indicated by the extra
* {@link #EXTRA_STATUS}. Refer to the individual status codes
* on how to handle them.
- *
- * @hide
*/
@RequiresPermission(anyOf = {
Manifest.permission.DELETE_PACKAGES,
@@ -1871,6 +1913,101 @@
}
/**
+ * Parse a single APK or a directory of APKs to get install relevant information about
+ * the package wrapped in {@link InstallInfo}.
+ * @throws PackageParsingException if the package source file(s) provided is(are) not valid,
+ * or the parser isn't able to parse the supplied source(s).
+ * @hide
+ */
+ @SystemApi
+ @NonNull
+ public InstallInfo getInstallInfo(@NonNull File file, int flags)
+ throws PackageParsingException {
+ final ParseTypeImpl input = ParseTypeImpl.forDefaultParsing();
+ final ParseResult<PackageLite> result = ApkLiteParseUtils.parsePackageLite(
+ input.reset(), file, flags);
+ if (result.isError()) {
+ throw new PackageParsingException(result.getErrorCode(), result.getErrorMessage());
+ }
+ return new InstallInfo(result);
+ }
+
+ // (b/239722738) This class serves as a bridge between the PackageLite class, which
+ // is a hidden class, and the consumers of this class. (e.g. InstallInstalling.java)
+ // This is a part of an effort to remove dependency on hidden APIs and use SystemAPIs or
+ // public APIs.
+ /**
+ * Install related details from an APK or a folder of APK(s).
+ *
+ * @hide
+ */
+ @SystemApi
+ public static class InstallInfo {
+
+ /** @hide */
+ @IntDef(prefix = { "INSTALL_LOCATION_" }, value = {
+ INSTALL_LOCATION_AUTO,
+ INSTALL_LOCATION_INTERNAL_ONLY,
+ INSTALL_LOCATION_PREFER_EXTERNAL
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface InstallLocation{}
+
+ private PackageLite mPkg;
+
+ InstallInfo(ParseResult<PackageLite> result) {
+ mPkg = result.getResult();
+ }
+
+ /**
+ * See {@link PackageLite#getPackageName()}
+ */
+ @NonNull
+ public String getPackageName() {
+ return mPkg.getPackageName();
+ }
+
+ /**
+ * @return The default install location defined by an application in
+ * {@link android.R.attr#installLocation} attribute.
+ */
+ public @InstallLocation int getInstallLocation() {
+ return mPkg.getInstallLocation();
+ }
+
+ /**
+ * @param params {@link SessionParams} of the installation
+ * @return Total disk space occupied by an application after installation.
+ * Includes the size of the raw APKs, possibly unpacked resources, raw dex metadata files,
+ * and all relevant native code.
+ * @throws IOException when size of native binaries cannot be calculated.
+ */
+ public long calculateInstalledSize(@NonNull SessionParams params) throws IOException {
+ return InstallLocationUtils.calculateInstalledSize(mPkg, params.abiOverride);
+ }
+ }
+
+ /**
+ * Generic exception class for using with parsing operations.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static class PackageParsingException extends Exception {
+ private final int mErrorCode;
+
+ /** {@hide} */
+ public PackageParsingException(int errorCode, @Nullable String detailedMessage) {
+ super(detailedMessage);
+ mErrorCode = errorCode;
+ }
+
+ public int getErrorCode() {
+ return mErrorCode;
+ }
+ }
+
+ /**
* Parameters for creating a new {@link PackageInstaller.Session}.
*/
public static class SessionParams implements Parcelable {
@@ -2431,9 +2568,7 @@
* By default this is the app that created the {@link PackageInstaller} object.
*
* @param installerPackageName name of the installer package
- * {@hide}
*/
- @TestApi
public void setInstallerPackageName(@Nullable String installerPackageName) {
this.installerPackageName = installerPackageName;
}
@@ -3430,8 +3565,6 @@
/**
* Returns the Uid of the owner of the session.
- *
- * @hide
*/
public int getInstallerUid() {
return installerUid;
@@ -3445,6 +3578,13 @@
return keepApplicationEnabledSetting;
}
+ /**
+ * Returns whether this session has requested user pre-approval.
+ */
+ public @NonNull boolean getIsPreApprovalRequested() {
+ return isPreapprovalRequested;
+ }
+
@Override
public int describeContents() {
return 0;
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index cbdcc02..5eecde1 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -2250,6 +2250,7 @@
*
* @hide
*/
+ @SystemApi
public static final int DELETE_KEEP_DATA = 0x00000001;
/**
@@ -2258,6 +2259,7 @@
*
* @hide
*/
+ @SystemApi
public static final int DELETE_ALL_USERS = 0x00000002;
/**
@@ -2295,6 +2297,7 @@
*
* @hide
*/
+ @SystemApi
public static final int DELETE_SUCCEEDED = 1;
/**
@@ -2304,6 +2307,7 @@
*
* @hide
*/
+ @SystemApi
public static final int DELETE_FAILED_INTERNAL_ERROR = -1;
/**
@@ -2313,6 +2317,7 @@
*
* @hide
*/
+ @SystemApi
public static final int DELETE_FAILED_DEVICE_POLICY_MANAGER = -2;
/**
@@ -2332,9 +2337,11 @@
*
* @hide
*/
+ @SystemApi
public static final int DELETE_FAILED_OWNER_BLOCKED = -4;
/** {@hide} */
+ @SystemApi
public static final int DELETE_FAILED_ABORTED = -5;
/**
@@ -5336,17 +5343,7 @@
throws NameNotFoundException;
/**
- * Return the UID associated with the given package name.
- * <p>
- * Note that the same package will have different UIDs under different
- * {@link UserHandle} on the same device.
- *
- * @param packageName The full name (i.e. com.google.apps.contacts) of the
- * desired package.
- * @param userId The user handle identifier to look up the package under.
- * @return Returns an integer UID who owns the given package name.
- * @throws NameNotFoundException if no such package is available to the
- * caller.
+ * See {@link #getPackageUidAsUser(String, PackageInfoFlags, int)}.
* @deprecated Use {@link #getPackageUidAsUser(String, PackageInfoFlags, int)} instead.
* @hide
*/
@@ -5357,9 +5354,22 @@
int flags, @UserIdInt int userId) throws NameNotFoundException;
/**
- * See {@link #getPackageUidAsUser(String, int, int)}.
+ * Return the UID associated with the given package name.
+ * <p>
+ * Note that the same package will have different UIDs under different
+ * {@link UserHandle} on the same device.
+ *
+ * @param packageName The full name (i.e. com.google.apps.contacts) of the
+ * desired package.
+ * @param flags Additional option flags to modify the data returned.
+ * @param userId The user handle identifier to look up the package under.
+ * @return Returns an integer UID who owns the given package name.
+ * @throws NameNotFoundException if no such package is available to the
+ * caller.
* @hide
*/
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
public int getPackageUidAsUser(@NonNull String packageName, @NonNull PackageInfoFlags flags,
@UserIdInt int userId) throws NameNotFoundException {
throw new UnsupportedOperationException(
@@ -9805,6 +9815,83 @@
}
/**
+ * A parcelable class to pass as an intent extra to the PackageInstaller. When an uninstall is
+ * completed (both successfully or unsuccessfully), the result is sent to the uninstall
+ * initiators.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final class UninstallCompleteCallback implements Parcelable {
+ private IPackageDeleteObserver2 mBinder;
+
+ /** @hide */
+ @IntDef(prefix = { "DELETE_" }, value = {
+ DELETE_SUCCEEDED,
+ DELETE_FAILED_INTERNAL_ERROR,
+ DELETE_FAILED_DEVICE_POLICY_MANAGER,
+ DELETE_FAILED_USER_RESTRICTED,
+ DELETE_FAILED_OWNER_BLOCKED,
+ DELETE_FAILED_ABORTED,
+ DELETE_FAILED_USED_SHARED_LIBRARY,
+ DELETE_FAILED_APP_PINNED,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface DeleteStatus{}
+
+ /** @hide */
+ public UninstallCompleteCallback(@NonNull IBinder binder) {
+ mBinder = IPackageDeleteObserver2.Stub.asInterface(binder);
+ }
+
+ /** @hide */
+ private UninstallCompleteCallback(Parcel in) {
+ mBinder = IPackageDeleteObserver2.Stub.asInterface(in.readStrongBinder());
+ }
+
+ public static final @NonNull Parcelable.Creator<UninstallCompleteCallback> CREATOR =
+ new Parcelable.Creator<>() {
+ public UninstallCompleteCallback createFromParcel(Parcel source) {
+ return new UninstallCompleteCallback(source);
+ }
+
+ public UninstallCompleteCallback[] newArray(int size) {
+ return new UninstallCompleteCallback[size];
+ }
+ };
+
+ /**
+ * Called when an uninstallation is completed successfully or unsuccessfully.
+ *
+ * @param packageName The name of the package being uninstalled.
+ * @param resultCode Result code of the operation.
+ * @param errorMessage Error message if any.
+ *
+ * @hide */
+ @SystemApi
+ public void onUninstallComplete(@NonNull String packageName, @DeleteStatus int resultCode,
+ @Nullable String errorMessage) {
+ try {
+ mBinder.onPackageDeleted(packageName, resultCode, errorMessage);
+ } catch (RemoteException e) {
+ // no-op
+ }
+ }
+
+ /** @hide */
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ /** @hide */
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeStrongBinder(mBinder.asBinder());
+ }
+ }
+
+ /**
* Return the install reason that was recorded when a package was first
* installed for a specific user. Requesting the install reason for another
* user will require the permission INTERACT_ACROSS_USERS_FULL.
@@ -10723,4 +10810,33 @@
throw e.rethrowFromSystemServer();
}
}
+
+ /**
+ * Checks if a package is blocked from uninstall for a particular user. A package can be
+ * blocked from being uninstalled by a device owner or profile owner.
+ * See {@link DevicePolicyManager#setUninstallBlocked(ComponentName, String, boolean)}.
+ *
+ * @param packageName Name of the package being uninstalled.
+ * @param user UserHandle who's ability to uninstall a package is being checked.
+ *
+ * @hide
+ */
+ @SystemApi
+ @NonNull
+ public boolean canUserUninstall(@NonNull String packageName, @NonNull UserHandle user){
+ throw new UnsupportedOperationException(
+ "canUserUninstall not implemented in subclass");
+ }
+
+ /**
+ * See {@link android.provider.Settings.Global#SHOW_NEW_APP_INSTALLED_NOTIFICATION_ENABLED}.
+ *
+ * @hide
+ */
+ @SystemApi
+ @NonNull
+ public boolean shouldShowNewAppInstalledNotification() {
+ throw new UnsupportedOperationException(
+ "isShowNewAppInstalledNotificationEnabled not implemented in subclass");
+ }
}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index efe8238..b236d66 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -224,6 +224,7 @@
* @hide
*/
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ @SystemApi
public static final String ACTION_USER_SETTINGS =
"android.settings.USER_SETTINGS";