diff --git a/res/layout/date_time_custom_list_item_2.xml b/res/layout/date_time_custom_list_item_2.xml
deleted file mode 100644
index 49027588937..00000000000
--- a/res/layout/date_time_custom_list_item_2.xml
+++ /dev/null
@@ -1,42 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
diff --git a/res/layout/device_admin_item.xml b/res/layout/device_admin_item.xml
deleted file mode 100644
index 875c7349344..00000000000
--- a/res/layout/device_admin_item.xml
+++ /dev/null
@@ -1,86 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/res/layout/device_admin_settings.xml b/res/layout/device_admin_settings.xml
deleted file mode 100644
index 1766138f1d1..00000000000
--- a/res/layout/device_admin_settings.xml
+++ /dev/null
@@ -1,43 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/res/values/bools.xml b/res/values/bools.xml
index fa57b29a513..b4066059aa8 100644
--- a/res/values/bools.xml
+++ b/res/values/bools.xml
@@ -96,9 +96,6 @@
true
-
- true
-
true
diff --git a/res/xml/device_admin_settings.xml b/res/xml/device_admin_settings.xml
new file mode 100644
index 00000000000..999d7902bb1
--- /dev/null
+++ b/res/xml/device_admin_settings.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/xml/security_dashboard_settings.xml b/res/xml/security_dashboard_settings.xml
index af15c082ae2..8a3d10805c6 100644
--- a/res/xml/security_dashboard_settings.xml
+++ b/res/xml/security_dashboard_settings.xml
@@ -48,7 +48,7 @@
android:key="fingerprint_settings"
android:title="@string/security_settings_fingerprint_preference_title"
android:summary="@string/summary_placeholder"
- settings:keywords="@string/keywords_fingerprint_settings"/>
+ settings:keywords="@string/keywords_fingerprint_settings" />
@@ -75,7 +75,7 @@
android:key="visiblepattern_profile"
android:summary="@string/summary_placeholder"
android:title="@string/lockpattern_settings_enable_visible_pattern_title_profile"
- settings:controller="com.android.settings.security.VisiblePatternProfilePreferenceController"/>
+ settings:controller="com.android.settings.security.VisiblePatternProfilePreferenceController" />
+ settings:controller="com.android.settings.security.ShowPasswordPreferenceController" />
@@ -112,7 +112,8 @@
android:key="manage_device_admin"
android:title="@string/manage_device_admin"
android:summary="@string/summary_placeholder"
- android:fragment="com.android.settings.applications.specialaccess.deviceadmin.DeviceAdminSettings" />
+ android:fragment="com.android.settings.applications.specialaccess.deviceadmin.DeviceAdminSettings"
+ settings:controller="com.android.settings.enterprise.ManageDeviceAdminPreferenceController" />
+ android:summary="@string/summary_placeholder"
+ settings:controller="com.android.settings.enterprise.ManageDeviceAdminPreferenceController" />
{
+
+ private static final String TAG = "DeviceAdminListItem";
+
+ private final String mKey;
+ private final DeviceAdminInfo mInfo;
+ private final CharSequence mName;
+ private final Drawable mIcon;
+ private final DevicePolicyManager mDPM;
+ private CharSequence mDescription;
+
+ public DeviceAdminListItem(Context context, DeviceAdminInfo info) {
+ mInfo = info;
+ mKey = mInfo.getComponent().flattenToString();
+ mDPM = (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
+ final PackageManager pm = context.getPackageManager();
+ mName = mInfo.loadLabel(pm);
+ try {
+ mDescription = mInfo.loadDescription(pm);
+ } catch (Resources.NotFoundException exception) {
+ Log.w(TAG, "Setting description to null because can't find resource: " + mKey);
+ }
+ mIcon = pm.getUserBadgedIcon(mInfo.loadIcon(pm),
+ new UserHandle(DeviceAdminUtils.getUserIdFromDeviceAdminInfo(mInfo)));
+ }
+
+ @Override
+ public int compareTo(DeviceAdminListItem other) {
+ return this.mName.toString().compareTo(other.mName.toString());
+ }
+
+ public String getKey() {
+ return mKey;
+ }
+
+ public CharSequence getName() {
+ return mName;
+ }
+
+ public CharSequence getDescription() {
+ return mDescription;
+ }
+
+ public boolean isActive() {
+ return mDPM.isAdminActiveAsUser(mInfo.getComponent(),
+ DeviceAdminUtils.getUserIdFromDeviceAdminInfo(mInfo));
+ }
+
+ public Drawable getIcon() {
+ return mIcon;
+ }
+
+ public boolean isEnabled() {
+ return !mDPM.isRemovingAdmin(mInfo.getComponent(),
+ DeviceAdminUtils.getUserIdFromDeviceAdminInfo(mInfo));
+ }
+
+ public UserHandle getUser() {
+ return new UserHandle(DeviceAdminUtils.getUserIdFromDeviceAdminInfo(mInfo));
+ }
+
+ public Intent getLaunchIntent(Context context) {
+ return new Intent(context, DeviceAdminAdd.class)
+ .putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, mInfo.getComponent());
+ }
+}
diff --git a/src/com/android/settings/applications/specialaccess/deviceadmin/DeviceAdminListPreferenceController.java b/src/com/android/settings/applications/specialaccess/deviceadmin/DeviceAdminListPreferenceController.java
new file mode 100644
index 00000000000..52d186b7622
--- /dev/null
+++ b/src/com/android/settings/applications/specialaccess/deviceadmin/DeviceAdminListPreferenceController.java
@@ -0,0 +1,296 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.applications.specialaccess.deviceadmin;
+
+import static android.app.admin.DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED;
+
+import android.app.AppGlobals;
+import android.app.admin.DeviceAdminInfo;
+import android.app.admin.DeviceAdminReceiver;
+import android.app.admin.DevicePolicyManager;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.ActivityInfo;
+import android.content.pm.IPackageManager;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.text.TextUtils;
+import android.util.ArrayMap;
+import android.util.Log;
+import android.util.SparseArray;
+
+import com.android.settings.R;
+import com.android.settings.core.BasePreferenceController;
+import com.android.settingslib.core.lifecycle.LifecycleObserver;
+import com.android.settingslib.core.lifecycle.events.OnStart;
+import com.android.settingslib.core.lifecycle.events.OnStop;
+import com.android.settingslib.widget.FooterPreference;
+import com.android.settingslib.widget.FooterPreferenceMixin;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceGroup;
+import androidx.preference.PreferenceScreen;
+import androidx.preference.SwitchPreference;
+
+public class DeviceAdminListPreferenceController extends BasePreferenceController
+ implements LifecycleObserver, OnStart, OnStop {
+
+ private static final IntentFilter FILTER = new IntentFilter();
+ private static final String TAG = "DeviceAdminListPrefCtrl";
+
+ private final DevicePolicyManager mDPM;
+ private final UserManager mUm;
+ private final PackageManager mPackageManager;
+ private final IPackageManager mIPackageManager;
+ /**
+ * Internal collection of device admin info objects for all profiles associated with the current
+ * user.
+ */
+ private final ArrayList mAdmins = new ArrayList<>();
+ private final SparseArray mProfileOwnerComponents = new SparseArray<>();
+
+ private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ // Refresh the list, if state change has been received. It could be that checkboxes
+ // need to be updated
+ if (TextUtils.equals(ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED, intent.getAction())) {
+ updateList();
+ }
+ }
+ };
+
+ private PreferenceGroup mPreferenceGroup;
+ private FooterPreferenceMixin mFooterPreferenceMixin;
+
+ static {
+ FILTER.addAction(ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
+ }
+
+ public DeviceAdminListPreferenceController(Context context, String preferenceKey) {
+ super(context, preferenceKey);
+ mDPM = (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
+ mUm = (UserManager) context.getSystemService(Context.USER_SERVICE);
+ mPackageManager = mContext.getPackageManager();
+ mIPackageManager = AppGlobals.getPackageManager();
+ }
+
+ public DeviceAdminListPreferenceController setFooterPreferenceMixin(
+ FooterPreferenceMixin mixin) {
+ mFooterPreferenceMixin = mixin;
+ return this;
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ return AVAILABLE;
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ super.displayPreference(screen);
+ mPreferenceGroup = (PreferenceGroup) screen.findPreference(getPreferenceKey());
+ }
+
+ @Override
+ public void onStart() {
+ mContext.registerReceiverAsUser(
+ mBroadcastReceiver, UserHandle.ALL, FILTER,
+ null /* broadcastPermission */, null /* scheduler */);
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ super.updateState(preference);
+ mProfileOwnerComponents.clear();
+ final List profiles = mUm.getUserProfiles();
+ final int profilesSize = profiles.size();
+ for (int i = 0; i < profilesSize; ++i) {
+ final int profileId = profiles.get(i).getIdentifier();
+ mProfileOwnerComponents.put(profileId, mDPM.getProfileOwnerAsUser(profileId));
+ }
+ updateList();
+ }
+
+ @Override
+ public void onStop() {
+ mContext.unregisterReceiver(mBroadcastReceiver);
+ }
+
+ @VisibleForTesting
+ void updateList() {
+ refreshData();
+ refreshUI();
+ }
+
+ private void refreshData() {
+ mAdmins.clear();
+ final List profiles = mUm.getUserProfiles();
+ for (UserHandle profile : profiles) {
+ final int profileId = profile.getIdentifier();
+ updateAvailableAdminsForProfile(profileId);
+ }
+ Collections.sort(mAdmins);
+ }
+
+ private void refreshUI() {
+ if (mPreferenceGroup == null) {
+ return;
+ }
+ if (mFooterPreferenceMixin != null) {
+ final FooterPreference footer = mFooterPreferenceMixin.createFooterPreference();
+ footer.setTitle(R.string.no_device_admins);
+ footer.setVisible(mAdmins.isEmpty());
+ }
+ final Map preferenceCache = new ArrayMap<>();
+ final Context prefContext = mPreferenceGroup.getContext();
+ final int childrenCount = mPreferenceGroup.getPreferenceCount();
+ for (int i = 0; i < childrenCount; i++) {
+ SwitchPreference pref = (SwitchPreference) mPreferenceGroup.getPreference(i);
+ preferenceCache.put(pref.getKey(), pref);
+ }
+ for (DeviceAdminListItem item : mAdmins) {
+ final String key = item.getKey();
+ SwitchPreference pref = preferenceCache.remove(key);
+ if (pref == null) {
+ pref = new SwitchPreference(prefContext);
+ mPreferenceGroup.addPreference(pref);
+ }
+ bindPreference(item, pref);
+ }
+ for (SwitchPreference unusedCacheItem : preferenceCache.values()) {
+ mPreferenceGroup.removePreference(unusedCacheItem);
+ }
+ }
+
+ private void bindPreference(DeviceAdminListItem item, SwitchPreference pref) {
+ pref.setKey(item.getKey());
+ pref.setTitle(item.getName());
+ pref.setIcon(item.getIcon());
+ pref.setChecked(item.isActive());
+ pref.setSummary(item.getDescription());
+ pref.setEnabled(item.isEnabled());
+ pref.setOnPreferenceClickListener(preference -> {
+ final UserHandle user = item.getUser();
+ mContext.startActivityAsUser(item.getLaunchIntent(mContext), user);
+ return true;
+ });
+ pref.setOnPreferenceChangeListener((preference, newValue) -> false);
+ }
+
+ /**
+ * Add device admins to the internal collection that belong to a profile.
+ *
+ * @param profileId the profile identifier.
+ */
+ private void updateAvailableAdminsForProfile(final int profileId) {
+ // We are adding the union of two sets 'A' and 'B' of device admins to mAvailableAdmins.
+ // - Set 'A' is the set of active admins for the profile
+ // - set 'B' is the set of listeners to DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED for
+ // the profile.
+
+ // Add all of set 'A' to mAvailableAdmins.
+ final List activeAdminsForProfile = mDPM.getActiveAdminsAsUser(profileId);
+ addActiveAdminsForProfile(activeAdminsForProfile, profileId);
+
+ // Collect set 'B' and add B-A to mAvailableAdmins.
+ addDeviceAdminBroadcastReceiversForProfile(activeAdminsForProfile, profileId);
+ }
+
+ /**
+ * Add a {@link DeviceAdminInfo} object to the internal collection of available admins for all
+ * active admin components associated with a profile.
+ */
+ private void addActiveAdminsForProfile(List activeAdmins, int profileId) {
+ if (activeAdmins == null) {
+ return;
+ }
+
+ for (ComponentName activeAdmin : activeAdmins) {
+ final ActivityInfo ai;
+ try {
+ ai = mIPackageManager.getReceiverInfo(activeAdmin,
+ PackageManager.GET_META_DATA |
+ PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS |
+ PackageManager.MATCH_DIRECT_BOOT_UNAWARE |
+ PackageManager.MATCH_DIRECT_BOOT_AWARE, profileId);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Unable to load component: " + activeAdmin);
+ continue;
+ }
+ final DeviceAdminInfo deviceAdminInfo = DeviceAdminUtils.createDeviceAdminInfo(
+ mContext, ai);
+ if (deviceAdminInfo == null) {
+ continue;
+ }
+ mAdmins.add(new DeviceAdminListItem(mContext, deviceAdminInfo));
+ }
+ }
+
+ /**
+ * Add a profile's device admins that are receivers of
+ * {@code DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED} to the internal collection if they
+ * haven't been added yet.
+ *
+ * @param alreadyAddedComponents the set of active admin component names. Receivers of
+ * {@code DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED}
+ * whose component is in this
+ * set are not added to the internal collection again.
+ * @param profileId the identifier of the profile
+ */
+ private void addDeviceAdminBroadcastReceiversForProfile(
+ Collection alreadyAddedComponents, int profileId) {
+ final List enabledForProfile = mPackageManager.queryBroadcastReceiversAsUser(
+ new Intent(DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED),
+ PackageManager.GET_META_DATA | PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS,
+ profileId);
+ if (enabledForProfile == null) {
+ return;
+ }
+ for (ResolveInfo resolveInfo : enabledForProfile) {
+ final ComponentName riComponentName =
+ new ComponentName(resolveInfo.activityInfo.packageName,
+ resolveInfo.activityInfo.name);
+ if (alreadyAddedComponents != null
+ && alreadyAddedComponents.contains(riComponentName)) {
+ continue;
+ }
+ DeviceAdminInfo deviceAdminInfo = DeviceAdminUtils.createDeviceAdminInfo(
+ mContext, resolveInfo.activityInfo);
+ // add only visible ones (note: active admins are added regardless of visibility)
+ if (deviceAdminInfo != null && deviceAdminInfo.isVisible()) {
+ if (!deviceAdminInfo.getActivityInfo().applicationInfo.isInternal()) {
+ continue;
+ }
+ mAdmins.add(new DeviceAdminListItem(mContext, deviceAdminInfo));
+ }
+ }
+ }
+}
diff --git a/src/com/android/settings/applications/specialaccess/deviceadmin/DeviceAdminSettings.java b/src/com/android/settings/applications/specialaccess/deviceadmin/DeviceAdminSettings.java
index 6e0f60c9d65..4cd4c049f4f 100644
--- a/src/com/android/settings/applications/specialaccess/deviceadmin/DeviceAdminSettings.java
+++ b/src/com/android/settings/applications/specialaccess/deviceadmin/DeviceAdminSettings.java
@@ -16,448 +16,55 @@
package com.android.settings.applications.specialaccess.deviceadmin;
-import android.app.Activity;
-import android.app.AppGlobals;
-import android.app.ListFragment;
-import android.app.admin.DeviceAdminInfo;
-import android.app.admin.DeviceAdminReceiver;
-import android.app.admin.DevicePolicyManager;
-import android.content.BroadcastReceiver;
-import android.content.ComponentName;
import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.ActivityInfo;
-import android.content.pm.IPackageManager;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.content.res.Resources;
-import android.graphics.drawable.Drawable;
-import android.os.Bundle;
-import android.os.RemoteException;
-import android.os.UserHandle;
-import android.os.UserManager;
-import android.util.Log;
-import android.util.SparseArray;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.BaseAdapter;
-import android.widget.ImageView;
-import android.widget.ListView;
-import android.widget.Switch;
-import android.widget.TextView;
+import android.provider.SearchIndexableResource;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
-import com.android.settings.Utils;
-import com.android.settings.overlay.FeatureFactory;
-import com.android.settingslib.core.instrumentation.Instrumentable;
-import com.android.settingslib.core.instrumentation.VisibilityLoggerMixin;
+import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settings.search.Indexable;
+import com.android.settingslib.search.SearchIndexable;
-import org.xmlpull.v1.XmlPullParserException;
-
-import java.io.IOException;
import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
import java.util.List;
-public class DeviceAdminSettings extends ListFragment implements Instrumentable {
+@SearchIndexable
+public class DeviceAdminSettings extends DashboardFragment {
static final String TAG = "DeviceAdminSettings";
- private VisibilityLoggerMixin mVisibilityLoggerMixin;
- private DevicePolicyManager mDPM;
- private UserManager mUm;
-
- private static class DeviceAdminListItem implements Comparable {
- public DeviceAdminInfo info;
-
- // These aren't updated so they keep a stable sort order if user activates / de-activates
- // an admin.
- public String name;
- public boolean active;
-
- public int compareTo(DeviceAdminListItem other) {
- // Sort active admins first, then by name.
- if (this.active != other.active) {
- return this.active ? -1 : 1;
- }
- return this.name.compareTo(other.name);
- }
- }
-
- /**
- * Internal collection of device admin info objects for all profiles associated with the current
- * user.
- */
- private final ArrayList
- mAdmins = new ArrayList();
-
- private String mDeviceOwnerPkg;
- private SparseArray mProfileOwnerComponents = new SparseArray();
-
- private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- // Refresh the list, if state change has been received. It could be that checkboxes
- // need to be updated
- if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED.equals(
- intent.getAction())) {
- updateList();
- }
- }
- };
-
- @Override
public int getMetricsCategory() {
return MetricsProto.MetricsEvent.DEVICE_ADMIN_SETTINGS;
}
@Override
- public void onCreate(Bundle icicle) {
- super.onCreate(icicle);
- mVisibilityLoggerMixin = new VisibilityLoggerMixin(getMetricsCategory(),
- FeatureFactory.getFactory(getContext()).getMetricsFeatureProvider());
+ public void onAttach(Context context) {
+ super.onAttach(context);
+ use(DeviceAdminListPreferenceController.class).setFooterPreferenceMixin(
+ mFooterPreferenceMixin);
}
@Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
- mDPM = (DevicePolicyManager) getActivity().getSystemService(Context.DEVICE_POLICY_SERVICE);
- mUm = (UserManager) getActivity().getSystemService(Context.USER_SERVICE);
- return inflater.inflate(R.layout.device_admin_settings, container, false);
+ protected int getPreferenceScreenResId() {
+ return R.xml.device_admin_settings;
}
@Override
- public void onActivityCreated(Bundle savedInstanceState) {
- super.onActivityCreated(savedInstanceState);
- setHasOptionsMenu(true);
- Utils.forceCustomPadding(getListView(), true /* additive padding */);
- getActivity().setTitle(R.string.manage_device_admin);
+ protected String getLogTag() {
+ return TAG;
}
- @Override
- public void onResume() {
- super.onResume();
- final Activity activity = getActivity();
- mVisibilityLoggerMixin.onResume();
- IntentFilter filter = new IntentFilter();
- filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
- activity.registerReceiverAsUser(
- mBroadcastReceiver, UserHandle.ALL, filter, null, null);
+ public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+ new BaseSearchIndexProvider() {
+ @Override
+ public List getXmlResourcesToIndex(Context context,
+ boolean enabled) {
+ final ArrayList result = new ArrayList<>();
- final ComponentName deviceOwnerComponent = mDPM.getDeviceOwnerComponentOnAnyUser();
- mDeviceOwnerPkg =
- deviceOwnerComponent != null ? deviceOwnerComponent.getPackageName() : null;
- mProfileOwnerComponents.clear();
- final List profiles = mUm.getUserProfiles();
- final int profilesSize = profiles.size();
- for (int i = 0; i < profilesSize; ++i) {
- final int profileId = profiles.get(i).getIdentifier();
- mProfileOwnerComponents.put(profileId, mDPM.getProfileOwnerAsUser(profileId));
- }
- updateList();
- }
-
- @Override
- public void onPause() {
- final Activity activity = getActivity();
- activity.unregisterReceiver(mBroadcastReceiver);
- mVisibilityLoggerMixin.onPause();
- super.onPause();
- }
-
- /**
- * Update the internal collection of available admins for all profiles associated with the
- * current user.
- */
- void updateList() {
- mAdmins.clear();
-
- final List profiles = mUm.getUserProfiles();
- final int profilesSize = profiles.size();
- for (int i = 0; i < profilesSize; ++i) {
- final int profileId = profiles.get(i).getIdentifier();
- updateAvailableAdminsForProfile(profileId);
- }
- Collections.sort(mAdmins);
-
- getListView().setAdapter(new PolicyListAdapter());
- }
-
- @Override
- public void onListItemClick(ListView l, View v, int position, long id) {
- Object o = l.getAdapter().getItem(position);
- DeviceAdminInfo dpi = (DeviceAdminInfo) o;
- final UserHandle user = new UserHandle(getUserId(dpi));
- final Activity activity = getActivity();
- Intent intent = new Intent(activity, DeviceAdminAdd.class);
- intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, dpi.getComponent());
- activity.startActivityAsUser(intent, user);
- }
-
- static class ViewHolder {
- ImageView icon;
- TextView name;
- Switch checkbox;
- TextView description;
- }
-
- class PolicyListAdapter extends BaseAdapter {
- final LayoutInflater mInflater;
-
- PolicyListAdapter() {
- mInflater = (LayoutInflater)
- getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- }
-
- @Override
- public boolean hasStableIds() {
- return false;
- }
-
- @Override
- public int getCount() {
- return mAdmins.size();
- }
-
- /**
- * The item for the given position in the list.
- *
- * @return DeviceAdminInfo object for actual device admins.
- */
- @Override
- public Object getItem(int position) {
- return ((DeviceAdminListItem) (mAdmins.get(position))).info;
- }
-
- @Override
- public long getItemId(int position) {
- return position;
- }
-
- @Override
- public boolean areAllItemsEnabled() {
- return false;
- }
-
- /**
- * See {@link #getItemViewType} for the view types.
- */
- @Override
- public int getViewTypeCount() {
- return 1;
- }
-
- /**
- * Returns 0 for all types.
- */
- @Override
- public int getItemViewType(int position) {
- return 0;
- }
-
- @Override
- public boolean isEnabled(int position) {
- Object o = getItem(position);
- return isEnabled(o);
- }
-
- private boolean isEnabled(Object o) {
- DeviceAdminInfo info = (DeviceAdminInfo) o;
- // Disable item if admin is being removed
- if (isRemovingAdmin(info)) {
- return false;
- }
- return true;
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- Object o = getItem(position);
- if (convertView == null) {
- convertView = newDeviceAdminView(parent);
- }
- bindView(convertView, (DeviceAdminInfo) o);
- return convertView;
- }
-
- private View newDeviceAdminView(ViewGroup parent) {
- View v = mInflater.inflate(R.layout.device_admin_item, parent, false);
- ViewHolder h = new ViewHolder();
- h.icon = v.findViewById(R.id.icon);
- h.name = v.findViewById(R.id.name);
- h.checkbox = v.findViewById(R.id.checkbox);
- h.description = v.findViewById(R.id.description);
- v.setTag(h);
- return v;
- }
-
- private void bindView(View view, DeviceAdminInfo item) {
- final Activity activity = getActivity();
- ViewHolder vh = (ViewHolder) view.getTag();
- Drawable activityIcon = item.loadIcon(activity.getPackageManager());
- Drawable badgedIcon = activity.getPackageManager().getUserBadgedIcon(
- activityIcon, new UserHandle(getUserId(item)));
- vh.icon.setImageDrawable(badgedIcon);
- vh.name.setText(item.loadLabel(activity.getPackageManager()));
- vh.checkbox.setChecked(isActiveAdmin(item));
- final boolean enabled = isEnabled(item);
- try {
- vh.description.setText(item.loadDescription(activity.getPackageManager()));
- } catch (Resources.NotFoundException e) {
- }
- vh.checkbox.setEnabled(enabled);
- vh.name.setEnabled(enabled);
- vh.description.setEnabled(enabled);
- vh.icon.setEnabled(enabled);
- }
- }
-
- private boolean isDeviceOwner(DeviceAdminInfo item) {
- return getUserId(item) == UserHandle.myUserId()
- && item.getPackageName().equals(mDeviceOwnerPkg);
- }
-
- private boolean isProfileOwner(DeviceAdminInfo item) {
- ComponentName profileOwner = mProfileOwnerComponents.get(getUserId(item));
- return item.getComponent().equals(profileOwner);
- }
-
- private boolean isActiveAdmin(DeviceAdminInfo item) {
- return mDPM.isAdminActiveAsUser(item.getComponent(), getUserId(item));
- }
-
- private boolean isRemovingAdmin(DeviceAdminInfo item) {
- return mDPM.isRemovingAdmin(item.getComponent(), getUserId(item));
- }
-
- /**
- * Add device admins to the internal collection that belong to a profile.
- *
- * @param profileId the profile identifier.
- */
- private void updateAvailableAdminsForProfile(final int profileId) {
- // We are adding the union of two sets 'A' and 'B' of device admins to mAvailableAdmins.
- // Set 'A' is the set of active admins for the profile whereas set 'B' is the set of
- // listeners to DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED for the profile.
-
- // Add all of set 'A' to mAvailableAdmins.
- List activeAdminsListForProfile = mDPM.getActiveAdminsAsUser(profileId);
- addActiveAdminsForProfile(activeAdminsListForProfile, profileId);
-
- // Collect set 'B' and add B-A to mAvailableAdmins.
- addDeviceAdminBroadcastReceiversForProfile(activeAdminsListForProfile, profileId);
- }
-
- /**
- * Add a profile's device admins that are receivers of
- * {@code DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED} to the internal collection if they
- * haven't been added yet.
- *
- * @param alreadyAddedComponents the set of active admin component names. Receivers of
- * {@code DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED} whose component is in this
- * set are not added to the internal collection again.
- * @param profileId the identifier of the profile
- */
- private void addDeviceAdminBroadcastReceiversForProfile(
- Collection alreadyAddedComponents, final int profileId) {
- final PackageManager pm = getActivity().getPackageManager();
- List enabledForProfile = pm.queryBroadcastReceiversAsUser(
- new Intent(DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED),
- PackageManager.GET_META_DATA | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS,
- profileId);
- if (enabledForProfile == null) {
- enabledForProfile = Collections.emptyList();
- }
- final int n = enabledForProfile.size();
- for (int i = 0; i < n; ++i) {
- ResolveInfo resolveInfo = enabledForProfile.get(i);
- ComponentName riComponentName =
- new ComponentName(resolveInfo.activityInfo.packageName,
- resolveInfo.activityInfo.name);
- if (alreadyAddedComponents == null
- || !alreadyAddedComponents.contains(riComponentName)) {
- DeviceAdminInfo deviceAdminInfo = createDeviceAdminInfo(resolveInfo.activityInfo);
- // add only visible ones (note: active admins are added regardless of visibility)
- if (deviceAdminInfo != null && deviceAdminInfo.isVisible()) {
- if (!deviceAdminInfo.getActivityInfo().applicationInfo.isInternal()) {
- continue;
- }
- DeviceAdminListItem item = new DeviceAdminListItem();
- item.info = deviceAdminInfo;
- item.name = deviceAdminInfo.loadLabel(pm).toString();
- // Active ones already added.
- item.active = false;
- mAdmins.add(item);
+ final SearchIndexableResource sir = new SearchIndexableResource(context);
+ sir.xmlResId = R.xml.device_admin_settings;
+ result.add(sir);
+ return result;
}
- }
- }
- }
-
- /**
- * Add a {@link DeviceAdminInfo} object to the internal collection of available admins for all
- * active admin components associated with a profile.
- *
- * @param profileId a profile identifier.
- */
- private void addActiveAdminsForProfile(final List activeAdmins,
- final int profileId) {
- if (activeAdmins != null) {
- final PackageManager packageManager = getActivity().getPackageManager();
- final IPackageManager iPackageManager = AppGlobals.getPackageManager();
- final int n = activeAdmins.size();
- for (int i = 0; i < n; ++i) {
- final ComponentName activeAdmin = activeAdmins.get(i);
- final ActivityInfo ai;
- try {
- ai = iPackageManager.getReceiverInfo(activeAdmin,
- PackageManager.GET_META_DATA |
- PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS |
- PackageManager.MATCH_DIRECT_BOOT_UNAWARE |
- PackageManager.MATCH_DIRECT_BOOT_AWARE, profileId);
- } catch (RemoteException e) {
- Log.w(TAG, "Unable to load component: " + activeAdmin);
- continue;
- }
- final DeviceAdminInfo deviceAdminInfo = createDeviceAdminInfo(ai);
- if (deviceAdminInfo == null) {
- continue;
- }
- // Don't do the applicationInfo.isInternal() check here; if an active
- // admin is already on SD card, just show it.
- final DeviceAdminListItem item = new DeviceAdminListItem();
- item.info = deviceAdminInfo;
- item.name = deviceAdminInfo.loadLabel(packageManager).toString();
- item.active = true;
- mAdmins.add(item);
- }
- }
- }
-
- /**
- * Creates a device admin info object for the resolved intent that points to the component of
- * the device admin.
- *
- * @param ai ActivityInfo for the admin component.
- * @return new {@link DeviceAdminInfo} object or null if there was an error.
- */
- private DeviceAdminInfo createDeviceAdminInfo(ActivityInfo ai) {
- try {
- return new DeviceAdminInfo(getActivity(), ai);
- } catch (XmlPullParserException|IOException e) {
- Log.w(TAG, "Skipping " + ai, e);
- }
- return null;
- }
-
- /**
- * Extracts the user id from a device admin info object.
- * @param adminInfo the device administrator info.
- * @return identifier of the user associated with the device admin.
- */
- private int getUserId(DeviceAdminInfo adminInfo) {
- return UserHandle.getUserId(adminInfo.getActivityInfo().applicationInfo.uid);
- }
+ };
}
diff --git a/src/com/android/settings/applications/specialaccess/deviceadmin/DeviceAdminUtils.java b/src/com/android/settings/applications/specialaccess/deviceadmin/DeviceAdminUtils.java
new file mode 100644
index 00000000000..13d9d20bece
--- /dev/null
+++ b/src/com/android/settings/applications/specialaccess/deviceadmin/DeviceAdminUtils.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.applications.specialaccess.deviceadmin;
+
+import android.app.admin.DeviceAdminInfo;
+import android.content.Context;
+import android.content.pm.ActivityInfo;
+import android.os.UserHandle;
+import android.util.Log;
+
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+
+public class DeviceAdminUtils {
+
+ private static final String TAG = "DeviceAdminUtils";
+
+ /**
+ * Creates a device admin info object for the resolved intent that points to the component of
+ * the device admin.
+ *
+ * @param ai ActivityInfo for the admin component.
+ * @return new {@link DeviceAdminInfo} object or null if there was an error.
+ */
+ public static DeviceAdminInfo createDeviceAdminInfo(Context context, ActivityInfo ai) {
+ try {
+ return new DeviceAdminInfo(context, ai);
+ } catch (XmlPullParserException | IOException e) {
+ Log.w(TAG, "Skipping " + ai, e);
+ }
+ return null;
+ }
+
+ /**
+ * Extracts the user id from a device admin info object.
+ *
+ * @param adminInfo the device administrator info.
+ * @return identifier of the user associated with the device admin.
+ */
+ public static int getUserIdFromDeviceAdminInfo(DeviceAdminInfo adminInfo) {
+ return UserHandle.getUserId(adminInfo.getActivityInfo().applicationInfo.uid);
+ }
+}
diff --git a/src/com/android/settings/applications/specialaccess/deviceadmin/DeviceAdministratorsController.java b/src/com/android/settings/applications/specialaccess/deviceadmin/DeviceAdministratorsController.java
deleted file mode 100644
index 5b05b866ab5..00000000000
--- a/src/com/android/settings/applications/specialaccess/deviceadmin/DeviceAdministratorsController.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.applications.specialaccess.deviceadmin;
-
-import android.content.Context;
-
-import com.android.settings.R;
-import com.android.settings.core.BasePreferenceController;
-
-public class DeviceAdministratorsController extends BasePreferenceController {
-
- public DeviceAdministratorsController(Context context, String key) {
- super(context, key);
- }
-
- @AvailabilityStatus
- public int getAvailabilityStatus() {
- return mContext.getResources().getBoolean(R.bool.config_show_device_administrators)
- ? AVAILABLE
- : UNSUPPORTED_ON_DEVICE;
- }
-}
\ No newline at end of file
diff --git a/src/com/android/settings/datetime/DatePreferenceController.java b/src/com/android/settings/datetime/DatePreferenceController.java
index 856722ca460..ceb65ca8520 100644
--- a/src/com/android/settings/datetime/DatePreferenceController.java
+++ b/src/com/android/settings/datetime/DatePreferenceController.java
@@ -20,8 +20,6 @@ import android.app.Activity;
import android.app.AlarmManager;
import android.app.DatePickerDialog;
import android.content.Context;
-import androidx.annotation.VisibleForTesting;
-import androidx.preference.Preference;
import android.text.TextUtils;
import android.text.format.DateFormat;
import android.widget.DatePicker;
@@ -32,6 +30,9 @@ import com.android.settingslib.core.AbstractPreferenceController;
import java.util.Calendar;
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.Preference;
+
public class DatePreferenceController extends AbstractPreferenceController
implements PreferenceControllerMixin, DatePickerDialog.OnDateSetListener {
diff --git a/src/com/android/settings/enterprise/ManageDeviceAdminPreferenceController.java b/src/com/android/settings/enterprise/ManageDeviceAdminPreferenceController.java
index e4f2e76f7d1..bbb217b498f 100644
--- a/src/com/android/settings/enterprise/ManageDeviceAdminPreferenceController.java
+++ b/src/com/android/settings/enterprise/ManageDeviceAdminPreferenceController.java
@@ -14,42 +14,38 @@
package com.android.settings.enterprise;
import android.content.Context;
-import androidx.preference.Preference;
import com.android.settings.R;
-import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settings.core.BasePreferenceController;
import com.android.settings.overlay.FeatureFactory;
-import com.android.settingslib.core.AbstractPreferenceController;
-public class ManageDeviceAdminPreferenceController extends AbstractPreferenceController implements
- PreferenceControllerMixin {
+import androidx.preference.Preference;
+
+public class ManageDeviceAdminPreferenceController extends BasePreferenceController {
- private static final String KEY_MANAGE_DEVICE_ADMIN = "manage_device_admin";
private final EnterprisePrivacyFeatureProvider mFeatureProvider;
- public ManageDeviceAdminPreferenceController(Context context) {
- super(context);
+ public ManageDeviceAdminPreferenceController(Context context, String key) {
+ super(context, key);
mFeatureProvider = FeatureFactory.getFactory(context)
.getEnterprisePrivacyFeatureProvider(context);
}
@Override
- public void updateState(Preference preference) {
+ public CharSequence getSummary() {
final int activeAdmins
= mFeatureProvider.getNumberOfActiveDeviceAdminsForCurrentUserAndManagedProfile();
- preference.setSummary(activeAdmins == 0
+ return activeAdmins == 0
? mContext.getResources().getString(R.string.number_of_device_admins_none)
: mContext.getResources().getQuantityString(R.plurals.number_of_device_admins,
- activeAdmins, activeAdmins));
+ activeAdmins, activeAdmins);
}
@Override
- public boolean isAvailable() {
- return mContext.getResources().getBoolean(R.bool.config_show_manage_device_admin);
+ public int getAvailabilityStatus() {
+ return mContext.getResources().getBoolean(R.bool.config_show_manage_device_admin)
+ ? AVAILABLE_UNSEARCHABLE
+ : UNSUPPORTED_ON_DEVICE;
}
- @Override
- public String getPreferenceKey() {
- return KEY_MANAGE_DEVICE_ADMIN;
- }
}
diff --git a/src/com/android/settings/security/SecuritySettings.java b/src/com/android/settings/security/SecuritySettings.java
index 7ce6560f415..b5906184d14 100644
--- a/src/com/android/settings/security/SecuritySettings.java
+++ b/src/com/android/settings/security/SecuritySettings.java
@@ -29,7 +29,6 @@ import com.android.settings.Utils;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.dashboard.SummaryLoader;
import com.android.settings.enterprise.EnterprisePrivacyPreferenceController;
-import com.android.settings.enterprise.ManageDeviceAdminPreferenceController;
import com.android.settings.fingerprint.FingerprintProfileStatusPreferenceController;
import com.android.settings.fingerprint.FingerprintStatusPreferenceController;
import com.android.settings.location.LocationPreferenceController;
@@ -114,7 +113,6 @@ public class SecuritySettings extends DashboardFragment {
Lifecycle lifecycle, SecuritySettings host) {
final List controllers = new ArrayList<>();
controllers.add(new LocationPreferenceController(context, lifecycle));
- controllers.add(new ManageDeviceAdminPreferenceController(context));
controllers.add(new EnterprisePrivacyPreferenceController(context));
controllers.add(new ManageTrustAgentsPreferenceController(context));
controllers.add(new ScreenPinningPreferenceController(context));
diff --git a/tests/robotests/res/values-mcc999/config.xml b/tests/robotests/res/values-mcc999/config.xml
index 72f5134025e..2d95b657905 100644
--- a/tests/robotests/res/values-mcc999/config.xml
+++ b/tests/robotests/res/values-mcc999/config.xml
@@ -33,7 +33,6 @@
false
false
false
- false
false
false
false
diff --git a/tests/robotests/src/com/android/settings/applications/specialaccess/deviceadmin/DeviceAdminListItemTest.java b/tests/robotests/src/com/android/settings/applications/specialaccess/deviceadmin/DeviceAdminListItemTest.java
new file mode 100644
index 00000000000..e19d9e68631
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/applications/specialaccess/deviceadmin/DeviceAdminListItemTest.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.applications.specialaccess.deviceadmin;
+
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.when;
+
+import android.app.admin.DeviceAdminInfo;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.graphics.Color;
+import android.graphics.drawable.ColorDrawable;
+
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class DeviceAdminListItemTest {
+
+ @Mock
+ private DeviceAdminInfo mDeviceAdminInfo;
+ private Context mContext;
+
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext = RuntimeEnvironment.application;
+ }
+
+ @Test
+ public void newInstance_shouldLoadInfoFromDeviceAdminInfo() {
+ final String label = "testlabel";
+ final String description = "testdesc";
+ final ComponentName cn = new ComponentName(mContext.getPackageName(), "test");
+ when(mDeviceAdminInfo.getActivityInfo()).thenReturn(new ActivityInfo());
+ mDeviceAdminInfo.getActivityInfo().applicationInfo = new ApplicationInfo();
+ when(mDeviceAdminInfo.loadLabel(any(PackageManager.class))).thenReturn(label);
+ when(mDeviceAdminInfo.loadDescription(any(PackageManager.class))).thenReturn(description);
+ when(mDeviceAdminInfo.loadIcon(any(PackageManager.class)))
+ .thenReturn(new ColorDrawable(Color.BLUE));
+ when(mDeviceAdminInfo.getComponent()).thenReturn(cn);
+
+ DeviceAdminListItem item = new DeviceAdminListItem(mContext, mDeviceAdminInfo);
+
+ assertThat(item.getKey()).isEqualTo(cn.flattenToShortString());
+ assertThat(item.getName()).isEqualTo(label);
+ assertThat(item.getDescription()).isEqualTo(description);
+ }
+
+}
diff --git a/tests/robotests/src/com/android/settings/applications/specialaccess/deviceadmin/DeviceAdminListPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/specialaccess/deviceadmin/DeviceAdminListPreferenceControllerTest.java
new file mode 100644
index 00000000000..c99df010b74
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/applications/specialaccess/deviceadmin/DeviceAdminListPreferenceControllerTest.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.applications.specialaccess.deviceadmin;
+
+import static androidx.lifecycle.Lifecycle.Event.ON_START;
+import static androidx.lifecycle.Lifecycle.Event.ON_STOP;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.isNull;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.IntentFilter;
+import android.os.UserHandle;
+
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+import com.android.settingslib.widget.FooterPreferenceMixin;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+
+import androidx.lifecycle.LifecycleOwner;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class DeviceAdminListPreferenceControllerTest {
+
+ @Mock
+ private FooterPreferenceMixin mFooterPreferenceMixin;
+ private Context mContext;
+ private DeviceAdminListPreferenceController mController;
+ private LifecycleOwner mLifecycleOwner;
+ private Lifecycle mLifecycle;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext = spy(RuntimeEnvironment.application);
+
+ mLifecycleOwner = () -> mLifecycle;
+ mLifecycle = new Lifecycle(mLifecycleOwner);
+
+ mController = spy(new DeviceAdminListPreferenceController(mContext, "test_key")
+ .setFooterPreferenceMixin(mFooterPreferenceMixin));
+ mLifecycle.addObserver(mController);
+ }
+
+ @Test
+ public void onStart_registerReceiver() {
+ mLifecycle.handleLifecycleEvent(ON_START);
+
+ verify(mContext).registerReceiverAsUser(any(BroadcastReceiver.class), eq(UserHandle.ALL),
+ any(IntentFilter.class), isNull(), isNull());
+ }
+
+ @Test
+ public void onStop_unregisterReceiver() {
+ mLifecycle.handleLifecycleEvent(ON_START);
+ mLifecycle.handleLifecycleEvent(ON_STOP);
+
+ verify(mContext).unregisterReceiver(any(BroadcastReceiver.class));
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/applications/specialaccess/deviceadmin/DeviceAdministratorsControllerTest.java b/tests/robotests/src/com/android/settings/applications/specialaccess/deviceadmin/DeviceAdministratorsControllerTest.java
deleted file mode 100644
index 6e3ff2c857e..00000000000
--- a/tests/robotests/src/com/android/settings/applications/specialaccess/deviceadmin/DeviceAdministratorsControllerTest.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.applications.specialaccess.deviceadmin;
-
-import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Mockito.spy;
-
-import android.content.Context;
-
-import com.android.settings.testutils.SettingsRobolectricTestRunner;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
-
-@RunWith(SettingsRobolectricTestRunner.class)
-public class DeviceAdministratorsControllerTest {
-
- private Context mContext;
- private DeviceAdministratorsController mController;
-
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
- mContext = spy(RuntimeEnvironment.application.getApplicationContext());
- mController = new DeviceAdministratorsController(mContext, "key");
- }
-
- @Test
- public void testDeviceAdministrators_byDefault_shouldBeShown() {
- assertThat(mController.isAvailable()).isTrue();
- }
-
- @Test
- @Config(qualifiers = "mcc999")
- public void testDeviceAdministrators_ifDisabled_shouldNotBeShown() {
- assertThat(mController.isAvailable()).isFalse();
- }
-}
diff --git a/tests/robotests/src/com/android/settings/enterprise/ManageDeviceAdminPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/enterprise/ManageDeviceAdminPreferenceControllerTest.java
index 885e8901cff..e9066aa2900 100644
--- a/tests/robotests/src/com/android/settings/enterprise/ManageDeviceAdminPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/enterprise/ManageDeviceAdminPreferenceControllerTest.java
@@ -22,7 +22,6 @@ import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.res.Resources;
-import androidx.preference.Preference;
import com.android.settings.R;
import com.android.settings.testutils.FakeFeatureFactory;
@@ -36,6 +35,8 @@ import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
+import androidx.preference.Preference;
+
@RunWith(SettingsRobolectricTestRunner.class)
public class ManageDeviceAdminPreferenceControllerTest {
@@ -51,7 +52,7 @@ public class ManageDeviceAdminPreferenceControllerTest {
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application);
mFeatureFactory = FakeFeatureFactory.setupForTest();
- mController = new ManageDeviceAdminPreferenceController(mContext);
+ mController = new ManageDeviceAdminPreferenceController(mContext, "testkey");
}
@Test
@@ -60,7 +61,7 @@ public class ManageDeviceAdminPreferenceControllerTest {
when(mFeatureFactory.enterprisePrivacyFeatureProvider
.getNumberOfActiveDeviceAdminsForCurrentUserAndManagedProfile()).thenReturn(0);
- when (mContext.getResources()).thenReturn(mResources);
+ when(mContext.getResources()).thenReturn(mResources);
when(mResources.getString(R.string.number_of_device_admins_none))
.thenReturn("no apps");
mController.updateState(preference);
@@ -84,15 +85,4 @@ public class ManageDeviceAdminPreferenceControllerTest {
public void isAvailable_whenNotVisible_isFalse() {
assertThat(mController.isAvailable()).isFalse();
}
-
- @Test
- public void testHandlePreferenceTreeClick() {
- assertThat(mController.handlePreferenceTreeClick(new Preference(mContext, null, 0, 0)))
- .isFalse();
- }
-
- @Test
- public void testGetPreferenceKey() {
- assertThat(mController.getPreferenceKey()).isEqualTo("manage_device_admin");
- }
}