Add toggle to hide private space entry point in All Apps

This change includes implementaion for below:
1. Add a preference inside private space settings page with a toggle switch to control hide/unhide
   private space entry in All Apps
2. Store the preference value in settingsprovider for persistence.

Bug: 302682054
Test: Manual
Change-Id: Ia1a56fc2c43550e23c00a61a5ce4742e42effcbe
This commit is contained in:
josephpv
2023-10-11 16:15:23 +00:00
committed by Joseph Vincent
parent 27dd22302f
commit eace275921
12 changed files with 392 additions and 15 deletions

View File

@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="?android:attr/colorAccent"
android:pathData="M480,880Q397,880 324,848.5Q251,817 197,763Q143,709 111.5,636Q80,563 80,480Q80,397 111.5,324Q143,251 197,197Q251,143 324,111.5Q397,80 480,80Q563,80 636,111.5Q709,143 763,197Q817,251 848.5,324Q880,397 880,480Q880,563 848.5,636Q817,709 763,763Q709,817 636,848.5Q563,880 480,880ZM480,800Q614,800 707,707Q800,614 800,480Q800,346 707,253Q614,160 480,160Q346,160 253,253Q160,346 160,480Q160,614 253,707Q346,800 480,800ZM480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480ZM460,680L540,680L540,280L380,280L380,360L460,360L460,680Z"/>
</vector>

View File

@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="?android:attr/colorAccent"
android:pathData="M480,880Q397,880 324,848.5Q251,817 197,763Q143,709 111.5,636Q80,563 80,480Q80,397 111.5,324Q143,251 197,197Q251,143 324,111.5Q397,80 480,80Q563,80 636,111.5Q709,143 763,197Q817,251 848.5,324Q880,397 880,480Q880,563 848.5,636Q817,709 763,763Q709,817 636,848.5Q563,880 480,880ZM480,800Q614,800 707,707Q800,614 800,480Q800,346 707,253Q614,160 480,160Q346,160 253,253Q160,346 160,480Q160,614 253,707Q346,800 480,800ZM480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480ZM360,680L600,680L600,600L440,600L440,520Q440,520 440,520Q440,520 440,520L520,520Q553,520 576.5,496.5Q600,473 600,440L600,360Q600,327 576.5,303.5Q553,280 520,280L360,280L360,360L520,360Q520,360 520,360Q520,360 520,360L520,440Q520,440 520,440Q520,440 520,440L440,440Q407,440 383.5,463.5Q360,487 360,520L360,680Z"/>
</vector>

View File

@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="?android:attr/colorAccent"
android:pathData="M480,880Q397,880 324,848.5Q251,817 197,763Q143,709 111.5,636Q80,563 80,480Q80,397 111.5,324Q143,251 197,197Q251,143 324,111.5Q397,80 480,80Q563,80 636,111.5Q709,143 763,197Q817,251 848.5,324Q880,397 880,480Q880,563 848.5,636Q817,709 763,763Q709,817 636,848.5Q563,880 480,880ZM480,800Q614,800 707,707Q800,614 800,480Q800,346 707,253Q614,160 480,160Q346,160 253,253Q160,346 160,480Q160,614 253,707Q346,800 480,800ZM480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480ZM360,680L520,680Q553,680 576.5,656.5Q600,633 600,600L600,540Q600,514 583,497Q566,480 540,480Q566,480 583,463Q600,446 600,420L600,360Q600,327 576.5,303.5Q553,280 520,280L360,280L360,360L520,360Q520,360 520,360Q520,360 520,360L520,440Q520,440 520,440Q520,440 520,440L440,440L440,520L520,520Q520,520 520,520Q520,520 520,520L520,600Q520,600 520,600Q520,600 520,600L360,600L360,680Z"/>
</vector>

File diff suppressed because one or more lines are too long

View File

@@ -1198,7 +1198,23 @@
<!-- Title for the Private Space one lock preference. [CHAR LIMIT=60] -->
<string name="private_space_one_lock_title">Unlock using screen lock</string>
<!-- Title for the preference to hide Private Space. [CHAR LIMIT=60] -->
<string name="private_space_hide_title">Show Private Space</string>
<string name="private_space_hide_title">Hide when locked</string>
<!-- Title for the hide Private Space setting. [CHAR LIMIT=60] -->
<string name="privatespace_hide_page_title">Hide Private Space when locked</string>
<!-- Description for hide Private Space settings page. [CHAR LIMIT=60] -->
<string name="privatespace_hide_page_summary">To stop other people knowing Private Space is on your device, you can hide it from your apps list</string>
<!-- Header in hide Private Space settings page to access Private Space when hidden. [CHAR LIMIT=60] -->
<string name="privatespace_access_header">Access Private Space when hidden</string>
<!-- Text in hide Private Space settings page on how to search Private Space when hidden. [CHAR LIMIT=60] -->
<string name="privatespace_search_description">Search for \'Private Space\' in the search bar</string>
<!-- Text in hide Private Space settings page to tap on Private Space tile. [CHAR LIMIT=60] -->
<string name="privatespace_tap_tile_description">Tap the Private Space tile</string>
<!-- Text in hide Private Space settings page to Unlock Private Space. [CHAR LIMIT=60] -->
<string name="privatespace_unlock_description">Unlock your Private Space</string>
<!-- Used to describe the off state of Private space hidden [CHAR LIMIT=30] -->
<string name="privatespace_hide_off_summary">Off</string>
<!-- Used to describe the off state of Private space hidden [CHAR LIMIT=30] -->
<string name="privatespace_hide_on_summary">On</string>
<!-- System category for the Private Space page. [CHAR LIMIT=30] -->
<string name="private_space_category_system">System</string>
<!-- Title for the preference to create Private Space. [CHAR LIMIT=60] -->

View File

@@ -31,10 +31,11 @@
settings:controller="com.android.settings.privatespace.UseOneLockController"
settings:searchable="false" />
<SwitchPreferenceCompat
<Preference
android:key="private_space_hidden"
android:title="@string/private_space_hide_title"
settings:controller="com.android.settings.privatespace.HidePrivateSpaceController"
android:fragment="com.android.settings.privatespace.HidePrivateSpaceSettings"
settings:controller="com.android.settings.privatespace.HidePrivateSpaceSummaryController"
settings:searchable="false" />
</PreferenceCategory>

View File

@@ -0,0 +1,63 @@
<!--
~ 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/privatespace_hide_page_title">
<com.android.settingslib.widget.IllustrationPreference
android:key="privatespace_hide_video"
settings:searchable="false"
settings:lottie_rawRes="@raw/lottie_privatespace_hide_placeholder"/>
<com.android.settingslib.widget.MainSwitchPreference
android:key="hide_when_locked"
android:title="@string/privatespace_hide_page_title"
settings:controller="com.android.settings.privatespace.HidePrivateSpaceController"/>
<Preference
android:key="private_space_hidden"
android:summary="@string/privatespace_hide_page_summary"
android:selectable="false"
settings:searchable="false" />
<PreferenceCategory
android:title="@string/privatespace_access_header">
<Preference
android:key="search_when_locked_footer"
android:icon="@drawable/counter_1_24dp"
android:title="@string/privatespace_search_description"
android:selectable="false"
settings:searchable="false" />
<Preference
android:key="tap_tile_footer"
android:icon="@drawable/counter_2_24dp"
android:title="@string/privatespace_tap_tile_description"
android:selectable="false"
settings:searchable="false" />
<Preference
android:key="unlock_profile_footer"
android:icon="@drawable/counter_3_24dp"
android:title="@string/privatespace_unlock_description"
android:selectable="false"
settings:searchable="false" />
</PreferenceCategory>
</PreferenceScreen>

View File

@@ -16,30 +16,41 @@
package com.android.settings.privatespace;
import static android.provider.Settings.Secure.HIDE_PRIVATESPACE_ENTRY_POINT;
import android.content.Context;
import android.provider.Settings;
import com.android.settings.core.TogglePreferenceController;
/** Represents the preference controller for (un)hiding the Private Space */
public final class HidePrivateSpaceController extends TogglePreferenceController {
public HidePrivateSpaceController(Context context, String preferenceKey) {
super(context, preferenceKey);
/**
* A class that is used to show details page for the setting to hide private space entry point
* in All Apps.
*/
public class HidePrivateSpaceController extends TogglePreferenceController {
private static final int DISABLED_VALUE = 0;
private static final int ENABLED_VALUE = 1;
public HidePrivateSpaceController(Context context, String key) {
super(context, key);
}
@Override
@AvailabilityStatus
public int getAvailabilityStatus() {
return AVAILABLE;
}
@Override
public boolean isChecked() {
// TODO(b/293569406) Need to check this from a persistent store, maybe like SettingsProvider
return false;
return Settings.Secure.getInt(mContext.getContentResolver(),
HIDE_PRIVATESPACE_ENTRY_POINT, DISABLED_VALUE) != DISABLED_VALUE;
}
@Override
public boolean setChecked(boolean isChecked) {
// TODO(b/293569406) Need to save this to a persistent store, maybe like SettingsProvider
Settings.Secure.putInt(mContext.getContentResolver(), HIDE_PRIVATESPACE_ENTRY_POINT,
isChecked ? ENABLED_VALUE : DISABLED_VALUE);
return true;
}

View File

@@ -0,0 +1,41 @@
/*
* 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;
import android.app.settings.SettingsEnums;
import com.android.settings.R;
import com.android.settings.dashboard.DashboardFragment;
public class HidePrivateSpaceSettings extends DashboardFragment{
private static final String TAG = "HidePrivateSpaceSettings";
@Override
public int getMetricsCategory() {
return SettingsEnums.PRIVATE_SPACE_SETTINGS;
}
@Override
protected int getPreferenceScreenResId() {
return R.xml.privatespace_hide_locked;
}
@Override
protected String getLogTag() {
return TAG;
}
}

View File

@@ -0,0 +1,57 @@
/*
* 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;
import static android.provider.Settings.Secure.HIDE_PRIVATESPACE_ENTRY_POINT;
import android.content.Context;
import android.provider.Settings;
import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
/**
* Represents the preference controller for (un)hiding Private Space entry point in All Apps and
* shows On/Off summary depending upon the settings provider value.
*/
public final class HidePrivateSpaceSummaryController extends BasePreferenceController {
public HidePrivateSpaceSummaryController(Context context, String preferenceKey) {
super(context, preferenceKey);
}
@Override
public int getAvailabilityStatus() {
return AVAILABLE;
}
@Override
public int getSliceHighlightMenuRes() {
return 0;
}
@Override
public CharSequence getSummary() {
return isHidden() ? mContext.getString(R.string.privatespace_hide_on_summary)
: mContext.getString(R.string.privatespace_hide_off_summary);
}
private boolean isHidden() {
return Settings.Secure.getInt(mContext.getContentResolver(),
HIDE_PRIVATESPACE_ENTRY_POINT, 0) == 1;
}
}

View File

@@ -17,30 +17,59 @@
package com.android.settings.privatespace;
import static com.android.settings.core.BasePreferenceController.AVAILABLE;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.spy;
import android.content.ContentResolver;
import android.content.Context;
import android.os.Flags;
import android.platform.test.annotations.RequiresFlagsEnabled;
import android.platform.test.flag.junit.CheckFlagsRule;
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
import android.provider.Settings;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@RunWith(AndroidJUnit4.class)
@RequiresFlagsEnabled(Flags.FLAG_ALLOW_PRIVATE_PROFILE)
public class HidePrivateSpaceControllerTest {
@Mock private Context mContext;
@Rule
public final CheckFlagsRule mCheckFlagsRule =
DeviceFlagsValueProvider.createCheckFlagsRule();
private static final String KEY = "private_space_hidden";
private static final String DETAIL_PAGE_KEY = "private_space_hidden_details";
private Context mContext;
private HidePrivateSpaceSummaryController mHidePrivateSpaceSummaryController;
private HidePrivateSpaceController mHidePrivateSpaceController;
private ContentResolver mContentResolver;
private int mOriginalHiddenValue;
/** Required setup before a test. */
@Before
public void setUp() {
mContext = ApplicationProvider.getApplicationContext();
final String preferenceKey = "private_space_hidden";
mContext = spy(ApplicationProvider.getApplicationContext());
mContentResolver = mContext.getContentResolver();
mHidePrivateSpaceSummaryController = new HidePrivateSpaceSummaryController(mContext, KEY);
mHidePrivateSpaceController =
new HidePrivateSpaceController(mContext, DETAIL_PAGE_KEY);
mOriginalHiddenValue = Settings.Secure.getInt(mContentResolver,
Settings.Secure.HIDE_PRIVATESPACE_ENTRY_POINT, 0);
}
mHidePrivateSpaceController = new HidePrivateSpaceController(mContext, preferenceKey);
@After
public void tearDown() {
Settings.Secure.putInt(mContentResolver, Settings.Secure.HIDE_PRIVATESPACE_ENTRY_POINT,
mOriginalHiddenValue);
}
/** Tests that the controller is always available. */
@@ -48,4 +77,33 @@ public class HidePrivateSpaceControllerTest {
public void getAvailabilityStatus_returnsAvailable() {
assertThat(mHidePrivateSpaceController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
}
/** Tests that hide preference summary displays On when hide toggle is enabled.*/
@Test
public void setChecked_enable_shouldDisplayOn() {
Settings.Secure.putInt(mContentResolver, Settings.Secure.HIDE_PRIVATESPACE_ENTRY_POINT,
0);
assertThat(mHidePrivateSpaceController.isChecked()).isFalse();
mHidePrivateSpaceController.setChecked(true);
assertThat(mHidePrivateSpaceSummaryController.getSummary().toString())
.isEqualTo("On");
assertThat(mHidePrivateSpaceController.isChecked()).isTrue();
}
/** Tests that hide preference summary displays Off when toggle is disabled.*/
@Test
public void setChecked_disable_shouldDisplayOff() {
Settings.Secure.putInt(mContentResolver, Settings.Secure.HIDE_PRIVATESPACE_ENTRY_POINT,
1);
assertThat(mHidePrivateSpaceController.isChecked()).isTrue();
mHidePrivateSpaceController.setChecked(false);
assertThat(mHidePrivateSpaceSummaryController.getSummary().toString())
.isEqualTo("Off");
assertThat(mHidePrivateSpaceController.isChecked()).isFalse();
}
}

View File

@@ -0,0 +1,99 @@
/*
* 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;
import static com.android.settings.core.BasePreferenceController.AVAILABLE;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.spy;
import android.content.ContentResolver;
import android.content.Context;
import android.os.Flags;
import android.platform.test.annotations.RequiresFlagsEnabled;
import android.platform.test.flag.junit.CheckFlagsRule;
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
import android.provider.Settings;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(AndroidJUnit4.class)
@RequiresFlagsEnabled(Flags.FLAG_ALLOW_PRIVATE_PROFILE)
public class HidePrivateSpaceSummaryControllerTest {
@Rule
public final CheckFlagsRule mCheckFlagsRule =
DeviceFlagsValueProvider.createCheckFlagsRule();
private Context mContext;
private HidePrivateSpaceSummaryController mHidePrivateSpaceSummaryController;
private ContentResolver mContentResolver;
private int mOriginalHiddenValue;
/** Required setup before a test. */
@Before
public void setUp() {
mContext = spy(ApplicationProvider.getApplicationContext());
mContentResolver = mContext.getContentResolver();
final String preferenceKey = "private_space_hidden";
mHidePrivateSpaceSummaryController =
new HidePrivateSpaceSummaryController(mContext, preferenceKey);
mOriginalHiddenValue = Settings.Secure.getInt(mContentResolver,
Settings.Secure.HIDE_PRIVATESPACE_ENTRY_POINT, 0);
}
@After
public void tearDown() {
Settings.Secure.putInt(mContentResolver, Settings.Secure.HIDE_PRIVATESPACE_ENTRY_POINT,
mOriginalHiddenValue);
}
/** Tests that the controller is always available. */
@Test
public void getAvailabilityStatus_returnsAvailable() {
assertThat(mHidePrivateSpaceSummaryController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
}
/** Tests that the preference summary displays On when hide is enabled.*/
@Test
public void setEnabled_shouldDisplayOn() {
Settings.Secure.putInt(mContentResolver, Settings.Secure.HIDE_PRIVATESPACE_ENTRY_POINT, 1);
assertThat(Settings.Secure.getInt(mContentResolver,
Settings.Secure.HIDE_PRIVATESPACE_ENTRY_POINT, -1)).isEqualTo(1);
assertThat(mHidePrivateSpaceSummaryController.getSummary().toString())
.isEqualTo("On");
}
/** Tests that the preference summary displays Off when hide is disabled.*/
@Test
public void setDisabled_shouldDisplayOff() {
Settings.Secure.putInt(mContentResolver, Settings.Secure.HIDE_PRIVATESPACE_ENTRY_POINT, 0);
assertThat(Settings.Secure.getInt(mContentResolver,
Settings.Secure.HIDE_PRIVATESPACE_ENTRY_POINT, -1)).isEqualTo(0);
assertThat(mHidePrivateSpaceSummaryController.getSummary().toString())
.isEqualTo("Off");
}
}