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

Commit a6d36c4e authored by Eran Messeri's avatar Eran Messeri Committed by Android (Google) Code Review
Browse files

Merge "Require work profile to be unlocked for changing notification settings...

Merge "Require work profile to be unlocked for changing notification settings in a different way" into pi-dev
parents 8dcd550d f61ccf3f
Loading
Loading
Loading
Loading
+36 −1
Original line number Diff line number Diff line
@@ -16,10 +16,16 @@

package com.android.settings;

import android.app.ActivityManager;
import android.app.AlertDialog;
import android.app.KeyguardManager;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.UserManager;
import android.support.annotation.VisibleForTesting;
import android.support.v14.preference.ListPreferenceDialogFragment;
import android.support.v7.preference.PreferenceViewHolder;
import android.util.AttributeSet;
@@ -32,6 +38,7 @@ import android.widget.ImageView;
import android.widget.ListAdapter;
import android.widget.ListView;

import com.android.settings.Utils;
import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedPreferenceHelper;

@@ -43,6 +50,8 @@ import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
public class RestrictedListPreference extends CustomListPreference {
    private final RestrictedPreferenceHelper mHelper;
    private final List<RestrictedItem> mRestrictedItems = new ArrayList<>();
    private boolean mRequiresActiveUnlockedProfile = false;
    private int mProfileUserId;

    public RestrictedListPreference(Context context, AttributeSet attrs) {
        super(context, attrs);
@@ -68,6 +77,24 @@ public class RestrictedListPreference extends CustomListPreference {

    @Override
    public void performClick() {
        if (mRequiresActiveUnlockedProfile) {
            // Check if the profile is started, first.
            if (Utils.startQuietModeDialogIfNecessary(getContext(), UserManager.get(getContext()),
                    mProfileUserId)) {
                return;
            }

            // Next, check if the profile is unlocked.
            KeyguardManager manager =
                    (KeyguardManager) getContext().getSystemService(Context.KEYGUARD_SERVICE);
            if (manager.isDeviceLocked(mProfileUserId)) {
                Intent intent = manager.createConfirmDeviceCredentialIntent(
                        null, null, mProfileUserId);
                getContext().startActivity(intent);
                return;
            }
        }

        if (!mHelper.performClick()) {
            super.performClick();
        }
@@ -92,6 +119,14 @@ public class RestrictedListPreference extends CustomListPreference {
        return mHelper.isDisabledByAdmin();
    }

    public void setRequiresActiveUnlockedProfile(boolean reqState) {
        mRequiresActiveUnlockedProfile = reqState;
    }

    public void setProfileUserId(int profileUserId) {
        mProfileUserId = profileUserId;
    }

    public boolean isRestrictedForEntry(CharSequence entry) {
        if (entry == null) {
            return false;
+2 −37
Original line number Diff line number Diff line
@@ -19,16 +19,12 @@ package com.android.settings.notification;
import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_SECURE_NOTIFICATIONS;
import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS;

import android.app.ActivityManager;
import android.app.admin.DevicePolicyManager;
import android.app.KeyguardManager;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Handler;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
@@ -101,6 +97,8 @@ public class LockScreenNotificationPreferenceController extends AbstractPreferen
        }
        if (mProfileUserId != UserHandle.USER_NULL) {
            mLockscreenProfile = (RestrictedListPreference) screen.findPreference(mWorkSettingKey);
            mLockscreenProfile.setRequiresActiveUnlockedProfile(true);
            mLockscreenProfile.setProfileUserId(mProfileUserId);
        } else {
            setVisible(screen, mWorkSettingKey, false /* visible */);
            setVisible(screen, mWorkSettingCategoryKey, false /* visible */);
@@ -244,39 +242,6 @@ public class LockScreenNotificationPreferenceController extends AbstractPreferen
        return false;
    }

    @Override
    public boolean handlePreferenceTreeClick(Preference preference) {
        final String key = preference.getKey();
        if (!TextUtils.equals(mWorkSettingKey, key)) {
            return false;
        }

        // Check if the profile is started, first.
        if (Utils.startQuietModeDialogIfNecessary(mContext, UserManager.get(mContext),
                    mProfileUserId)) {
            return true;
        }

        // Next, check if the profile is unlocked.
        KeyguardManager manager =
                (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
        if (manager.isDeviceLocked(mProfileUserId)) {
            //TODO: Figure out how to return the user to the current activity so they
            //don't have to navigate to the settings again.
            Intent intent = manager.createConfirmDeviceCredentialIntent(
                    null, null, mProfileUserId);
            try {
                ActivityManager.getService().startConfirmDeviceCredentialIntent(intent,
                        null /*options*/);
            } catch (RemoteException ignored) {
            }

            return true;
        }

        return false;
    }

    private void setRestrictedIfNotificationFeaturesDisabled(CharSequence entry,
            CharSequence entryValue, int keyguardNotificationFeatures) {
        RestrictedLockUtils.EnforcedAdmin admin =
+124 −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;

import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.robolectric.RuntimeEnvironment.application;
import static org.robolectric.Shadows.shadowOf;

import android.app.KeyguardManager;
import android.content.Intent;
import android.os.Bundle;
import android.util.AttributeSet;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.shadow.ShadowUserManager;
import com.android.settingslib.RestrictedPreferenceHelper;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.Shadows;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowKeyguardManager;
import org.robolectric.util.ReflectionHelpers;

@RunWith(SettingsRobolectricTestRunner.class)
@Config(
        shadows = {
            ShadowUserManager.class,
            ShadowKeyguardManager.class,
        })
public class RestrictedListPreferenceTest {
    private static final int PROFILE_USER_ID = 11;
    // From UnlaunchableAppActivity
    private static final int UNLAUNCHABLE_REASON_QUIET_MODE = 1;
    private static final String EXTRA_UNLAUNCHABLE_REASON = "unlaunchable_reason";

    private ShadowUserManager mShadowUserManager;
    private ShadowKeyguardManager mShadowKeyguardManager;
    private RestrictedListPreference mPreference;
    private RestrictedPreferenceHelper mMockHelper;

    @Before
    public void setUp() {
        mShadowKeyguardManager =
                Shadows.shadowOf(application.getSystemService(KeyguardManager.class));
        mMockHelper = mock(RestrictedPreferenceHelper.class);
        mShadowUserManager = ShadowUserManager.getShadow();
        mPreference = new RestrictedListPreference(application, mock(AttributeSet.class));
        mPreference.setProfileUserId(PROFILE_USER_ID);
        ReflectionHelpers.setField(mPreference, "mHelper", mMockHelper);
    }

    @Test
    public void performClick_profileLocked() {
        mPreference.setRequiresActiveUnlockedProfile(true);
        mShadowUserManager.setQuietModeEnabled(false);
        mShadowKeyguardManager.setIsDeviceLocked(PROFILE_USER_ID, true);
        // Device has to be marked as secure so the real KeyguardManager will create a non-null
        // intent.
        mShadowKeyguardManager.setIsDeviceSecure(PROFILE_USER_ID, true);
        mPreference.performClick();
        // Make sure that the performClick method on the helper is never reached.
        verify(mMockHelper, never()).performClick();
        // Assert that a CONFIRM_DEVICE_CREDENTIAL intent has been started.
        Intent started = shadowOf(application).getNextStartedActivity();
        assertThat(started.getExtras().getInt(Intent.EXTRA_USER_ID)).isEqualTo(PROFILE_USER_ID);
        assertThat(started.getAction())
                .isEqualTo(KeyguardManager.ACTION_CONFIRM_DEVICE_CREDENTIAL_WITH_USER);
    }

    @Test
    public void performClick_profileDisabled() {
        mPreference.setRequiresActiveUnlockedProfile(true);
        mShadowUserManager.setQuietModeEnabled(true);
        mShadowKeyguardManager.setIsDeviceLocked(PROFILE_USER_ID, false);
        mPreference.performClick();
        // Make sure that the performClick method on the helper is never reached.
        verify(mMockHelper, never()).performClick();
        // Assert that a new intent for enabling the work profile is started.
        Intent started = shadowOf(application).getNextStartedActivity();
        Bundle extras = started.getExtras();
        int reason = extras.getInt(EXTRA_UNLAUNCHABLE_REASON);
        assertThat(reason).isEqualTo(UNLAUNCHABLE_REASON_QUIET_MODE);
    }

    @Test
    public void performClick_profileAvailable() {
        // Verify that the helper's perfomClick method is called if the profile is
        // available and unlocked.
        mPreference.setRequiresActiveUnlockedProfile(true);
        mShadowUserManager.setQuietModeEnabled(false);
        mShadowKeyguardManager.setIsDeviceLocked(PROFILE_USER_ID, false);
        when(mMockHelper.performClick()).thenReturn(true);
        mPreference.performClick();
        verify(mMockHelper).performClick();
    }

    @Test
    public void performClick_profileLockedAndUnlockedProfileNotRequired() {
        // Verify that even if the profile is disabled, if the Preference class does not
        // require it than the regular flow takes place.
        mPreference.setRequiresActiveUnlockedProfile(false);
        mShadowUserManager.setQuietModeEnabled(true);
        when(mMockHelper.performClick()).thenReturn(true);
        mPreference.performClick();
        verify(mMockHelper).performClick();
    }
}
+11 −0
Original line number Diff line number Diff line
@@ -44,6 +44,7 @@ public class ShadowUserManager extends org.robolectric.shadows.ShadowUserManager
    private final Map<String, List<EnforcingUser>> mRestrictionSources = new HashMap<>();
    private final List<UserInfo> mUserProfileInfos = new ArrayList<>();
    private final Set<Integer> mManagedProfiles = new HashSet<>();
    private boolean mIsQuietModeEnabled = false;

    @Resetter
    public void reset() {
@@ -52,6 +53,7 @@ public class ShadowUserManager extends org.robolectric.shadows.ShadowUserManager
        mUserProfileInfos.clear();
        mRestrictionSources.clear();
        mManagedProfiles.clear();
        mIsQuietModeEnabled = false;
    }

    public void setUserInfo(int userHandle, UserInfo userInfo) {
@@ -110,4 +112,13 @@ public class ShadowUserManager extends org.robolectric.shadows.ShadowUserManager
    public void addManagedProfile(int userId) {
        mManagedProfiles.add(userId);
    }

    @Implementation
    public boolean isQuietModeEnabled(UserHandle userHandle) {
        return mIsQuietModeEnabled;
    }

    public void setQuietModeEnabled(boolean enabled) {
        mIsQuietModeEnabled = enabled;
    }
}