primaryUserAppList = mPackageManager
.queryIntentActivities(launcherIntent, 0);
if (primaryUserAppList.isEmpty()) {
showToast(R.string.no_primary_app_available);
} else {
Collections.sort(primaryUserAppList,
new ResolveInfo.DisplayNameComparator(mPackageManager));
final LockTaskAppInfoArrayAdapter appInfoArrayAdapter = new LockTaskAppInfoArrayAdapter(
getActivity(), R.id.pkg_name, primaryUserAppList);
ListView listView = new ListView(getActivity());
listView.setAdapter(appInfoArrayAdapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView> parent, View view, int position, long id) {
appInfoArrayAdapter.onItemClick(parent, view, position, id);
}
});
new AlertDialog.Builder(getActivity())
.setTitle(getString(dialogTitle))
.setView(listView)
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
String[] lockTaskEnabledArray = appInfoArrayAdapter.getLockTaskList();
callback.onPositiveButtonClicked(lockTaskEnabledArray);
}
})
.setNegativeButton(android.R.string.cancel,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
})
.show();
}
}
/**
* Shows a prompt to collect a package name and checks whether the lock task for the
* corresponding app is permitted or not.
*/
private void showCheckLockTaskPermittedPrompt() {
if (getActivity() == null || getActivity().isFinishing()) {
return;
}
View view = getActivity().getLayoutInflater().inflate(R.layout.simple_edittext, null);
final EditText input = (EditText) view.findViewById(R.id.input);
input.setHint(getString(R.string.input_package_name_hints));
new AlertDialog.Builder(getActivity())
.setTitle(getString(R.string.check_lock_task_permitted))
.setView(view)
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
String packageName = input.getText().toString();
boolean isLockTaskPermitted = mDevicePolicyManager
.isLockTaskPermitted(packageName);
showToast(isLockTaskPermitted
? R.string.check_lock_task_permitted_result_permitted
: R.string.check_lock_task_permitted_result_not_permitted);
dialog.dismiss();
}
})
.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
})
.show();
}
/**
* Shows a prompt to ask for a password to reset to and to set whether this requires
* re-entry before any further changes and/or whether the password needs to be entered during
* boot to start the user.
*/
private void showResetPasswordPrompt() {
View dialogView = getActivity().getLayoutInflater().inflate(
R.layout.reset_password_dialog, null);
final EditText passwordView = (EditText) dialogView.findViewById(
R.id.password);
final CheckBox requireEntry = (CheckBox) dialogView.findViewById(
R.id.require_password_entry_checkbox);
final CheckBox dontRequireOnBoot = (CheckBox) dialogView.findViewById(
R.id.dont_require_password_on_boot_checkbox);
DialogInterface.OnClickListener resetListener = new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int which) {
String password = passwordView.getText().toString();
if (TextUtils.isEmpty(password)) {
password = null;
}
int flags = 0;
flags |= requireEntry.isChecked() ?
DevicePolicyManager.RESET_PASSWORD_REQUIRE_ENTRY : 0;
flags |= dontRequireOnBoot.isChecked() ?
DevicePolicyManager.RESET_PASSWORD_DO_NOT_ASK_CREDENTIALS_ON_BOOT : 0;
boolean ok = false;
try {
ok = mDevicePolicyManager.resetPassword(password, flags);
} catch (IllegalArgumentException | IllegalStateException | SecurityException e) {
// Not allowed to set password or trying to set a bad password, eg. 2 characters
// where system minimum length is 4.
Log.w(TAG, "Failed to reset password", e);
}
showToast(ok ? R.string.password_reset_success : R.string.password_reset_failed);
}
};
new AlertDialog.Builder(getActivity())
.setTitle(R.string.reset_password)
.setView(dialogView)
.setPositiveButton(android.R.string.ok, resetListener)
.setNegativeButton(android.R.string.cancel, null)
.show();
}
/**
* Shows a prompt to ask for confirmation on wiping the data and also provide an option
* to set if external storage and factory reset protection data also needs to wiped.
*/
private void showWipeDataPrompt() {
final LayoutInflater inflater = getActivity().getLayoutInflater();
final View dialogView = inflater.inflate(R.layout.wipe_data_dialog_prompt, null);
final CheckBox externalStorageCheckBox = (CheckBox) dialogView.findViewById(
R.id.external_storage_checkbox);
final CheckBox resetProtectionCheckBox = (CheckBox) dialogView.findViewById(
R.id.reset_protection_checkbox);
new AlertDialog.Builder(getActivity())
.setTitle(R.string.wipe_data_title)
.setView(dialogView)
.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
int flags = 0;
flags |= (externalStorageCheckBox.isChecked() ?
DevicePolicyManager.WIPE_EXTERNAL_STORAGE : 0);
flags |= (resetProtectionCheckBox.isChecked() ?
DevicePolicyManager.WIPE_RESET_PROTECTION_DATA : 0);
mDevicePolicyManager.wipeData(flags);
}
})
.setNegativeButton(android.R.string.cancel, null)
.show();
}
/**
* Shows a prompt to ask for confirmation on removing device owner.
*/
private void showRemoveDeviceOwnerPrompt() {
new AlertDialog.Builder(getActivity())
.setTitle(R.string.remove_device_owner_title)
.setMessage(R.string.remove_device_owner_confirmation)
.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
mDevicePolicyManager.clearDeviceOwnerApp(mPackageName);
if (getActivity() != null && !getActivity().isFinishing()) {
showToast(R.string.device_owner_removed);
getActivity().finish();
}
}
})
.setNegativeButton(android.R.string.cancel, null)
.show();
}
/**
* Shows a message box with the device wifi mac address.
*/
@TargetApi(Build.VERSION_CODES.N)
private void showWifiMacAddress() {
final String macAddress = mDevicePolicyManager.getWifiMacAddress(mAdminComponentName);
final String message = macAddress != null ? macAddress
: getResources().getString(R.string.show_wifi_mac_address_not_available_msg);
new AlertDialog.Builder(getActivity())
.setTitle(R.string.show_wifi_mac_address_title)
.setMessage(message)
.setPositiveButton(android.R.string.ok, null)
.show();
}
private void setPreferenceChangeListeners(String[] preferenceKeys) {
for (String key : preferenceKeys) {
findPreference(key).setOnPreferenceChangeListener(this);
}
}
/**
* Update the preference switch for {@link Settings.Global#STAY_ON_WHILE_PLUGGED_IN} setting.
*
*
* If either one of the {@link BatteryManager#BATTERY_PLUGGED_AC},
* {@link BatteryManager#BATTERY_PLUGGED_USB}, {@link BatteryManager#BATTERY_PLUGGED_WIRELESS}
* values is set, we toggle the preference to true and update the setting value to
* {@link #BATTERY_PLUGGED_ANY}
*
*/
private void updateStayOnWhilePluggedInPreference() {
if (!mStayOnWhilePluggedInSwitchPreference.isEnabled()) {
return;
}
boolean checked = false;
final int currentState = Settings.Global.getInt(getActivity().getContentResolver(),
Settings.Global.STAY_ON_WHILE_PLUGGED_IN, 0);
checked = (currentState &
(BatteryManager.BATTERY_PLUGGED_AC |
BatteryManager.BATTERY_PLUGGED_USB |
BatteryManager.BATTERY_PLUGGED_WIRELESS)) != 0;
mDevicePolicyManager.setGlobalSetting(mAdminComponentName,
Settings.Global.STAY_ON_WHILE_PLUGGED_IN,
checked ? BATTERY_PLUGGED_ANY : DONT_STAY_ON);
mStayOnWhilePluggedInSwitchPreference.setChecked(checked);
}
/**
* Update the preference switch for {@link Settings.Secure#INSTALL_NON_MARKET_APPS} setting.
*
*
* If the user restriction {@link UserManager#DISALLOW_INSTALL_UNKNOWN_SOURCES} is set, then
* we disable this preference.
*
*/
public void updateInstallNonMarketAppsPreference() {
int isInstallNonMarketAppsAllowed = Settings.Secure.getInt(
getActivity().getContentResolver(), Settings.Secure.INSTALL_NON_MARKET_APPS, 0);
mInstallNonMarketAppsPreference.setChecked(
isInstallNonMarketAppsAllowed == 0 ? false : true);
}
/**
* Shows the default response for future runtime permission requests by applications, and lets
* the user change the default value.
*/
@TargetApi(Build.VERSION_CODES.M)
private void showSetPermissionPolicyDialog() {
if (getActivity() == null || getActivity().isFinishing()) {
return;
}
View setPermissionPolicyView = getActivity().getLayoutInflater().inflate(
R.layout.set_permission_policy, null);
final RadioGroup permissionGroup =
(RadioGroup) setPermissionPolicyView.findViewById(R.id.set_permission_group);
int permissionPolicy = mDevicePolicyManager.getPermissionPolicy(mAdminComponentName);
switch (permissionPolicy) {
case DevicePolicyManager.PERMISSION_POLICY_PROMPT:
((RadioButton) permissionGroup.findViewById(R.id.prompt)).toggle();
break;
case DevicePolicyManager.PERMISSION_POLICY_AUTO_GRANT:
((RadioButton) permissionGroup.findViewById(R.id.accept)).toggle();
break;
case DevicePolicyManager.PERMISSION_POLICY_AUTO_DENY:
((RadioButton) permissionGroup.findViewById(R.id.deny)).toggle();
break;
}
new AlertDialog.Builder(getActivity())
.setTitle(getString(R.string.set_default_permission_policy))
.setView(setPermissionPolicyView)
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
int policy = 0;
int checked = permissionGroup.getCheckedRadioButtonId();
switch (checked) {
case (R.id.prompt):
policy = DevicePolicyManager.PERMISSION_POLICY_PROMPT;
break;
case (R.id.accept):
policy = DevicePolicyManager.PERMISSION_POLICY_AUTO_GRANT;
break;
case (R.id.deny):
policy = DevicePolicyManager.PERMISSION_POLICY_AUTO_DENY;
break;
}
mDevicePolicyManager.setPermissionPolicy(mAdminComponentName, policy);
dialog.dismiss();
}
})
.show();
}
/**
* Shows a prompt that allows entering the account type for which account management should be
* disabled or enabled.
*/
private void showSetDisableAccountManagementPrompt() {
if (getActivity() == null || getActivity().isFinishing()) {
return;
}
View view = LayoutInflater.from(getActivity()).inflate(R.layout.simple_edittext, null);
final EditText input = (EditText) view.findViewById(R.id.input);
input.setHint(R.string.account_type_hint);
new AlertDialog.Builder(getActivity())
.setTitle(R.string.set_disable_account_management)
.setView(view)
.setPositiveButton(R.string.disable, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
String accountType = input.getText().toString();
setDisableAccountManagement(accountType, true);
}
})
.setNeutralButton(R.string.enable, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
String accountType = input.getText().toString();
setDisableAccountManagement(accountType, false);
}
})
.setNegativeButton(android.R.string.cancel, null /* Nothing to do */)
.show();
}
private void setDisableAccountManagement(String accountType, boolean disabled) {
if (!TextUtils.isEmpty(accountType)) {
mDevicePolicyManager.setAccountManagementDisabled(mAdminComponentName, accountType,
disabled);
showToast(disabled
? R.string.account_management_disabled
: R.string.account_management_enabled,
accountType);
return;
}
showToast(R.string.fail_to_set_account_management);
}
/**
* Shows a list of account types that is disabled for account management.
*/
private void showDisableAccountTypeList() {
if (getActivity() == null || getActivity().isFinishing()) {
return;
}
String[] disabledAccountTypeList = mDevicePolicyManager
.getAccountTypesWithManagementDisabled();
Arrays.sort(disabledAccountTypeList, String.CASE_INSENSITIVE_ORDER);
if (disabledAccountTypeList == null || disabledAccountTypeList.length == 0) {
showToast(R.string.no_disabled_account);
} else {
new AlertDialog.Builder(getActivity())
.setTitle(R.string.list_of_disabled_account_types)
.setAdapter(new ArrayAdapter(getActivity(),
android.R.layout.simple_list_item_1, android.R.id.text1,
disabledAccountTypeList), null)
.setPositiveButton(android.R.string.ok, null)
.show();
}
}
/**
* For user creation:
* Shows a prompt asking for the username of the new user and whether the setup wizard should
* be skipped.
*/
@TargetApi(Build.VERSION_CODES.N)
private void showCreateAndManageUserPrompt() {
if (getActivity() == null || getActivity().isFinishing()) {
return;
}
final View dialogView = getActivity().getLayoutInflater().inflate(
R.layout.create_and_manage_user_dialog_prompt, null);
final EditText userNameEditText = (EditText) dialogView.findViewById(R.id.user_name);
userNameEditText.setHint(R.string.enter_username_hint);
final CheckBox skipSetupWizardCheckBox = (CheckBox) dialogView.findViewById(
R.id.skip_setup_wizard_checkbox);
new AlertDialog.Builder(getActivity())
.setTitle(R.string.create_and_manage_user)
.setView(dialogView)
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
String name = userNameEditText.getText().toString();
if (!TextUtils.isEmpty(name)) {
int flags = skipSetupWizardCheckBox.isChecked()
? DevicePolicyManager.SKIP_SETUP_WIZARD : 0;
UserHandle userHandle = mDevicePolicyManager.createAndManageUser(
mAdminComponentName,
name,
mAdminComponentName,
null,
flags);
if (userHandle != null) {
long serialNumber =
mUserManager.getSerialNumberForUser(userHandle);
showToast(R.string.user_created, serialNumber);
return;
}
showToast(R.string.failed_to_create_user);
}
}
})
.setNegativeButton(android.R.string.cancel, null)
.show();
}
/**
* For user removal:
* Shows a prompt for a user serial number. The associated user will be removed.
*/
private void showRemoveUserPrompt() {
if (getActivity() == null || getActivity().isFinishing()) {
return;
}
View view = LayoutInflater.from(getActivity()).inflate(R.layout.simple_edittext, null);
final EditText input = (EditText) view.findViewById(R.id.input);
input.setHint(R.string.enter_user_id);
input.setRawInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_SIGNED);
new AlertDialog.Builder(getActivity())
.setTitle(R.string.remove_user)
.setView(view)
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
boolean success = false;
long serialNumber = -1;
try {
serialNumber = Long.parseLong(input.getText().toString());
UserHandle userHandle = mUserManager
.getUserForSerialNumber(serialNumber);
if (userHandle != null) {
success = mDevicePolicyManager
.removeUser(mAdminComponentName, userHandle);
}
} catch (NumberFormatException e) {
// Error message is printed in the next line.
}
showToast(success ? R.string.user_removed : R.string.failed_to_remove_user);
}
})
.show();
}
/**
* Asks for the package name whose uninstallation should be blocked / unblocked.
*/
private void showBlockUninstallationByPackageNamePrompt() {
Activity activity = getActivity();
if (activity == null || activity.isFinishing()) {
return;
}
View view = LayoutInflater.from(activity).inflate(R.layout.simple_edittext, null);
final EditText input = (EditText) view.findViewById(R.id.input);
input.setHint(getString(R.string.input_package_name_hints));
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setTitle(R.string.block_uninstallation_title)
.setView(view)
.setPositiveButton(R.string.block, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
String pkgName = input.getText().toString();
if (!TextUtils.isEmpty(pkgName)) {
mDevicePolicyManager.setUninstallBlocked(mAdminComponentName, pkgName,
true);
showToast(R.string.uninstallation_blocked, pkgName);
} else {
showToast(R.string.block_uninstallation_failed_invalid_pkgname);
}
}
})
.setNeutralButton(R.string.unblock, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
String pkgName = input.getText().toString();
if (!TextUtils.isEmpty(pkgName)) {
mDevicePolicyManager.setUninstallBlocked(mAdminComponentName, pkgName,
false);
showToast(R.string.uninstallation_allowed, pkgName);
} else {
showToast(R.string.block_uninstallation_failed_invalid_pkgname);
}
}
})
.setNegativeButton(android.R.string.cancel, null)
.show();
}
private void loadAppStatus() {
final @StringRes int appStatusStringId;
if (mDevicePolicyManager.isProfileOwnerApp(mPackageName)) {
appStatusStringId = R.string.this_is_a_profile_owner;
} else if (mDevicePolicyManager.isDeviceOwnerApp(mPackageName)) {
appStatusStringId = R.string.this_is_a_device_owner;
} else {
appStatusStringId = R.string.this_is_not_an_admin;
}
findPreference(APP_STATUS_KEY).setSummary(appStatusStringId);
}
@TargetApi(Build.VERSION_CODES.M)
private void loadSecurityPatch() {
Preference securityPatchPreference = findPreference(SECURITY_PATCH_KEY);
if (!securityPatchPreference.isEnabled()) {
return;
}
String buildSecurityPatch = Build.VERSION.SECURITY_PATCH;
final Date date;
try {
date = new SimpleDateFormat(SECURITY_PATCH_FORMAT).parse(buildSecurityPatch);
} catch (ParseException e) {
securityPatchPreference.setSummary(
getString(R.string.invalid_security_patch, buildSecurityPatch));
return;
}
String display = DateFormat.getDateInstance(DateFormat.MEDIUM).format(date);
securityPatchPreference.setSummary(display);
}
@TargetApi(Build.VERSION_CODES.N)
private void loadPasswordCompliant() {
Preference passwordCompliantPreference = findPreference(PASSWORD_COMPLIANT_KEY);
if (!passwordCompliantPreference.isEnabled()) {
return;
}
String summary;
boolean compliant = mDevicePolicyManager.isActivePasswordSufficient();
if (Util.isManagedProfileOwner(getActivity())) {
DevicePolicyManager parentDpm
= mDevicePolicyManager.getParentProfileInstance(mAdminComponentName);
boolean parentCompliant = parentDpm.isActivePasswordSufficient();
summary = String.format(getResources()
.getString(R.string.password_compliant_profile_summary),
Boolean.toString(parentCompliant), Boolean.toString(compliant));
} else {
summary = String.format(getResources()
.getString(R.string.password_compliant_summary),
Boolean.toString(compliant));
}
passwordCompliantPreference.setSummary(summary);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void reloadCameraDisableUi() {
boolean isCameraDisabled = mDevicePolicyManager.getCameraDisabled(mAdminComponentName);
mDisableCameraSwitchPreference.setChecked(isCameraDisabled);
}
@TargetApi(Build.VERSION_CODES.O)
private void reloadEnableNetworkLoggingUi() {
if (mEnableNetworkLoggingPreference.isEnabled()) {
mEnableNetworkLoggingPreference.setChecked(
mDevicePolicyManager.isNetworkLoggingEnabled(mAdminComponentName));
}
}
@TargetApi(Build.VERSION_CODES.N)
private void reloadEnableProcessLoggingUi() {
if (mEnableProcessLoggingPreference.isEnabled()) {
boolean isProcessLoggingEnabled = mDevicePolicyManager.isSecurityLoggingEnabled(
mAdminComponentName);
mEnableProcessLoggingPreference.setChecked(isProcessLoggingEnabled);
mRequestLogsPreference.refreshEnabledState();
}
}
@TargetApi(Build.VERSION_CODES.O)
private void reloadEnableBackupServiceUi() {
if (mEnableBackupServicePreference.isEnabled()) {
mEnableBackupServicePreference.setChecked(mDevicePolicyManager.isBackupServiceEnabled(
mAdminComponentName));
}
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void reloadScreenCaptureDisableUi() {
boolean isScreenCaptureDisabled = mDevicePolicyManager.getScreenCaptureDisabled(
mAdminComponentName);
mDisableScreenCaptureSwitchPreference.setChecked(isScreenCaptureDisabled);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void reloadSetAutoTimeRequiredUi() {
if (mDevicePolicyManager.isDeviceOwnerApp(mPackageName)) {
boolean isAutoTimeRequired = mDevicePolicyManager.getAutoTimeRequired();
mSetAutoTimeRequiredPreference.setChecked(isAutoTimeRequired);
}
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void reloadMuteAudioUi() {
if (mMuteAudioSwitchPreference.isEnabled()) {
final boolean isAudioMuted = mDevicePolicyManager.isMasterVolumeMuted(mAdminComponentName);
mMuteAudioSwitchPreference.setChecked(isAudioMuted);
}
}
/**
* Shows a prompt to ask for package name which is used to enable a system app.
*/
private void showEnableSystemAppByPackageNamePrompt() {
if (getActivity() == null || getActivity().isFinishing()) {
return;
}
LinearLayout inputContainer = (LinearLayout) getActivity().getLayoutInflater()
.inflate(R.layout.simple_edittext, null);
final EditText editText = (EditText) inputContainer.findViewById(R.id.input);
editText.setHint(getString(R.string.enable_system_apps_by_package_name_hints));
new AlertDialog.Builder(getActivity())
.setTitle(getString(R.string.enable_system_apps_title))
.setView(inputContainer)
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
final String packageName = editText.getText().toString();
try {
mDevicePolicyManager.enableSystemApp(mAdminComponentName, packageName);
showToast(R.string.enable_system_apps_by_package_name_success_msg,
packageName);
} catch (IllegalArgumentException e) {
showToast(R.string.enable_system_apps_by_package_name_error);
} finally {
dialog.dismiss();
}
}
})
.setNegativeButton(android.R.string.cancel, null)
.show();
}
/**
* Imports a certificate to the managed profile. If the provided password failed to decrypt the
* given certificate, shows a try again prompt. Otherwise, shows a prompt for the certificate
* alias.
*
* @param intent Intent that contains the certificate data uri.
* @param password The password to decrypt the certificate.
*/
private void importKeyCertificateFromIntent(Intent intent, String password) {
importKeyCertificateFromIntent(intent, password, 0 /* first try */);
}
/**
* Imports a certificate to the managed profile. If the provided decryption password is
* incorrect, shows a try again prompt. Otherwise, shows a prompt for the certificate alias.
*
* @param intent Intent that contains the certificate data uri.
* @param password The password to decrypt the certificate.
* @param attempts The number of times user entered incorrect password.
*/
private void importKeyCertificateFromIntent(Intent intent, String password, int attempts) {
if (getActivity() == null || getActivity().isFinishing()) {
return;
}
Uri data = null;
if (intent != null && (data = intent.getData()) != null) {
// If the password is null, try to decrypt the certificate with an empty password.
if (password == null) {
password = "";
}
try {
CertificateUtil.PKCS12ParseInfo parseInfo = CertificateUtil
.parsePKCS12Certificate(getActivity().getContentResolver(), data, password);
showPromptForKeyCertificateAlias(parseInfo.privateKey, parseInfo.certificate,
parseInfo.alias);
} catch (KeyStoreException | FileNotFoundException | CertificateException |
UnrecoverableKeyException | NoSuchAlgorithmException e) {
Log.e(TAG, "Unable to load key", e);
} catch (IOException e) {
showPromptForCertificatePassword(intent, ++attempts);
} catch (ClassCastException e) {
showToast(R.string.not_a_key_certificate);
}
}
}
/**
* Shows a prompt to ask for the certificate password. If the certificate password is correct,
* import the private key and certificate.
*
* @param intent Intent that contains the certificate data uri.
* @param attempts The number of times user entered incorrect password.
*/
private void showPromptForCertificatePassword(final Intent intent, final int attempts) {
if (getActivity() == null || getActivity().isFinishing()) {
return;
}
View passwordInputView = getActivity().getLayoutInflater()
.inflate(R.layout.certificate_password_prompt, null);
final EditText input = (EditText) passwordInputView.findViewById(R.id.password_input);
if (attempts > 1) {
passwordInputView.findViewById(R.id.incorrect_password).setVisibility(View.VISIBLE);
}
new AlertDialog.Builder(getActivity())
.setTitle(getString(R.string.certificate_password_prompt_title))
.setView(passwordInputView)
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
String userPassword = input.getText().toString();
importKeyCertificateFromIntent(intent, userPassword, attempts);
dialog.dismiss();
}
})
.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
})
.show();
}
/**
* Shows a prompt to ask for the certificate alias. This alias will be imported together with
* the private key and certificate.
*
* @param key The private key of a certificate.
* @param certificate The certificate will be imported.
* @param alias A name that represents the certificate in the profile.
*/
private void showPromptForKeyCertificateAlias(final PrivateKey key,
final Certificate certificate, String alias) {
if (getActivity() == null || getActivity().isFinishing() || key == null
|| certificate == null) {
return;
}
View passwordInputView = getActivity().getLayoutInflater().inflate(
R.layout.certificate_alias_prompt, null);
final EditText input = (EditText) passwordInputView.findViewById(R.id.alias_input);
if (!TextUtils.isEmpty(alias)) {
input.setText(alias);
input.selectAll();
}
new AlertDialog.Builder(getActivity())
.setTitle(getString(R.string.certificate_alias_prompt_title))
.setView(passwordInputView)
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
String alias = input.getText().toString();
if (mDevicePolicyManager.installKeyPair(mAdminComponentName, key,
certificate, alias) == true) {
showToast(R.string.certificate_added, alias);
} else {
showToast(R.string.certificate_add_failed, alias);
}
dialog.dismiss();
}
})
.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
})
.show();
}
/**
* Selects a private/public key pair to uninstall, using the system dialog to choose
* an alias.
*
* Once the alias is chosen and deleted, a {@link Toast} shows status- success or failure.
*/
@TargetApi(Build.VERSION_CODES.N)
private void choosePrivateKeyForRemoval() {
KeyChain.choosePrivateKeyAlias(getActivity(), new KeyChainAliasCallback() {
@Override
public void alias(String alias) {
if (alias == null) {
// No value was chosen.
return;
}
final boolean removed =
mDevicePolicyManager.removeKeyPair(mAdminComponentName, alias);
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
if (removed) {
showToast(R.string.remove_keypair_successfully);
} else {
showToast(R.string.remove_keypair_fail);
}
}
});
}
}, /* keyTypes[] */ null, /* issuers[] */ null, /* uri */ null, /* alias */ null);
}
/**
* Imports a CA certificate from the given data URI.
*
* @param intent Intent that contains the CA data URI.
*/
private void importCaCertificateFromIntent(Intent intent) {
if (getActivity() == null || getActivity().isFinishing()) {
return;
}
Uri data = null;
if (intent != null && (data = intent.getData()) != null) {
ContentResolver cr = getActivity().getContentResolver();
boolean isCaInstalled = false;
try {
InputStream certificateInputStream = cr.openInputStream(data);
isCaInstalled = Util.installCaCertificate(certificateInputStream,
mDevicePolicyManager, mAdminComponentName);
} catch (FileNotFoundException e) {
Log.e(TAG, "importCaCertificateFromIntent: ", e);
}
showToast(isCaInstalled ? R.string.install_ca_successfully : R.string.install_ca_fail);
}
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == Activity.RESULT_OK) {
switch (requestCode) {
case INSTALL_KEY_CERTIFICATE_REQUEST_CODE:
importKeyCertificateFromIntent(data, "");
break;
case INSTALL_CA_CERTIFICATE_REQUEST_CODE:
importCaCertificateFromIntent(data);
break;
case CAPTURE_IMAGE_REQUEST_CODE:
showFragment(MediaDisplayFragment.newInstance(
MediaDisplayFragment.REQUEST_DISPLAY_IMAGE, mImageUri));
break;
case CAPTURE_VIDEO_REQUEST_CODE:
showFragment(MediaDisplayFragment.newInstance(
MediaDisplayFragment.REQUEST_DISPLAY_VIDEO, mVideoUri));
break;
}
}
}
/**
* Shows a list of installed CA certificates.
*/
private void showCaCertificateList() {
if (getActivity() == null || getActivity().isFinishing()) {
return;
}
// Avoid starting the same task twice.
if (mShowCaCertificateListTask != null && !mShowCaCertificateListTask.isCancelled()) {
mShowCaCertificateListTask.cancel(true);
}
mShowCaCertificateListTask = new ShowCaCertificateListTask();
mShowCaCertificateListTask.execute();
}
/**
* Shows a dialog that asks the user for a host and port, then sets the recommended global proxy
* to these values.
*/
private void showSetGlobalHttpProxyDialog() {
if (getActivity() == null || getActivity().isFinishing()) {
return;
}
final View dialogView = getActivity().getLayoutInflater().inflate(
R.layout.proxy_config_dialog, null);
final EditText hostEditText = (EditText) dialogView.findViewById(R.id.proxy_host);
final EditText portEditText = (EditText) dialogView.findViewById(R.id.proxy_port);
final String host = System.getProperty("http.proxyHost");
if (!TextUtils.isEmpty(host)) {
hostEditText.setText(host);
portEditText.setText(System.getProperty("http.proxyPort"));
}
new AlertDialog.Builder(getActivity())
.setTitle(R.string.set_global_http_proxy)
.setView(dialogView)
.setPositiveButton(android.R.string.ok, (dialogInterface, i) -> {
final String hostString = hostEditText.getText().toString();
if (hostString.isEmpty()) {
showToast(R.string.no_host);
return;
}
final String portString = portEditText.getText().toString();
if (portString.isEmpty()) {
showToast(R.string.no_port);
return;
}
final int port = Integer.parseInt(portString);
if (port > 65535) {
showToast(R.string.port_out_of_range);
return;
}
mDevicePolicyManager.setRecommendedGlobalProxy(mAdminComponentName,
ProxyInfo.buildDirectProxy(hostString, port));
})
.setNegativeButton(android.R.string.cancel, null)
.show();
}
/**
* Displays an alert dialog that allows the user to select applications from all non-system
* applications installed on the current profile. After the user selects an app, this app can't
* be uninstallation.
*/
private void showBlockUninstallationPrompt() {
Activity activity = getActivity();
if (activity == null || activity.isFinishing()) {
return;
}
List applicationInfoList
= mPackageManager.getInstalledApplications(0 /* No flag */);
List resolveInfoList = new ArrayList();
Collections.sort(applicationInfoList,
new ApplicationInfo.DisplayNameComparator(mPackageManager));
for (ApplicationInfo applicationInfo : applicationInfoList) {
// Ignore system apps because they can't be uninstalled.
if ((applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
ResolveInfo resolveInfo = new ResolveInfo();
resolveInfo.resolvePackageName = applicationInfo.packageName;
resolveInfoList.add(resolveInfo);
}
}
final BlockUninstallationInfoArrayAdapter blockUninstallationInfoArrayAdapter
= new BlockUninstallationInfoArrayAdapter(getActivity(), R.id.pkg_name,
resolveInfoList);
ListView listview = new ListView(getActivity());
listview.setAdapter(blockUninstallationInfoArrayAdapter);
listview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView> parent, View view, int pos, long id) {
blockUninstallationInfoArrayAdapter.onItemClick(parent, view, pos, id);
}
});
new AlertDialog.Builder(getActivity())
.setTitle(R.string.block_uninstallation_title)
.setView(listview)
.setPositiveButton(R.string.close, null /* Nothing to do */)
.show();
}
/**
* Shows an alert dialog which displays a list of disabled system apps. Clicking an app in the
* dialog enables the app.
*/
private void showEnableSystemAppsPrompt() {
// Disabled system apps list = {All system apps} - {Enabled system apps}
final List disabledSystemApps = new ArrayList();
// This list contains both enabled and disabled apps.
List allApps = mPackageManager.getInstalledApplications(
PackageManager.GET_UNINSTALLED_PACKAGES);
Collections.sort(allApps, new ApplicationInfo.DisplayNameComparator(mPackageManager));
// This list contains all enabled apps.
List enabledApps =
mPackageManager.getInstalledApplications(0 /* Default flags */);
Set enabledAppsPkgNames = new HashSet();
for (ApplicationInfo applicationInfo : enabledApps) {
enabledAppsPkgNames.add(applicationInfo.packageName);
}
for (ApplicationInfo applicationInfo : allApps) {
// Interested in disabled system apps only.
if (!enabledAppsPkgNames.contains(applicationInfo.packageName)
&& (applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
disabledSystemApps.add(applicationInfo.packageName);
}
}
if (disabledSystemApps.isEmpty()) {
showToast(R.string.no_disabled_system_apps);
} else {
AppInfoArrayAdapter appInfoArrayAdapter = new AppInfoArrayAdapter(getActivity(),
R.id.pkg_name, disabledSystemApps, true);
new AlertDialog.Builder(getActivity())
.setTitle(getString(R.string.enable_system_apps_title))
.setAdapter(appInfoArrayAdapter, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int position) {
String packageName = disabledSystemApps.get(position);
mDevicePolicyManager.enableSystemApp(mAdminComponentName, packageName);
showToast(R.string.enable_system_apps_by_package_name_success_msg,
packageName);
}
})
.show();
}
}
/**
* Shows an alert dialog which displays a list hidden / non-hidden apps. Clicking an app in the
* dialog enables the app.
*/
private void showHideAppsPrompt(final boolean showHiddenApps) {
final List showApps = new ArrayList<> ();
if (showHiddenApps) {
// Find all hidden packages using the GET_UNINSTALLED_PACKAGES flag
for (ApplicationInfo applicationInfo : getAllInstalledApplicationsSorted()) {
if (mDevicePolicyManager.isApplicationHidden(mAdminComponentName,
applicationInfo.packageName)) {
showApps.add(applicationInfo.packageName);
}
}
} else {
// Find all non-hidden apps with a launcher icon
for (ResolveInfo res : getAllLauncherIntentResolversSorted()) {
if (!showApps.contains(res.activityInfo.packageName)
&& !mDevicePolicyManager.isApplicationHidden(mAdminComponentName,