Merge "Perform user restriction check before creating install session" into udc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
63ff47ecc8
@@ -20,6 +20,8 @@ import static com.android.packageinstaller.PackageUtil.getMaxTargetSdkVersionFor
|
||||
|
||||
import android.Manifest;
|
||||
import android.app.Activity;
|
||||
import android.app.DialogFragment;
|
||||
import android.app.admin.DevicePolicyManager;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
@@ -31,6 +33,8 @@ import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Process;
|
||||
import android.os.UserManager;
|
||||
import android.provider.Settings;
|
||||
import android.text.TextUtils;
|
||||
import android.util.EventLog;
|
||||
import android.util.Log;
|
||||
@@ -45,16 +49,24 @@ import java.util.Arrays;
|
||||
* it.
|
||||
*/
|
||||
public class InstallStart extends Activity {
|
||||
private static final String LOG_TAG = InstallStart.class.getSimpleName();
|
||||
private static final String TAG = InstallStart.class.getSimpleName();
|
||||
|
||||
private static final String DOWNLOADS_AUTHORITY = "downloads";
|
||||
|
||||
private static final int DLG_INSTALL_APPS_RESTRICTED_FOR_USER = 1;
|
||||
private static final int DLG_UNKNOWN_SOURCES_RESTRICTED_FOR_USER = 2;
|
||||
private PackageManager mPackageManager;
|
||||
private UserManager mUserManager;
|
||||
private boolean mAbortInstall = false;
|
||||
|
||||
private final boolean mLocalLOGV = false;
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
mPackageManager = getPackageManager();
|
||||
mUserManager = getSystemService(UserManager.class);
|
||||
|
||||
Intent intent = getIntent();
|
||||
String callingPackage = getCallingPackage();
|
||||
String callingAttributionTag = null;
|
||||
@@ -80,8 +92,7 @@ public class InstallStart extends Activity {
|
||||
// Uid of the source package, coming from ActivityManager
|
||||
int callingUid = getLaunchedFromUid();
|
||||
if (callingUid == Process.INVALID_UID) {
|
||||
// Cannot reach ActivityManager. Aborting install.
|
||||
Log.e(LOG_TAG, "Could not determine the launching uid.");
|
||||
Log.e(TAG, "Could not determine the launching uid.");
|
||||
}
|
||||
// Uid of the source package, with a preference to uid from ApplicationInfo
|
||||
final int originatingUid = sourceInfo != null ? sourceInfo.uid : callingUid;
|
||||
@@ -104,12 +115,12 @@ public class InstallStart extends Activity {
|
||||
&& originatingUid != Process.INVALID_UID) {
|
||||
final int targetSdkVersion = getMaxTargetSdkVersionForUid(this, originatingUid);
|
||||
if (targetSdkVersion < 0) {
|
||||
Log.w(LOG_TAG, "Cannot get target sdk version for uid " + originatingUid);
|
||||
Log.w(TAG, "Cannot get target sdk version for uid " + originatingUid);
|
||||
// Invalid originating uid supplied. Abort install.
|
||||
mAbortInstall = true;
|
||||
} else if (targetSdkVersion >= Build.VERSION_CODES.O && !isUidRequestingPermission(
|
||||
originatingUid, Manifest.permission.REQUEST_INSTALL_PACKAGES)) {
|
||||
Log.e(LOG_TAG, "Requesting uid " + originatingUid + " needs to declare permission "
|
||||
Log.e(TAG, "Requesting uid " + originatingUid + " needs to declare permission "
|
||||
+ Manifest.permission.REQUEST_INSTALL_PACKAGES);
|
||||
mAbortInstall = true;
|
||||
}
|
||||
@@ -119,6 +130,8 @@ public class InstallStart extends Activity {
|
||||
mAbortInstall = true;
|
||||
}
|
||||
|
||||
checkDevicePolicyRestriction();
|
||||
|
||||
final String installerPackageNameFromIntent = getIntent().getStringExtra(
|
||||
Intent.EXTRA_INSTALLER_PACKAGE_NAME);
|
||||
if (installerPackageNameFromIntent != null) {
|
||||
@@ -126,7 +139,7 @@ public class InstallStart extends Activity {
|
||||
if (!TextUtils.equals(installerPackageNameFromIntent, callingPkgName)
|
||||
&& mPackageManager.checkPermission(Manifest.permission.INSTALL_PACKAGES,
|
||||
callingPkgName) != PackageManager.PERMISSION_GRANTED) {
|
||||
Log.e(LOG_TAG, "The given installer package name " + installerPackageNameFromIntent
|
||||
Log.e(TAG, "The given installer package name " + installerPackageNameFromIntent
|
||||
+ " is invalid. Remove it.");
|
||||
EventLog.writeEvent(0x534e4554, "236687884", getLaunchedFromUid(),
|
||||
"Invalid EXTRA_INSTALLER_PACKAGE_NAME");
|
||||
@@ -270,4 +283,97 @@ public class InstallStart extends Activity {
|
||||
int installerUid = packageInstaller.getSessionInfo(sessionId).getInstallerUid();
|
||||
return (originatingUid == Process.ROOT_UID) || (originatingUid == installerUid);
|
||||
}
|
||||
|
||||
private void checkDevicePolicyRestriction() {
|
||||
// Check for install apps user restriction first.
|
||||
final int installAppsRestrictionSource = mUserManager.getUserRestrictionSource(
|
||||
UserManager.DISALLOW_INSTALL_APPS, Process.myUserHandle());
|
||||
if ((installAppsRestrictionSource & UserManager.RESTRICTION_SOURCE_SYSTEM) != 0) {
|
||||
if (mLocalLOGV) Log.i(TAG, "install not allowed: " + UserManager.DISALLOW_INSTALL_APPS);
|
||||
mAbortInstall = true;
|
||||
showDialogInner(DLG_INSTALL_APPS_RESTRICTED_FOR_USER);
|
||||
return;
|
||||
} else if (installAppsRestrictionSource != UserManager.RESTRICTION_NOT_SET) {
|
||||
if (mLocalLOGV) {
|
||||
Log.i(TAG, "install not allowed by admin; showing "
|
||||
+ Settings.ACTION_SHOW_ADMIN_SUPPORT_DETAILS);
|
||||
}
|
||||
mAbortInstall = true;
|
||||
startActivity(new Intent(Settings.ACTION_SHOW_ADMIN_SUPPORT_DETAILS));
|
||||
return;
|
||||
}
|
||||
|
||||
final int unknownSourcesRestrictionSource = mUserManager.getUserRestrictionSource(
|
||||
UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, Process.myUserHandle());
|
||||
final int unknownSourcesGlobalRestrictionSource = mUserManager.getUserRestrictionSource(
|
||||
UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY, Process.myUserHandle());
|
||||
final int systemRestriction = UserManager.RESTRICTION_SOURCE_SYSTEM
|
||||
& (unknownSourcesRestrictionSource | unknownSourcesGlobalRestrictionSource);
|
||||
if (systemRestriction != 0) {
|
||||
if (mLocalLOGV) Log.i(TAG, "Showing DLG_UNKNOWN_SOURCES_RESTRICTED_FOR_USER");
|
||||
mAbortInstall = true;
|
||||
showDialogInner(DLG_UNKNOWN_SOURCES_RESTRICTED_FOR_USER);
|
||||
} else if (unknownSourcesRestrictionSource != UserManager.RESTRICTION_NOT_SET) {
|
||||
mAbortInstall = true;
|
||||
startAdminSupportDetailsActivity(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES);
|
||||
} else if (unknownSourcesGlobalRestrictionSource != UserManager.RESTRICTION_NOT_SET) {
|
||||
mAbortInstall = true;
|
||||
startAdminSupportDetailsActivity(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace any dialog shown by the dialog with the one for the given {@link #createDialog(int)}.
|
||||
*
|
||||
* @param id The dialog type to add
|
||||
*/
|
||||
private void showDialogInner(int id) {
|
||||
if (mLocalLOGV) Log.i(TAG, "showDialogInner(" + id + ")");
|
||||
DialogFragment currentDialog =
|
||||
(DialogFragment) getFragmentManager().findFragmentByTag("dialog");
|
||||
if (currentDialog != null) {
|
||||
currentDialog.dismissAllowingStateLoss();
|
||||
}
|
||||
|
||||
DialogFragment newDialog = createDialog(id);
|
||||
if (newDialog != null) {
|
||||
getFragmentManager().beginTransaction()
|
||||
.add(newDialog, "dialog").commitAllowingStateLoss();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new dialog.
|
||||
*
|
||||
* @param id The id of the dialog (determines dialog type)
|
||||
*
|
||||
* @return The dialog
|
||||
*/
|
||||
private DialogFragment createDialog(int id) {
|
||||
if (mLocalLOGV) Log.i(TAG, "createDialog(" + id + ")");
|
||||
switch (id) {
|
||||
case DLG_INSTALL_APPS_RESTRICTED_FOR_USER:
|
||||
return PackageUtil.SimpleErrorDialog.newInstance(
|
||||
R.string.install_apps_user_restriction_dlg_text);
|
||||
case DLG_UNKNOWN_SOURCES_RESTRICTED_FOR_USER:
|
||||
return PackageUtil.SimpleErrorDialog.newInstance(
|
||||
R.string.unknown_apps_user_restriction_dlg_text);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void startAdminSupportDetailsActivity(String restriction) {
|
||||
if (mLocalLOGV) Log.i(TAG, "startAdminSupportDetailsActivity(): " + restriction);
|
||||
|
||||
// If the given restriction is set by an admin, display information about the
|
||||
// admin enforcing the restriction for the affected user.
|
||||
final DevicePolicyManager dpm = getSystemService(DevicePolicyManager.class);
|
||||
final Intent showAdminSupportDetailsIntent = dpm.createAdminSupportIntent(restriction);
|
||||
if (showAdminSupportDetailsIntent != null) {
|
||||
if (mLocalLOGV) Log.i(TAG, "starting " + showAdminSupportDetailsIntent);
|
||||
startActivity(showAdminSupportDetailsIntent);
|
||||
} else {
|
||||
if (mLocalLOGV) Log.w(TAG, "not intent for " + restriction);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,6 @@ import android.app.AlertDialog;
|
||||
import android.app.AppOpsManager;
|
||||
import android.app.Dialog;
|
||||
import android.app.DialogFragment;
|
||||
import android.app.admin.DevicePolicyManager;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
@@ -56,7 +55,6 @@ import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.StringRes;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
@@ -123,13 +121,11 @@ public class PackageInstallerActivity extends AlertActivity {
|
||||
|
||||
// Dialog identifiers used in showDialog
|
||||
private static final int DLG_BASE = 0;
|
||||
private static final int DLG_PACKAGE_ERROR = DLG_BASE + 2;
|
||||
private static final int DLG_OUT_OF_SPACE = DLG_BASE + 3;
|
||||
private static final int DLG_INSTALL_ERROR = DLG_BASE + 4;
|
||||
private static final int DLG_UNKNOWN_SOURCES_RESTRICTED_FOR_USER = DLG_BASE + 5;
|
||||
private static final int DLG_ANONYMOUS_SOURCE = DLG_BASE + 6;
|
||||
private static final int DLG_EXTERNAL_SOURCE_BLOCKED = DLG_BASE + 7;
|
||||
private static final int DLG_INSTALL_APPS_RESTRICTED_FOR_USER = DLG_BASE + 8;
|
||||
private static final int DLG_PACKAGE_ERROR = DLG_BASE + 1;
|
||||
private static final int DLG_OUT_OF_SPACE = DLG_BASE + 2;
|
||||
private static final int DLG_INSTALL_ERROR = DLG_BASE + 3;
|
||||
private static final int DLG_ANONYMOUS_SOURCE = DLG_BASE + 4;
|
||||
private static final int DLG_EXTERNAL_SOURCE_BLOCKED = DLG_BASE + 5;
|
||||
|
||||
// If unknown sources are temporary allowed
|
||||
private boolean mAllowUnknownSources;
|
||||
@@ -218,19 +214,13 @@ public class PackageInstallerActivity extends AlertActivity {
|
||||
if (mLocalLOGV) Log.i(TAG, "createDialog(" + id + ")");
|
||||
switch (id) {
|
||||
case DLG_PACKAGE_ERROR:
|
||||
return SimpleErrorDialog.newInstance(R.string.Parse_error_dlg_text);
|
||||
return PackageUtil.SimpleErrorDialog.newInstance(R.string.Parse_error_dlg_text);
|
||||
case DLG_OUT_OF_SPACE:
|
||||
return OutOfSpaceDialog.newInstance(
|
||||
mPm.getApplicationLabel(mPkgInfo.applicationInfo));
|
||||
case DLG_INSTALL_ERROR:
|
||||
return InstallErrorDialog.newInstance(
|
||||
mPm.getApplicationLabel(mPkgInfo.applicationInfo));
|
||||
case DLG_INSTALL_APPS_RESTRICTED_FOR_USER:
|
||||
return SimpleErrorDialog.newInstance(
|
||||
R.string.install_apps_user_restriction_dlg_text);
|
||||
case DLG_UNKNOWN_SOURCES_RESTRICTED_FOR_USER:
|
||||
return SimpleErrorDialog.newInstance(
|
||||
R.string.unknown_apps_user_restriction_dlg_text);
|
||||
case DLG_EXTERNAL_SOURCE_BLOCKED:
|
||||
return ExternalSourcesBlockedDialog.newInstance(mOriginatingPackage);
|
||||
case DLG_ANONYMOUS_SOURCE:
|
||||
@@ -524,69 +514,17 @@ public class PackageInstallerActivity extends AlertActivity {
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if it is allowed to install the package and initiate install if allowed. If not allowed
|
||||
* show the appropriate dialog.
|
||||
* Check if it is allowed to install the package and initiate install if allowed.
|
||||
*/
|
||||
private void checkIfAllowedAndInitiateInstall() {
|
||||
// Check for install apps user restriction first.
|
||||
final int installAppsRestrictionSource = mUserManager.getUserRestrictionSource(
|
||||
UserManager.DISALLOW_INSTALL_APPS, Process.myUserHandle());
|
||||
if ((installAppsRestrictionSource & UserManager.RESTRICTION_SOURCE_SYSTEM) != 0) {
|
||||
if (mLocalLOGV) Log.i(TAG, "install not allowed: " + UserManager.DISALLOW_INSTALL_APPS);
|
||||
showDialogInner(DLG_INSTALL_APPS_RESTRICTED_FOR_USER);
|
||||
return;
|
||||
} else if (installAppsRestrictionSource != UserManager.RESTRICTION_NOT_SET) {
|
||||
if (mLocalLOGV) {
|
||||
Log.i(TAG, "install not allowed by admin; showing "
|
||||
+ Settings.ACTION_SHOW_ADMIN_SUPPORT_DETAILS);
|
||||
}
|
||||
startActivity(new Intent(Settings.ACTION_SHOW_ADMIN_SUPPORT_DETAILS));
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
if (mAllowUnknownSources || !isInstallRequestFromUnknownSource(getIntent())) {
|
||||
if (mLocalLOGV) Log.i(TAG, "install allowed");
|
||||
initiateInstall();
|
||||
} else {
|
||||
// Check for unknown sources restrictions.
|
||||
final int unknownSourcesRestrictionSource = mUserManager.getUserRestrictionSource(
|
||||
UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, Process.myUserHandle());
|
||||
final int unknownSourcesGlobalRestrictionSource = mUserManager.getUserRestrictionSource(
|
||||
UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY, Process.myUserHandle());
|
||||
final int systemRestriction = UserManager.RESTRICTION_SOURCE_SYSTEM
|
||||
& (unknownSourcesRestrictionSource | unknownSourcesGlobalRestrictionSource);
|
||||
if (systemRestriction != 0) {
|
||||
if (mLocalLOGV) Log.i(TAG, "Showing DLG_UNKNOWN_SOURCES_RESTRICTED_FOR_USER");
|
||||
showDialogInner(DLG_UNKNOWN_SOURCES_RESTRICTED_FOR_USER);
|
||||
} else if (unknownSourcesRestrictionSource != UserManager.RESTRICTION_NOT_SET) {
|
||||
startAdminSupportDetailsActivity(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES);
|
||||
} else if (unknownSourcesGlobalRestrictionSource != UserManager.RESTRICTION_NOT_SET) {
|
||||
startAdminSupportDetailsActivity(
|
||||
UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY);
|
||||
} else {
|
||||
handleUnknownSources();
|
||||
}
|
||||
handleUnknownSources();
|
||||
}
|
||||
}
|
||||
|
||||
private void startAdminSupportDetailsActivity(String restriction) {
|
||||
if (mLocalLOGV) Log.i(TAG, "startAdminSupportDetailsActivity(): " + restriction);
|
||||
|
||||
// If the given restriction is set by an admin, display information about the
|
||||
// admin enforcing the restriction for the affected user.
|
||||
final DevicePolicyManager dpm = getSystemService(DevicePolicyManager.class);
|
||||
final Intent showAdminSupportDetailsIntent = dpm.createAdminSupportIntent(restriction);
|
||||
if (showAdminSupportDetailsIntent != null) {
|
||||
if (mLocalLOGV) Log.i(TAG, "starting " + showAdminSupportDetailsIntent);
|
||||
startActivity(showAdminSupportDetailsIntent);
|
||||
} else {
|
||||
if (mLocalLOGV) Log.w(TAG, "not intent for " + restriction);
|
||||
}
|
||||
|
||||
finish();
|
||||
}
|
||||
|
||||
private void handleUnknownSources() {
|
||||
if (mOriginatingPackage == null) {
|
||||
Log.i(TAG, "No source found for package " + mPkgInfo.packageName);
|
||||
@@ -761,38 +699,6 @@ public class PackageInstallerActivity extends AlertActivity {
|
||||
finish();
|
||||
}
|
||||
|
||||
/**
|
||||
* A simple error dialog showing a message
|
||||
*/
|
||||
public static class SimpleErrorDialog extends DialogFragment {
|
||||
private static final String MESSAGE_KEY =
|
||||
SimpleErrorDialog.class.getName() + "MESSAGE_KEY";
|
||||
|
||||
static SimpleErrorDialog newInstance(@StringRes int message) {
|
||||
SimpleErrorDialog dialog = new SimpleErrorDialog();
|
||||
|
||||
Bundle args = new Bundle();
|
||||
args.putInt(MESSAGE_KEY, message);
|
||||
dialog.setArguments(args);
|
||||
|
||||
return dialog;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
return new AlertDialog.Builder(getActivity())
|
||||
.setMessage(getArguments().getInt(MESSAGE_KEY))
|
||||
.setPositiveButton(R.string.ok, (dialog, which) -> getActivity().finish())
|
||||
.create();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancel(DialogInterface dialog) {
|
||||
getActivity().setResult(Activity.RESULT_CANCELED);
|
||||
getActivity().finish();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Dialog to show when the source of apk can not be identified
|
||||
*/
|
||||
|
||||
@@ -18,12 +18,17 @@
|
||||
package com.android.packageinstaller;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.app.DialogFragment;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Bundle;
|
||||
import android.os.UserHandle;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
@@ -32,6 +37,7 @@ import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.StringRes;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.File;
|
||||
@@ -207,4 +213,36 @@ public class PackageUtil {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A simple error dialog showing a message
|
||||
*/
|
||||
public static class SimpleErrorDialog extends DialogFragment {
|
||||
private static final String MESSAGE_KEY =
|
||||
SimpleErrorDialog.class.getName() + "MESSAGE_KEY";
|
||||
|
||||
static SimpleErrorDialog newInstance(@StringRes int message) {
|
||||
SimpleErrorDialog dialog = new SimpleErrorDialog();
|
||||
|
||||
Bundle args = new Bundle();
|
||||
args.putInt(MESSAGE_KEY, message);
|
||||
dialog.setArguments(args);
|
||||
|
||||
return dialog;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
return new AlertDialog.Builder(getActivity())
|
||||
.setMessage(getArguments().getInt(MESSAGE_KEY))
|
||||
.setPositiveButton(R.string.ok, (dialog, which) -> getActivity().finish())
|
||||
.create();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancel(DialogInterface dialog) {
|
||||
getActivity().setResult(Activity.RESULT_CANCELED);
|
||||
getActivity().finish();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user