Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4082c6b2 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Convert trust agent pref list logic to PreferenceController"

parents 00dcd712 9a38ed45
Loading
Loading
Loading
Loading
+16 −0
Original line number Diff line number Diff line
@@ -28,6 +28,22 @@
        android:title="@string/security_status_title" />

    <!-- TODO Need security section -->
    <PreferenceCategory
        android:key="security_category"
        android:title="@string/lock_settings_title">

        <!-- security_settings_chooser -->
        <com.android.settings.widget.GearPreference
            android:key="unlock_set_or_change"
            android:title="@string/unlock_set_unlock_launch_picker_title"
            android:summary="@string/unlock_set_unlock_mode_none"
            settings:keywords="@string/keywords_lockscreen" />

        <Preference android:key="lockscreen_preferences"
                    android:title="@string/lockscreen_settings_title"
                    android:fragment="com.android.settings.security.LockscreenDashboardFragment"/>

    </PreferenceCategory>

    <!-- security_settings_misc.xml -->
    <PreferenceCategory
+12 −83
Original line number Diff line number Diff line
@@ -41,7 +41,7 @@ import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.SearchIndexableRaw;
import com.android.settings.security.screenlock.ScreenLockSettings;
import com.android.settings.security.trustagent.ManageTrustAgentsPreferenceController;
import com.android.settings.security.trustagent.TrustAgentManager;
import com.android.settings.security.trustagent.TrustAgentListPreferenceController;
import com.android.settings.widget.GearPreference;
import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedPreference;
@@ -58,8 +58,6 @@ public class SecuritySettingsV2 extends DashboardFragment

    private static final String TAG = "SecuritySettingsV2";

    private static final String TRUST_AGENT_CLICK_INTENT = "trust_agent_click_intent";

    // Lock Settings
    private static final String KEY_UNLOCK_SET_OR_CHANGE = "unlock_set_or_change";
    private static final String KEY_UNLOCK_SET_OR_CHANGE_PROFILE = "unlock_set_or_change_profile";
@@ -73,16 +71,13 @@ public class SecuritySettingsV2 extends DashboardFragment
    private static final String KEY_LOCATION = "location";

    private static final int SET_OR_CHANGE_LOCK_METHOD_REQUEST = 123;
    private static final int CHANGE_TRUST_AGENT_SETTINGS = 126;
    public static final int CHANGE_TRUST_AGENT_SETTINGS = 126;
    private static final int SET_OR_CHANGE_LOCK_METHOD_REQUEST_PROFILE = 127;
    private static final int UNIFY_LOCK_CONFIRM_DEVICE_REQUEST = 128;
    private static final int UNIFY_LOCK_CONFIRM_PROFILE_REQUEST = 129;
    private static final int UNUNIFY_LOCK_CONFIRM_DEVICE_REQUEST = 130;
    private static final String TAG_UNIFICATION_DIALOG = "unification_dialog";

    // Misc Settings
    private static final String KEY_TRUST_AGENT = "trust_agent";

    // Security status
    private static final String KEY_SECURITY_STATUS = "security_status";
    private static final String SECURITY_STATUS_KEY_PREFIX = "security_status_";
@@ -101,7 +96,6 @@ public class SecuritySettingsV2 extends DashboardFragment
    private DashboardFeatureProvider mDashboardFeatureProvider;
    private DevicePolicyManager mDPM;
    private SecurityFeatureProvider mSecurityFeatureProvider;
    private TrustAgentManager mTrustAgentManager;
    private UserManager mUm;

    private ChooseLockSettingsHelper mChooseLockSettingsHelper;
@@ -111,8 +105,6 @@ public class SecuritySettingsV2 extends DashboardFragment
    private SwitchPreference mVisiblePatternProfile;
    private RestrictedSwitchPreference mUnifyProfile;

    private Intent mTrustAgentClickIntent;

    private int mProfileChallengeUserId;

    private String mCurrentDevicePassword;
@@ -127,6 +119,7 @@ public class SecuritySettingsV2 extends DashboardFragment
    private ScreenPinningPreferenceController mScreenPinningPreferenceController;
    private SimLockPreferenceController mSimLockPreferenceController;
    private ShowPasswordPreferenceController mShowPasswordPreferenceController;
    private TrustAgentListPreferenceController mTrustAgentListPreferenceController;

    @Override
    public int getMetricsCategory() {
@@ -145,7 +138,7 @@ public class SecuritySettingsV2 extends DashboardFragment
        mDashboardFeatureProvider = FeatureFactory.getFactory(context)
                .getDashboardFeatureProvider(context);

        mTrustAgentManager = mSecurityFeatureProvider.getTrustAgentManager();
        mChooseLockSettingsHelper = new ChooseLockSettingsHelper(getActivity());
    }

    @Override
@@ -172,21 +165,11 @@ public class SecuritySettingsV2 extends DashboardFragment
        mShowPasswordPreferenceController = new ShowPasswordPreferenceController(context);
        mEncryptionStatusPreferenceController = new EncryptionStatusPreferenceController(
                context, PREF_KEY_ENCRYPTION_SECURITY_PAGE);
        mTrustAgentListPreferenceController = new TrustAgentListPreferenceController(getActivity(),
                this /* host */, getLifecycle());
        return null;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mChooseLockSettingsHelper = new ChooseLockSettingsHelper(getActivity());

        if (savedInstanceState != null
                && savedInstanceState.containsKey(TRUST_AGENT_CLICK_INTENT)) {
            mTrustAgentClickIntent = savedInstanceState.getParcelable(TRUST_AGENT_CLICK_INTENT);
        }
    }

    private static int getResIdForLockUnlockScreen(LockPatternUtils lockPatternUtils,
            ManagedLockPasswordProvider managedPasswordProvider, int userId) {
        final boolean isMyUser = userId == MY_USER_ID;
@@ -237,6 +220,7 @@ public class SecuritySettingsV2 extends DashboardFragment
        }
        addPreferencesFromResource(R.xml.security_settings_v2);
        root = getPreferenceScreen();
        mTrustAgentListPreferenceController.displayPreference(root);

        // Add options for lock/unlock screen
        final int resid = getResIdForLockUnlockScreen(mLockPatternUtils,
@@ -272,7 +256,6 @@ public class SecuritySettingsV2 extends DashboardFragment
                        mProfileChallengeUserId);
            }
        }

        Preference unlockSetOrChange = findPreference(KEY_UNLOCK_SET_OR_CHANGE);
        if (unlockSetOrChange instanceof GearPreference) {
            ((GearPreference) unlockSetOrChange).setOnGearClickListener(this);
@@ -284,7 +267,6 @@ public class SecuritySettingsV2 extends DashboardFragment
                root.findPreference(KEY_SECURITY_CATEGORY);
        if (securityCategory != null) {
            maybeAddFingerprintPreference(securityCategory, UserHandle.myUserId());
            addTrustAgentSettings(securityCategory);
            setLockscreenPreferencesSummary(securityCategory);
        }

@@ -379,34 +361,6 @@ public class SecuritySettingsV2 extends DashboardFragment
        }
    }

    // Return the number of trust agents being added
    private int addTrustAgentSettings(PreferenceGroup securityCategory) {
        final boolean hasSecurity = mLockPatternUtils.isSecure(MY_USER_ID);
        final List<TrustAgentManager.TrustAgentComponentInfo> agents =
                mTrustAgentManager.getActiveTrustAgents(getActivity(), mLockPatternUtils);
        for (TrustAgentManager.TrustAgentComponentInfo agent : agents) {
            final RestrictedPreference trustAgentPreference =
                    new RestrictedPreference(securityCategory.getContext());
            trustAgentPreference.setKey(KEY_TRUST_AGENT);
            trustAgentPreference.setTitle(agent.title);
            trustAgentPreference.setSummary(agent.summary);
            // Create intent for this preference.
            Intent intent = new Intent();
            intent.setComponent(agent.componentName);
            intent.setAction(Intent.ACTION_MAIN);
            trustAgentPreference.setIntent(intent);
            // Add preference to the settings menu.
            securityCategory.addPreference(trustAgentPreference);

            trustAgentPreference.setDisabledByAdmin(agent.admin);
            if (!trustAgentPreference.isDisabledByAdmin() && !hasSecurity) {
                trustAgentPreference.setEnabled(false);
                trustAgentPreference.setSummary(R.string.disabled_because_no_backup_security);
            }
        }
        return agents.size();
    }

    @Override
    public void onGearClick(GearPreference p) {
        if (KEY_UNLOCK_SET_OR_CHANGE.equals(p.getKey())) {
@@ -414,14 +368,6 @@ public class SecuritySettingsV2 extends DashboardFragment
        }
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        if (mTrustAgentClickIntent != null) {
            outState.putParcelable(TRUST_AGENT_CLICK_INTENT, mTrustAgentClickIntent);
        }
    }

    @Override
    public void onResume() {
        super.onResume();
@@ -445,7 +391,7 @@ public class SecuritySettingsV2 extends DashboardFragment
        final Preference encryptionStatusPref = getPreferenceScreen().findPreference(
                mEncryptionStatusPreferenceController.getPreferenceKey());
        mEncryptionStatusPreferenceController.updateState(encryptionStatusPref);

        mTrustAgentListPreferenceController.onResume();
        mLocationController.updateSummary();
    }

@@ -465,6 +411,9 @@ public class SecuritySettingsV2 extends DashboardFragment

    @Override
    public boolean onPreferenceTreeClick(Preference preference) {
        if (mTrustAgentListPreferenceController.handlePreferenceTreeClick(preference)) {
            return true;
        }
        final String key = preference.getKey();
        if (KEY_UNLOCK_SET_OR_CHANGE.equals(key)) {
            // TODO(b/35930129): Remove once existing password can be passed into vold directly.
@@ -491,17 +440,6 @@ public class SecuritySettingsV2 extends DashboardFragment
            startFragment(this, ChooseLockGeneric.ChooseLockGenericFragment.class.getName(),
                    R.string.lock_settings_picker_title_profile,
                    SET_OR_CHANGE_LOCK_METHOD_REQUEST_PROFILE, extras);
        } else if (KEY_TRUST_AGENT.equals(key)) {
            ChooseLockSettingsHelper helper =
                    new ChooseLockSettingsHelper(this.getActivity(), this);
            mTrustAgentClickIntent = preference.getIntent();
            boolean confirmationLaunched = helper.launchConfirmationActivity(
                    CHANGE_TRUST_AGENT_SETTINGS, preference.getTitle());
            if (!confirmationLaunched && mTrustAgentClickIntent != null) {
                // If this returns false, it means no password confirmation is required.
                startActivity(mTrustAgentClickIntent);
                mTrustAgentClickIntent = null;
            }
        } else {
            // If we didn't handle it, let preferences handle it.
            return super.onPreferenceTreeClick(preference);
@@ -516,10 +454,7 @@ public class SecuritySettingsV2 extends DashboardFragment
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == CHANGE_TRUST_AGENT_SETTINGS && resultCode == Activity.RESULT_OK) {
            if (mTrustAgentClickIntent != null) {
                startActivity(mTrustAgentClickIntent);
                mTrustAgentClickIntent = null;
            }
            mTrustAgentListPreferenceController.handleActivityResult(resultCode);
            return;
        } else if (requestCode == UNIFY_LOCK_CONFIRM_DEVICE_REQUEST
                && resultCode == Activity.RESULT_OK) {
@@ -760,15 +695,9 @@ public class SecuritySettingsV2 extends DashboardFragment
        @Override
        public List<String> getNonIndexableKeys(Context context) {
            final List<String> keys = super.getNonIndexableKeys(context);
            final LockPatternUtils lockPatternUtils = new LockPatternUtils(context);

            new SimLockPreferenceController(context).updateNonIndexableKeys(keys);

            // TrustAgent settings disappear when the user has no primary security.
            if (!lockPatternUtils.isSecure(MY_USER_ID)) {
                keys.add(KEY_TRUST_AGENT);
            }

            if (!(new EnterprisePrivacyPreferenceController(context))
                    .isAvailable()) {
                keys.add(KEY_ENTERPRISE_PRIVACY);
+172 −0
Original line number Diff line number Diff line
/*
 * 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.security.trustagent;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.UserHandle;
import android.support.annotation.VisibleForTesting;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceCategory;
import android.support.v7.preference.PreferenceScreen;
import android.text.TextUtils;

import com.android.internal.widget.LockPatternUtils;
import com.android.settings.R;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.password.ChooseLockSettingsHelper;
import com.android.settings.security.SecurityFeatureProvider;
import com.android.settings.security.SecuritySettingsV2;
import com.android.settingslib.RestrictedPreference;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnCreate;
import com.android.settingslib.core.lifecycle.events.OnResume;
import com.android.settingslib.core.lifecycle.events.OnSaveInstanceState;

import java.util.List;

public class TrustAgentListPreferenceController extends AbstractPreferenceController
        implements LifecycleObserver, OnSaveInstanceState, OnCreate, OnResume {

    private static final String TRUST_AGENT_CLICK_INTENT = "trust_agent_click_intent";
    @VisibleForTesting
    static final String PREF_KEY_TRUST_AGENT = "trust_agent";
    @VisibleForTesting
    static final String PREF_KEY_SECURITY_CATEGORY = "security_category";
    private static final int MY_USER_ID = UserHandle.myUserId();

    private final LockPatternUtils mLockPatternUtils;
    private final TrustAgentManager mTrustAgentManager;
    private final Activity mActivity;
    private final SecuritySettingsV2 mHost;

    private Intent mTrustAgentClickIntent;
    private PreferenceCategory mSecurityCategory;

    public TrustAgentListPreferenceController(Activity activity, SecuritySettingsV2 host,
            Lifecycle lifecycle) {
        super(activity);
        final SecurityFeatureProvider provider = FeatureFactory.getFactory(activity)
                .getSecurityFeatureProvider();
        mActivity = activity;
        mHost = host;
        mLockPatternUtils = provider.getLockPatternUtils(activity);
        mTrustAgentManager = provider.getTrustAgentManager();
        if (lifecycle != null) {
            lifecycle.addObserver(this);
        }
    }

    @Override
    public boolean isAvailable() {
        return true;
    }

    @Override
    public String getPreferenceKey() {
        return PREF_KEY_TRUST_AGENT;
    }

    @Override
    public void displayPreference(PreferenceScreen screen) {
        super.displayPreference(screen);
        mSecurityCategory = (PreferenceCategory) screen.findPreference(PREF_KEY_SECURITY_CATEGORY);
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        if (savedInstanceState != null
                && savedInstanceState.containsKey(TRUST_AGENT_CLICK_INTENT)) {
            mTrustAgentClickIntent = savedInstanceState.getParcelable(TRUST_AGENT_CLICK_INTENT);
        }
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        if (mTrustAgentClickIntent != null) {
            outState.putParcelable(TRUST_AGENT_CLICK_INTENT, mTrustAgentClickIntent);
        }
    }

    @Override
    public boolean handlePreferenceTreeClick(Preference preference) {
        if (!TextUtils.equals(preference.getKey(), getPreferenceKey())) {
            return super.handlePreferenceTreeClick(preference);
        }
        final ChooseLockSettingsHelper helper = new ChooseLockSettingsHelper(mActivity, mHost);
        mTrustAgentClickIntent = preference.getIntent();
        boolean confirmationLaunched = helper.launchConfirmationActivity(
                SecuritySettingsV2.CHANGE_TRUST_AGENT_SETTINGS, preference.getTitle());

        if (!confirmationLaunched && mTrustAgentClickIntent != null) {
            // If this returns false, it means no password confirmation is required.
            mHost.startActivity(mTrustAgentClickIntent);
            mTrustAgentClickIntent = null;
        }
        return true;
    }

    @Override
    public void onResume() {
        if (mSecurityCategory == null) {
            return;
        }
        // First remove all old trust agents.
        while (true) {
            final Preference oldAgent = mSecurityCategory.findPreference(PREF_KEY_TRUST_AGENT);
            if (oldAgent == null) {
                break;
            } else {
                mSecurityCategory.removePreference(oldAgent);
            }
        }
        // Then add new ones.
        final boolean hasSecurity = mLockPatternUtils.isSecure(MY_USER_ID);
        final List<TrustAgentManager.TrustAgentComponentInfo> agents =
                mTrustAgentManager.getActiveTrustAgents(mContext, mLockPatternUtils);
        if (agents == null) {
            return;
        }
        for (TrustAgentManager.TrustAgentComponentInfo agent : agents) {
            final RestrictedPreference trustAgentPreference =
                    new RestrictedPreference(mSecurityCategory.getContext());
            trustAgentPreference.setKey(PREF_KEY_TRUST_AGENT);
            trustAgentPreference.setTitle(agent.title);
            trustAgentPreference.setSummary(agent.summary);
            // Create intent for this preference.
            trustAgentPreference.setIntent(new Intent(Intent.ACTION_MAIN)
                    .setComponent(agent.componentName));
            trustAgentPreference.setDisabledByAdmin(agent.admin);
            if (!trustAgentPreference.isDisabledByAdmin() && !hasSecurity) {
                trustAgentPreference.setEnabled(false);
                trustAgentPreference.setSummary(R.string.disabled_because_no_backup_security);
            }
            // Add preference to the settings menu.
            mSecurityCategory.addPreference(trustAgentPreference);
        }
    }

    public void handleActivityResult(int resultCode) {
        if (resultCode == Activity.RESULT_OK && mTrustAgentClickIntent != null) {
            mHost.startActivity(mTrustAgentClickIntent);
            mTrustAgentClickIntent = null;
        }
    }
}
+132 −0
Original line number Diff line number Diff line
/*
 * 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.security.trustagent;


import static com.android.settings.security.trustagent.TrustAgentListPreferenceController
        .PREF_KEY_SECURITY_CATEGORY;
import static com.android.settings.security.trustagent.TrustAgentListPreferenceController
        .PREF_KEY_TRUST_AGENT;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceCategory;
import android.support.v7.preference.PreferenceScreen;

import com.android.internal.widget.LockPatternUtils;
import com.android.settings.TestConfig;
import com.android.settings.security.SecuritySettingsV2;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settingslib.core.lifecycle.Lifecycle;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.Robolectric;
import org.robolectric.annotation.Config;

import java.util.ArrayList;
import java.util.List;

@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class TrustAgentListPreferenceControllerTest {

    @Mock
    private TrustAgentManager mTrustAgentManager;
    @Mock
    private LockPatternUtils mLockPatternUtils;
    @Mock
    private PreferenceScreen mScreen;
    @Mock
    private PreferenceCategory mCategory;
    @Mock
    private SecuritySettingsV2 mFragment;

    private Lifecycle mLifecycle;
    private FakeFeatureFactory mFeatureFactory;
    private Activity mActivity;

    private TrustAgentListPreferenceController mController;


    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
        mActivity = Robolectric.buildActivity(Activity.class).get();
        mLifecycle = new Lifecycle(() -> mLifecycle);
        mFeatureFactory = FakeFeatureFactory.setupForTest();
        when(mFeatureFactory.securityFeatureProvider.getLockPatternUtils(any(Context.class)))
                .thenReturn(mLockPatternUtils);
        when(mFeatureFactory.securityFeatureProvider.getTrustAgentManager())
                .thenReturn(mTrustAgentManager);
        when(mCategory.getKey()).thenReturn(PREF_KEY_SECURITY_CATEGORY);
        when(mCategory.getContext()).thenReturn(mActivity);
        when(mScreen.findPreference(PREF_KEY_SECURITY_CATEGORY))
                .thenReturn(mCategory);
        mController = new TrustAgentListPreferenceController(mActivity, mFragment, mLifecycle);
    }

    @Test
    public void testConstants() {
        assertThat(mController.isAvailable()).isTrue();
        assertThat(mController.getPreferenceKey()).isEqualTo(PREF_KEY_TRUST_AGENT);
    }

    @Test
    public void onResume_shouldClearOldAgents() {
        final Preference oldAgent = new Preference(mActivity);
        oldAgent.setKey(PREF_KEY_TRUST_AGENT);
        when(mCategory.findPreference(PREF_KEY_TRUST_AGENT))
                .thenReturn(oldAgent)
                .thenReturn(null);

        mController.displayPreference(mScreen);
        mController.onResume();

        verify(mCategory).removePreference(oldAgent);
    }

    @Test
    public void onResume_shouldAddNewAgents() {
        final List<TrustAgentManager.TrustAgentComponentInfo> agents = new ArrayList<>();
        final TrustAgentManager.TrustAgentComponentInfo agent = mock(
                TrustAgentManager.TrustAgentComponentInfo.class);
        agent.title = "Test_title";
        agent.summary = "test summary";
        agent.componentName = new ComponentName("pkg", "agent");
        agent.admin = null;
        agents.add(agent);
        when(mTrustAgentManager.getActiveTrustAgents(mActivity, mLockPatternUtils))
                .thenReturn(agents);

        mController.displayPreference(mScreen);
        mController.onResume();

        verify(mCategory).addPreference(any(Preference.class));
    }
}