method public abstract boolean addPermission(android.content.pm.PermissionInfo);
method public abstract boolean addPermissionAsync(android.content.pm.PermissionInfo);
method public abstract deprecated void addPreferredActivity(android.content.IntentFilter, int, android.content.ComponentName[], android.content.ComponentName);
+ method public abstract boolean canRequestPackageInstalls();
method public abstract java.lang.String[] canonicalToCurrentPackageNames(java.lang.String[]);
method public abstract int checkPermission(java.lang.String, java.lang.String);
method public abstract int checkSignatures(java.lang.String, java.lang.String);
field public static final java.lang.String ACTION_MANAGE_ALL_APPLICATIONS_SETTINGS = "android.settings.MANAGE_ALL_APPLICATIONS_SETTINGS";
field public static final java.lang.String ACTION_MANAGE_APPLICATIONS_SETTINGS = "android.settings.MANAGE_APPLICATIONS_SETTINGS";
field public static final java.lang.String ACTION_MANAGE_DEFAULT_APPS_SETTINGS = "android.settings.MANAGE_DEFAULT_APPS_SETTINGS";
+ field public static final java.lang.String ACTION_MANAGE_EXTERNAL_SOURCES = "android.settings.action.MANAGE_EXTERNAL_SOURCES";
field public static final java.lang.String ACTION_MANAGE_OVERLAY_PERMISSION = "android.settings.action.MANAGE_OVERLAY_PERMISSION";
field public static final java.lang.String ACTION_MANAGE_WRITE_SETTINGS = "android.settings.action.MANAGE_WRITE_SETTINGS";
field public static final java.lang.String ACTION_MEMORY_CARD_SETTINGS = "android.settings.MEMORY_CARD_SETTINGS";
field public static final java.lang.String ENABLED_INPUT_METHODS = "enabled_input_methods";
field public static final deprecated java.lang.String HTTP_PROXY = "http_proxy";
field public static final java.lang.String INPUT_METHOD_SELECTOR_VISIBILITY = "input_method_selector_visibility";
- field public static final java.lang.String INSTALL_NON_MARKET_APPS = "install_non_market_apps";
+ field public static final deprecated java.lang.String INSTALL_NON_MARKET_APPS = "install_non_market_apps";
field public static final java.lang.String LOCATION_MODE = "location_mode";
field public static final int LOCATION_MODE_BATTERY_SAVING = 2; // 0x2
field public static final int LOCATION_MODE_HIGH_ACCURACY = 3; // 0x3
method public boolean addPermission(android.content.pm.PermissionInfo);
method public boolean addPermissionAsync(android.content.pm.PermissionInfo);
method public void addPreferredActivity(android.content.IntentFilter, int, android.content.ComponentName[], android.content.ComponentName);
+ method public boolean canRequestPackageInstalls();
method public java.lang.String[] canonicalToCurrentPackageNames(java.lang.String[]);
method public int checkPermission(java.lang.String, java.lang.String);
method public int checkSignatures(java.lang.String, java.lang.String);
method public abstract boolean addPermission(android.content.pm.PermissionInfo);
method public abstract boolean addPermissionAsync(android.content.pm.PermissionInfo);
method public abstract deprecated void addPreferredActivity(android.content.IntentFilter, int, android.content.ComponentName[], android.content.ComponentName);
+ method public abstract boolean canRequestPackageInstalls();
method public abstract java.lang.String[] canonicalToCurrentPackageNames(java.lang.String[]);
method public abstract int checkPermission(java.lang.String, java.lang.String);
method public abstract int checkSignatures(java.lang.String, java.lang.String);
field public static final java.lang.String ACTION_MANAGE_ALL_APPLICATIONS_SETTINGS = "android.settings.MANAGE_ALL_APPLICATIONS_SETTINGS";
field public static final java.lang.String ACTION_MANAGE_APPLICATIONS_SETTINGS = "android.settings.MANAGE_APPLICATIONS_SETTINGS";
field public static final java.lang.String ACTION_MANAGE_DEFAULT_APPS_SETTINGS = "android.settings.MANAGE_DEFAULT_APPS_SETTINGS";
+ field public static final java.lang.String ACTION_MANAGE_EXTERNAL_SOURCES = "android.settings.action.MANAGE_EXTERNAL_SOURCES";
field public static final java.lang.String ACTION_MANAGE_OVERLAY_PERMISSION = "android.settings.action.MANAGE_OVERLAY_PERMISSION";
field public static final java.lang.String ACTION_MANAGE_WRITE_SETTINGS = "android.settings.action.MANAGE_WRITE_SETTINGS";
field public static final java.lang.String ACTION_MEMORY_CARD_SETTINGS = "android.settings.MEMORY_CARD_SETTINGS";
field public static final java.lang.String ENABLED_INPUT_METHODS = "enabled_input_methods";
field public static final deprecated java.lang.String HTTP_PROXY = "http_proxy";
field public static final java.lang.String INPUT_METHOD_SELECTOR_VISIBILITY = "input_method_selector_visibility";
- field public static final java.lang.String INSTALL_NON_MARKET_APPS = "install_non_market_apps";
+ field public static final deprecated java.lang.String INSTALL_NON_MARKET_APPS = "install_non_market_apps";
field public static final java.lang.String LOCATION_MODE = "location_mode";
field public static final int LOCATION_MODE_BATTERY_SAVING = 2; // 0x2
field public static final int LOCATION_MODE_HIGH_ACCURACY = 3; // 0x3
method public boolean addPermission(android.content.pm.PermissionInfo);
method public boolean addPermissionAsync(android.content.pm.PermissionInfo);
method public void addPreferredActivity(android.content.IntentFilter, int, android.content.ComponentName[], android.content.ComponentName);
+ method public boolean canRequestPackageInstalls();
method public java.lang.String[] canonicalToCurrentPackageNames(java.lang.String[]);
method public int checkPermission(java.lang.String, java.lang.String);
method public int checkSignatures(java.lang.String, java.lang.String);
method public abstract boolean addPermission(android.content.pm.PermissionInfo);
method public abstract boolean addPermissionAsync(android.content.pm.PermissionInfo);
method public abstract deprecated void addPreferredActivity(android.content.IntentFilter, int, android.content.ComponentName[], android.content.ComponentName);
+ method public abstract boolean canRequestPackageInstalls();
method public abstract java.lang.String[] canonicalToCurrentPackageNames(java.lang.String[]);
method public abstract int checkPermission(java.lang.String, java.lang.String);
method public abstract int checkSignatures(java.lang.String, java.lang.String);
field public static final java.lang.String ACTION_MANAGE_ALL_APPLICATIONS_SETTINGS = "android.settings.MANAGE_ALL_APPLICATIONS_SETTINGS";
field public static final java.lang.String ACTION_MANAGE_APPLICATIONS_SETTINGS = "android.settings.MANAGE_APPLICATIONS_SETTINGS";
field public static final java.lang.String ACTION_MANAGE_DEFAULT_APPS_SETTINGS = "android.settings.MANAGE_DEFAULT_APPS_SETTINGS";
+ field public static final java.lang.String ACTION_MANAGE_EXTERNAL_SOURCES = "android.settings.action.MANAGE_EXTERNAL_SOURCES";
field public static final java.lang.String ACTION_MANAGE_OVERLAY_PERMISSION = "android.settings.action.MANAGE_OVERLAY_PERMISSION";
field public static final java.lang.String ACTION_MANAGE_WRITE_SETTINGS = "android.settings.action.MANAGE_WRITE_SETTINGS";
field public static final java.lang.String ACTION_MEMORY_CARD_SETTINGS = "android.settings.MEMORY_CARD_SETTINGS";
field public static final java.lang.String ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES = "enabled_notification_policy_access_packages";
field public static final deprecated java.lang.String HTTP_PROXY = "http_proxy";
field public static final java.lang.String INPUT_METHOD_SELECTOR_VISIBILITY = "input_method_selector_visibility";
- field public static final java.lang.String INSTALL_NON_MARKET_APPS = "install_non_market_apps";
+ field public static final deprecated java.lang.String INSTALL_NON_MARKET_APPS = "install_non_market_apps";
field public static final java.lang.String LOCATION_MODE = "location_mode";
field public static final int LOCATION_MODE_BATTERY_SAVING = 2; // 0x2
field public static final int LOCATION_MODE_HIGH_ACCURACY = 3; // 0x3
method public boolean addPermission(android.content.pm.PermissionInfo);
method public boolean addPermissionAsync(android.content.pm.PermissionInfo);
method public void addPreferredActivity(android.content.IntentFilter, int, android.content.ComponentName[], android.content.ComponentName);
+ method public boolean canRequestPackageInstalls();
method public java.lang.String[] canonicalToCurrentPackageNames(java.lang.String[]);
method public int checkPermission(java.lang.String, java.lang.String);
method public int checkSignatures(java.lang.String, java.lang.String);
return false;
}
}
+
+ @Override
+ public boolean canRequestPackageInstalls() {
+ try {
+ return mPM.canRequestPackageInstalls(mContext.getPackageName(), mContext.getUserId());
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
+ }
}
int getInstallReason(String packageName, int userId);
ParceledListSlice getSharedLibraries(int flags, int userId);
+
+ boolean canRequestPackageInstalls(String packageName, int userId);
}
@TestApi
public abstract @InstallReason int getInstallReason(String packageName,
@NonNull UserHandle user);
+
+ /**
+ * Checks whether the calling package is allowed to request package installs through package
+ * installer. Apps are encouraged to call this api before launching the package installer via
+ * intent {@link android.content.Intent#ACTION_INSTALL_PACKAGE}. Starting from Android O, the
+ * user can explicitly choose what external sources they trust to install apps on the device.
+ * If this api returns false, the install request will be blocked by the package installer and
+ * a dialog will be shown to the user with an option to launch settings to change their
+ * preference. An application must target Android O or higher and declare permission
+ * {@link android.Manifest.permission#REQUEST_INSTALL_PACKAGES} in order to use this api.
+ *
+ * @return true if the calling package is trusted by the user to request install packages on
+ * the device, false otherwise.
+ * @see {@link android.content.Intent#ACTION_INSTALL_PACKAGE}
+ * @see {@link android.provider.Settings#ACTION_MANAGE_EXTERNAL_SOURCES}
+ */
+ public abstract boolean canRequestPackageInstalls();
}
* @return The SetupWizard package name.
*/
public abstract String getSetupWizardPackageName();
+
+ public interface ExternalSourcesPolicy {
+
+ int USER_TRUSTED = 0; // User has trusted the package to install apps
+ int USER_BLOCKED = 1; // User has blocked the package to install apps
+ int USER_DEFAULT = 2; // Default code to use when user response is unavailable
+
+ /**
+ * Checks the user preference for whether a package is trusted to request installs through
+ * package installer
+ *
+ * @param packageName The package to check for
+ * @param uid the uid in which the package is running
+ * @return {@link USER_TRUSTED} if the user has trusted the package, {@link USER_BLOCKED}
+ * if user has blocked requests from the package, {@link USER_DEFAULT} if the user response
+ * is not yet available
+ */
+ int getPackageTrustedToInstallApps(String packageName, int uid);
+ }
+
+ public abstract void setExternalSourcesPolicy(ExternalSourcesPolicy policy);
}
* Input: Nothing.
* <p>
* Output: Nothing.
- * @hide
*/
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_MANAGE_EXTERNAL_SOURCES =
*
* <p>1 = permit app installation via the system package installer intent
* <p>0 = do not allow use of the package installer
+ * @deprecated Starting from {@link android.os.Build.VERSION_CODES#O}, apps should use
+ * {@link PackageManager#canRequestPackageInstalls()}
+ * @see PackageManager#canRequestPackageInstalls()
*/
public static final String INSTALL_NON_MARKET_APPS = "install_non_market_apps";
<!-- Allows an application to request installing packages. Apps
targeting APIs greater than 25 must hold this permission in
order to use {@link android.content.Intent#ACTION_INSTALL_PACKAGE}.
- <p>Protection level: normal
+ <p>Protection level: signature
-->
<permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"
android:label="@string/permlab_requestInstallPackages"
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
import android.media.AudioAttributes;
import android.os.AsyncTask;
import android.os.Binder;
}
}
+ PackageManagerInternal packageManagerInternal = LocalServices.getService(
+ PackageManagerInternal.class);
+ packageManagerInternal.setExternalSourcesPolicy(
+ new PackageManagerInternal.ExternalSourcesPolicy() {
+ @Override
+ public int getPackageTrustedToInstallApps(String packageName, int uid) {
+ int appOpMode = checkOperation(AppOpsManager.OP_REQUEST_INSTALL_PACKAGES,
+ uid, packageName);
+ switch (appOpMode) {
+ case AppOpsManager.MODE_ALLOWED:
+ return PackageManagerInternal.ExternalSourcesPolicy.USER_TRUSTED;
+ case AppOpsManager.MODE_ERRORED:
+ return PackageManagerInternal.ExternalSourcesPolicy.USER_BLOCKED;
+ default:
+ return PackageManagerInternal.ExternalSourcesPolicy.USER_DEFAULT;
+ }
+ }
+ });
+
StorageManagerInternal storageManagerInternal = LocalServices.getService(
StorageManagerInternal.class);
storageManagerInternal.addExternalStoragePolicy(
boolean mFirstBoot;
+ PackageManagerInternal.ExternalSourcesPolicy mExternalSourcesPolicy;
+
// System configuration read by SystemConfig.
final int[] mGlobalGids;
final SparseArray<ArraySet<String>> mSystemPermissions;
public String getSetupWizardPackageName() {
return mSetupWizardPackage;
}
+
+ public void setExternalSourcesPolicy(ExternalSourcesPolicy policy) {
+ if (policy != null) {
+ mExternalSourcesPolicy = policy;
+ }
+ }
}
@Override
}
return PackageManager.INSTALL_REASON_UNKNOWN;
}
+
+ @Override
+ public boolean canRequestPackageInstalls(String packageName, int userId) {
+ int callingUid = Binder.getCallingUid();
+ int uid = getPackageUid(packageName, 0, userId);
+ if (callingUid != uid && callingUid != Process.ROOT_UID
+ && callingUid != Process.SYSTEM_UID) {
+ throw new SecurityException(
+ "Caller uid " + callingUid + " does not own package " + packageName);
+ }
+ ApplicationInfo info = getApplicationInfo(packageName, 0, userId);
+ if (info == null) {
+ return false;
+ }
+ if (info.targetSdkVersion < Build.VERSION_CODES.O) {
+ throw new UnsupportedOperationException(
+ "Operation only supported on apps targeting Android O or higher");
+ }
+ String appOpPermission = Manifest.permission.REQUEST_INSTALL_PACKAGES;
+ String[] packagesDeclaringPermission = getAppOpPermissionPackages(appOpPermission);
+ if (!ArrayUtils.contains(packagesDeclaringPermission, packageName)) {
+ throw new SecurityException("Need to declare " + appOpPermission + " to call this api");
+ }
+ if (sUserManager.hasUserRestriction(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, userId)) {
+ return false;
+ }
+ if (mExternalSourcesPolicy != null) {
+ int isTrusted = mExternalSourcesPolicy.getPackageTrustedToInstallApps(packageName, uid);
+ if (isTrusted != PackageManagerInternal.ExternalSourcesPolicy.USER_DEFAULT) {
+ return isTrusted == PackageManagerInternal.ExternalSourcesPolicy.USER_TRUSTED;
+ }
+ }
+ return checkUidPermission(appOpPermission, uid) == PERMISSION_GRANTED;
+ }
}
}
@Override
+ public boolean canRequestPackageInstalls() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
public boolean isPermissionRevokedByPolicy(String permName, String pkgName) {
throw new UnsupportedOperationException();
}
public int getInstallReason(String packageName, UserHandle user) {
return INSTALL_REASON_UNKNOWN;
}
+
+ @Override
+ public boolean canRequestPackageInstalls() {
+ return false;
+ }
}