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

Commit 30e841ce authored by josephpv's avatar josephpv Committed by Joseph Vincent
Browse files

Add One Lock settings inside private space settings page

This includes below changes:
1. Add new sub settings page in Private Space settings with option to
   swithch between private profile lock and device screen lock
2. Call Private profile lock setup when swithcing to private lock from
   screen lock.
3. Preference to change private lock when a separate Private lock is set

Bug: 308862923
Test: atest UseOneLockPreferenceControllerTest,
PrivateSpaceLockControllerTest

Change-Id: I0a6d8c7dfbd0ffea19db03ffd6dfe7aa520c9684
parent 5c8204c5
Loading
Loading
Loading
Loading
+15 −1
Original line number Diff line number Diff line
@@ -1208,8 +1208,22 @@
    <string name="private_space_title">Private Space</string>
    <!-- Summary for the Private Space page. [CHAR LIMIT=NONE] -->
    <string name="private_space_summary">Hide apps in a private folder</string>
    <!-- Description for the Private Space page. [CHAR LIMIT=NONE] -->
    <string name="private_space_description">Hide apps in a private folder that only you can access</string>
    <!-- Title for the Private Space one lock preference. [CHAR LIMIT=60] -->
    <string name="private_space_one_lock_title">Unlock using screen lock</string>
    <string name="private_space_lock_title">Private Space lock</string>
    <!-- Description for the Private Space one lock preference page. [CHAR LIMIT=NONE] -->
    <string name="private_space_one_lock_summary">You can unlock Private Space the same way you unlock your device, or choose a different lock</string>
    <!-- Title for the Private Space one lock preference. [CHAR LIMIT=60] -->
    <string name="private_space_screen_lock_title">Use device screen lock</string>
    <!-- Title for the Face and Fingerprint preference. [CHAR LIMIT=60] -->
    <string name="private_space_biometric_title">Face &amp; Fingerprint Unlock</string>
    <!-- Summary for the Face and Fingerprint preference when no biometric is set. [CHAR LIMIT=60] -->
    <string name="private_space_biometric_summary">Tap to set up</string>
    <!-- Summary for one lock when device screen lock is used as private profile lock. [CHAR LIMIT=60] -->
    <string name="private_space_screen_lock_summary">Same as device screen lock</string>
    <!-- Dialog message to choose a new lock for Private Space. [CHAR LIMIT=50] -->
    <string name="private_space_new_lock_title">Choose a new lock for Private Space?</string>
    <!-- Title for the preference to hide Private Space. [CHAR LIMIT=60] -->
    <string name="private_space_hide_title">Hide when locked</string>
    <!-- Title for the hide Private Space setting. [CHAR LIMIT=60] -->
+16 −4
Original line number Diff line number Diff line
@@ -22,13 +22,25 @@
    android:title="@string/private_space_title"
    settings:searchable="false">

    <com.android.settingslib.widget.IllustrationPreference
        android:key="privatespace_hide_video"
        settings:searchable="false"
        settings:lottie_rawRes="@drawable/privatespace_placeholder_image"/>

    <Preference
        android:key="private_space_description"
        android:summary="@string/private_space_description"
        android:selectable="false"
        settings:searchable="false" />

    <PreferenceCategory
        android:title="@string/security_header">

        <SwitchPreferenceCompat
        <Preference
            android:key="private_space_use_one_lock"
            android:title="@string/private_space_one_lock_title"
            settings:controller="com.android.settings.privatespace.UseOneLockController"
            android:title="@string/private_space_lock_title"
            android:fragment="com.android.settings.privatespace.onelock.UseOneLockSettingsFragment"
            settings:controller="com.android.settings.privatespace.onelock.UseOneLockController"
            settings:searchable="false" />

        <Preference
+44 −0
Original line number Diff line number Diff line
<!--
  ~ Copyright (C) 2023 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.
  -->
<PreferenceScreen
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:settings="http://schemas.android.com/apk/res-auto"
    android:title="@string/private_space_lock_title"
    settings:searchable="false" >

    <com.android.settingslib.widget.TopIntroPreference
        android:title="@string/private_space_one_lock_summary"
        settings:searchable="false" />

    <com.android.settingslib.widget.MainSwitchPreference
        android:key="private_lock_unification"
        android:title="@string/private_space_screen_lock_title"
        settings:searchable="false" />

    <Preference
        android:key="change_private_space_lock"
        android:title="@string/private_space_lock_title"
        android:summary="@string/unlock_set_unlock_mode_pattern"
        settings:searchable="false" />

    <Preference
        android:key="private_space_biometrics"
        android:title="@string/private_space_biometric_title"
        android:summary="@string/private_space_biometric_summary"
        android:fragment="com.android.settings.privatespace.onelock.FaceFingerprintUnlockFragment"
        settings:searchable="false" />

</PreferenceScreen>
+57 −0
Original line number Diff line number Diff line
@@ -14,37 +14,44 @@
 * limitations under the License.
 */

package com.android.settings.privatespace;
package com.android.settings.privatespace.onelock;

import android.content.Context;
import android.text.TextUtils;

import com.android.settings.core.TogglePreferenceController;
import androidx.preference.Preference;

/** Represents the preference controller for using the same lock as the screen lock */
public class UseOneLockController extends TogglePreferenceController {
    public UseOneLockController(Context context, String preferenceKey) {
        super(context, preferenceKey);
import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
import com.android.settingslib.core.AbstractPreferenceController;

/** Represents the preference controller to enroll biometrics for private space lock. */
public class FaceFingerprintUnlockController extends AbstractPreferenceController {
    private static final String KEY_SET_UNSET_FACE_FINGERPRINT = "private_space_biometrics";

    public FaceFingerprintUnlockController(Context context, SettingsPreferenceFragment host) {
        super(context);
    }

    @Override
    public int getAvailabilityStatus() {
        return AVAILABLE;
    public boolean isAvailable() {
        return false;
    }

    @Override
    public boolean isChecked() {
        // TODO(b/293569406) Need to save this to a persistent store, maybe like SettingsProvider
        return false;
    public String getPreferenceKey() {
        return KEY_SET_UNSET_FACE_FINGERPRINT;
    }

    @Override
    public boolean setChecked(boolean isChecked) {
        // TODO(b/293569406) Need to save this to a persistent store, maybe like SettingsProvider
        return true;
    public boolean handlePreferenceTreeClick(Preference preference) {
        return TextUtils.equals(preference.getKey(), getPreferenceKey());
    }

    @Override
    public int getSliceHighlightMenuRes() {
        return 0;
    public void updateState(Preference preference) {
        //TODO(b/308862923) : Add condition to check and enable when separate private lock is set.
        preference.setSummary(mContext.getString(R.string.lock_settings_profile_unified_summary));
        preference.setEnabled(false);
    }
}
+134 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 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.privatespace.onelock;

import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSWORD;
import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PATTERN;
import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PIN;
import static com.android.settings.password.ChooseLockGeneric.ChooseLockGenericFragment.HIDE_INSECURE_OPTIONS;

import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.UserHandle;
import android.os.UserManager;
import android.text.TextUtils;
import android.util.Log;

import androidx.preference.Preference;

import com.android.internal.widget.LockPatternUtils;
import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.Utils;
import com.android.settings.core.SubSettingLauncher;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.password.ChooseLockGeneric;
import com.android.settings.privatespace.PrivateSpaceMaintainer;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.transition.SettingsTransitionHelper;


/** Represents the preference controller for changing private space lock. */
public class PrivateSpaceLockController extends AbstractPreferenceController {
    private static final String TAG = "PrivateSpaceLockContr";
    private static final String KEY_CHANGE_PROFILE_LOCK =
            "change_private_space_lock";

    private final SettingsPreferenceFragment mHost;
    private final UserManager mUserManager;
    private final LockPatternUtils mLockPatternUtils;
    private final int mProfileUserId;

    public PrivateSpaceLockController(Context context, SettingsPreferenceFragment host) {
        super(context);
        mUserManager = context.getSystemService(UserManager.class);
        mLockPatternUtils = FeatureFactory.getFeatureFactory()
                .getSecurityFeatureProvider()
                .getLockPatternUtils(context);
        mHost = host;
        UserHandle privateProfileHandle = PrivateSpaceMaintainer.getInstance(context)
                .getPrivateProfileHandle();
        if (privateProfileHandle != null) {
            mProfileUserId = privateProfileHandle.getIdentifier();
        } else {
            mProfileUserId = -1;
            Log.e(TAG, "Private profile user handle is not expected to be null.");
        }
    }

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

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

    @Override
    public boolean handlePreferenceTreeClick(Preference preference) {
        if (!TextUtils.equals(preference.getKey(), getPreferenceKey())) {
            return false;
        }
        //Checks if the profile is in quiet mode and show a dialog to unpause the profile.
        if (Utils.startQuietModeDialogIfNecessary(mContext, mUserManager,
                mProfileUserId)) {
            return false;
        }
        final Bundle extras = new Bundle();
        extras.putInt(Intent.EXTRA_USER_ID, mProfileUserId);
        extras.putBoolean(HIDE_INSECURE_OPTIONS, true);
        new SubSettingLauncher(mContext)
                .setDestination(ChooseLockGeneric.ChooseLockGenericFragment.class.getName())
                .setSourceMetricsCategory(mHost.getMetricsCategory())
                .setArguments(extras)
                .setExtras(extras)
                .setTransitionType(SettingsTransitionHelper.TransitionType.TRANSITION_SLIDE)
                .launch();
        return true;
    }

    @Override
    public void updateState(Preference preference) {
        if (mLockPatternUtils.isSeparateProfileChallengeEnabled(mProfileUserId)) {
            preference.setSummary(
                    mContext.getString(getCredentialTypeResId(mProfileUserId)));
            preference.setEnabled(true);
        } else {
            preference.setSummary(mContext.getString(
                    R.string.lock_settings_profile_unified_summary));
            preference.setEnabled(false);
        }
    }

    private int getCredentialTypeResId(int userId) {
        int credentialType = mLockPatternUtils.getCredentialTypeForUser(userId);
        switch (credentialType) {
            case CREDENTIAL_TYPE_PATTERN :
                return R.string.unlock_set_unlock_mode_pattern;
            case CREDENTIAL_TYPE_PIN:
                return R.string.unlock_set_unlock_mode_pin;
            case CREDENTIAL_TYPE_PASSWORD:
                return R.string.unlock_set_unlock_mode_password;
            default:
                // This is returned for CREDENTIAL_TYPE_NONE
                return R.string.unlock_set_unlock_mode_off;
        }
    }
}
Loading