diff --git a/app/src/main/java/com/google/android/testdpc/common/AppInfoArrayAdapter.java b/app/src/main/java/com/google/android/testdpc/common/AppInfoArrayAdapter.java index 0f32bcd7..e64e9878 100644 --- a/app/src/main/java/com/google/android/testdpc/common/AppInfoArrayAdapter.java +++ b/app/src/main/java/com/google/android/testdpc/common/AppInfoArrayAdapter.java @@ -31,16 +31,24 @@ import java.util.List; /** - * A simple adapter which takes a list of package name and shows their app icon and app name in a + * A simple adapter which takes a list of package names and shows their app icon and app name in a * listview. */ public class AppInfoArrayAdapter extends ArrayAdapter { - private PackageManager mPackageManager; + private int mAppInfoFlags = 0; - public AppInfoArrayAdapter(Context context, int resource, List objects) { - super(context, resource, objects); + public AppInfoArrayAdapter(Context context, int resource, List pkgNameList, + boolean includeDisabledApps) { + super(context, resource, pkgNameList); mPackageManager = getContext().getPackageManager(); + if (includeDisabledApps) { + mAppInfoFlags = PackageManager.GET_UNINSTALLED_PACKAGES; + } + } + + public AppInfoArrayAdapter(Context context, int resource, List pkgNameList) { + this(context, resource, pkgNameList, false /* Don't include disabled apps */); } @Override @@ -52,13 +60,15 @@ public View getView(int position, View convertView, ViewGroup parent) { try { ApplicationInfo applicationInfo = mPackageManager.getApplicationInfo(getItem(position), - 0 /* No flags*/); + mAppInfoFlags); ImageView iconImageView = (ImageView) convertView.findViewById(R.id.pkg_icon); iconImageView.setImageDrawable(mPackageManager.getApplicationIcon(applicationInfo)); TextView pkgNameTextView = (TextView) convertView.findViewById(R.id.pkg_name); pkgNameTextView.setText(mPackageManager.getApplicationLabel(applicationInfo)); } catch (PackageManager.NameNotFoundException e) { e.printStackTrace(); + // Returns an empty view in case the package is not found. + return new View(getContext()); } return convertView; } diff --git a/app/src/main/java/com/google/android/testdpc/policy/PolicyManagementFragment.java b/app/src/main/java/com/google/android/testdpc/policy/PolicyManagementFragment.java index 42b85c42..bd8eed69 100644 --- a/app/src/main/java/com/google/android/testdpc/policy/PolicyManagementFragment.java +++ b/app/src/main/java/com/google/android/testdpc/policy/PolicyManagementFragment.java @@ -67,6 +67,7 @@ import com.google.android.testdpc.DeviceAdminReceiver; import com.google.android.testdpc.R; +import com.google.android.testdpc.common.AppInfoArrayAdapter; import com.google.android.testdpc.policy.accessibility.AccessibilityServiceInfoArrayAdapter; import com.google.android.testdpc.policy.blockuninstallation.BlockUninstallationInfoArrayAdapter; import com.google.android.testdpc.policy.inputmethod.InputMethodInfoArrayAdapter; @@ -91,7 +92,9 @@ import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Enumeration; +import java.util.HashSet; import java.util.List; +import java.util.Set; /** * Provides several device management functions. @@ -161,6 +164,7 @@ public class PolicyManagementFragment extends PreferenceFragment implements private static final String BLOCK_UNINSTALLATION_BY_PKG_KEY = "block_uninstallation_by_pkg"; private static final String BLOCK_UNINSTALLATION_LIST_KEY = "block_uninstallation_list"; private static final String DISABLE_CAMERA_KEY = "disable_camera"; + private static final String ENABLE_SYSTEM_APPS_KEY = "enable_system_apps"; private static final String ENABLE_SYSTEM_APPS_BY_PACKAGE_NAME_KEY = "enable_system_apps_by_package_name"; private static final String ENABLE_SYSTEM_APPS_BY_INTENT_KEY = "enable_system_apps_by_intent"; @@ -270,6 +274,7 @@ public void onCreate(Bundle savedInstanceState) { findPreference(GET_DISABLE_ACCOUNT_MANAGEMENT_KEY).setOnPreferenceClickListener(this); findPreference(BLOCK_UNINSTALLATION_BY_PKG_KEY).setOnPreferenceClickListener(this); findPreference(BLOCK_UNINSTALLATION_LIST_KEY).setOnPreferenceClickListener(this); + findPreference(ENABLE_SYSTEM_APPS_KEY).setOnPreferenceClickListener(this); findPreference(ENABLE_SYSTEM_APPS_BY_PACKAGE_NAME_KEY).setOnPreferenceClickListener(this); findPreference(ENABLE_SYSTEM_APPS_BY_INTENT_KEY).setOnPreferenceClickListener(this); findPreference(MANAGE_APP_RESTRICTIONS_KEY).setOnPreferenceClickListener(this); @@ -360,6 +365,9 @@ public void onClick(DialogInterface dialogInterface, int i) { case BLOCK_UNINSTALLATION_LIST_KEY: showBlockUninstallationPrompt(); return true; + case ENABLE_SYSTEM_APPS_KEY: + showEnableSystemAppsPrompt(); + return true; case ENABLE_SYSTEM_APPS_BY_PACKAGE_NAME_KEY: showEnableSystemAppByPackageNamePrompt(); return true; @@ -1066,8 +1074,8 @@ private void showCaCertificateList() { if (getActivity() == null || getActivity().isFinishing()) { return; } + // Avoid starting the same task twice. if (mShowCaCertificateListTask != null && !mShowCaCertificateListTask.isCancelled()) { - // Cancel the previous task mShowCaCertificateListTask.cancel(true); } mShowCaCertificateListTask = new ShowCaCertificateListTask(); @@ -1085,7 +1093,7 @@ private void showManagedProfileSpecificPolicyFragment() { /** * Displays an alert dialog that allows the user to select applications from all non-system - * applications installed on the current profile. When the user selects an app, this app can't + * applications installed on the current profile. After the user selects an app, this app can't * be uninstallation. */ private void showBlockUninstallationPrompt() { @@ -1124,6 +1132,51 @@ public void onItemClick(AdapterView arg0, View view, int pos, long id) { .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); + // This list contains all enabled apps. + List enabledApps = + mPackageManager.getInstalledApplications(0 /* No 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(); + } + } + private void showToast(int msgId, Object... args) { Activity activity = getActivity(); if (activity == null || activity.isFinishing()) { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 3062cbc0..256293b6 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -102,6 +102,7 @@ Enabled system apps with the given intent. + All system apps have been enabled. Enable Invalid action. diff --git a/app/src/main/res/xml/device_policy_header.xml b/app/src/main/res/xml/device_policy_header.xml index e7146444..e8decbbb 100644 --- a/app/src/main/res/xml/device_policy_header.xml +++ b/app/src/main/res/xml/device_policy_header.xml @@ -40,14 +40,15 @@ limitations under the License. + - -