Implement "More privacy settings"

Safety Center is enabled, the existing "Privacy" screen will be
different in a few ways:

1. Its title will become "More privacy settings"
2. A few preferences will be hidden
3. A few preferences will be reworded
4. The ordering of a few preferences will change
5. The PRIVACY_SETTINGS intent will now point to Safety Center;
   PRIVACY_ADVANCED_SETTINGS will point to "More privacy settings".

Test: manual
Bug: 222127397
Change-Id: I74faf770babb34f775b2ef572248e550ea683ab3
This commit is contained in:
Jay Thomas Sullivan
2022-05-05 20:56:43 +00:00
parent a571dd9973
commit ecc0a45a98
5 changed files with 181 additions and 40 deletions

View File

@@ -1297,7 +1297,10 @@
<string name="security_advanced_settings_no_work_profile_settings_summary">Encryption, credentials, and more</string> <string name="security_advanced_settings_no_work_profile_settings_summary">Encryption, credentials, and more</string>
<!-- Search keywords for the "More security settings" section in security settings. [CHAR_LIMIT=NONE] --> <!-- Search keywords for the "More security settings" section in security settings. [CHAR_LIMIT=NONE] -->
<string name="security_advanced_settings_keywords">security, more security settings, more settings, advanced security settings</string> <string name="security_advanced_settings_keywords">security, more security settings, more settings, advanced security settings</string>
<!-- Title for the section that has additional privacy settings. [CHAR LIMIT=60] -->
<string name="privacy_advanced_settings">More privacy settings</string>
<!-- Title for the section that has additional privacy settings. [CHAR LIMIT=60] -->
<string name="privacy_advanced_settings_summary">Autofill, activity controls, and more</string>
<!-- Text shown when "Add fingerprint" button is disabled --> <!-- Text shown when "Add fingerprint" button is disabled -->
<string name="fingerprint_add_max">You can add up to <xliff:g id="count" example="5">%d</xliff:g> fingerprints</string> <string name="fingerprint_add_max">You can add up to <xliff:g id="count" example="5">%d</xliff:g> fingerprints</string>
@@ -8973,6 +8976,9 @@
<!-- Configure Notifications: Work profile section header [CHAR LIMIT=30] --> <!-- Configure Notifications: Work profile section header [CHAR LIMIT=30] -->
<string name="profile_section_header">Work notifications</string> <string name="profile_section_header">Work notifications</string>
<!-- Configure Notifications: Work profile section header [CHAR LIMIT=30] -->
<string name="profile_section_header_for_advanced_privacy">Work profile</string>
<!-- Configure Notifications: section header for prioritizer settings [CHAR LIMIT=80] --> <!-- Configure Notifications: section header for prioritizer settings [CHAR LIMIT=80] -->
<string name="smart_notifications_title">Adaptive notifications</string> <string name="smart_notifications_title">Adaptive notifications</string>

View File

@@ -0,0 +1,96 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2022 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:key="privacy_dashboard_page"
android:title="@string/privacy_advanced_settings">
<!-- Work Policy info -->
<Preference
android:key="work_policy_info"
android:title="@string/work_policy_privacy_settings"
android:summary="@string/work_policy_privacy_settings_summary"
settings:controller="com.android.settings.privacy.WorkPolicyInfoPreferenceController"/>
<!-- Connected work and personal apps -->
<Preference
android:key="interact_across_profiles_privacy"
android:title="@string/interact_across_profiles_title"
android:fragment="com.android.settings.applications.specialaccess.interactacrossprofiles.InteractAcrossProfilesSettings"
settings:searchable="false"
settings:controller="com.android.settings.applications.specialaccess.interactacrossprofiles.InteractAcrossProfilesController" />
<!-- Accessibility usage -->
<Preference
android:key="privacy_accessibility_usage"
android:title="@string/accessibility_usage_title"
settings:controller="com.android.settings.privacy.AccessibilityUsagePreferenceController">
<intent android:action="android.intent.action.REVIEW_ACCESSIBILITY_SERVICES"/>
</Preference>
<!-- On lock screen notifications -->
<com.android.settings.RestrictedListPreference
android:key="privacy_lock_screen_notifications"
android:title="@string/lock_screen_notifs_title"
android:summary="@string/summary_placeholder"
settings:searchable="false"/>
<!-- Privacy Service -->
<PreferenceCategory
android:key="privacy_services"
android:layout="@layout/preference_category_no_label"/>
<PreferenceCategory
android:key="dashboard_tile_placeholder"/>
<!-- Work profile settings are at the bottom with high order value to avoid users thinking that
any of the above settings (including dynamic) are specific to the work profile. -->
<PreferenceCategory
android:key="privacy_work_profile_notifications_category"
android:title="@string/profile_section_header_for_advanced_privacy"
android:order="998">
<com.android.settings.RestrictedListPreference
android:key="privacy_lock_screen_work_profile_notifications"
android:title="@string/locked_work_profile_notification_title"
android:summary="@string/summary_placeholder"
android:order="999"
settings:searchable="false"/>
</PreferenceCategory>
<!-- Content Capture -->
<!-- NOTE: content capture has a different preference, depending whether or not the
ContentCaptureService implementations defines a custom settings activitiy on its manifest.
Hence, we show both here, but the controller itself will decide if it's available or not.
-->
<SwitchPreference
android:key="content_capture"
android:title="@string/content_capture"
android:summary="@string/content_capture_summary"
settings:controller="com.android.settings.privacy.EnableContentCapturePreferenceController"/>
<com.android.settingslib.PrimarySwitchPreference
android:key="content_capture_custom_settings"
android:title="@string/content_capture"
android:summary="@string/content_capture_summary"
settings:controller="com.android.settings.privacy.EnableContentCaptureWithServiceSettingsPreferenceController"/>
</PreferenceScreen>

View File

@@ -16,6 +16,8 @@
package com.android.settings; package com.android.settings;
import static android.provider.Settings.ACTION_PRIVACY_SETTINGS;
import android.content.ActivityNotFoundException; import android.content.ActivityNotFoundException;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
@@ -214,7 +216,8 @@ public class Settings extends SettingsActivity {
/** Redirects to SafetyCenter if enabled. */ /** Redirects to SafetyCenter if enabled. */
@VisibleForTesting @VisibleForTesting
public void handleSafetyCenterRedirection() { public void handleSafetyCenterRedirection() {
if (SafetyCenterManagerWrapper.get().isEnabled(this)) { if (ACTION_PRIVACY_SETTINGS.equals(getIntent().getAction())
&& SafetyCenterManagerWrapper.get().isEnabled(this)) {
try { try {
startActivity(new Intent(Intent.ACTION_SAFETY_CENTER)); startActivity(new Intent(Intent.ACTION_SAFETY_CENTER));
finish(); finish();

View File

@@ -25,6 +25,7 @@ import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_PROF
import android.app.settings.SettingsEnums; import android.app.settings.SettingsEnums;
import android.content.Context; import android.content.Context;
import android.os.Bundle; import android.os.Bundle;
import android.provider.SearchIndexableResource;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.dashboard.DashboardFragment; import com.android.settings.dashboard.DashboardFragment;
@@ -36,6 +37,7 @@ import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.search.SearchIndexable; import com.android.settingslib.search.SearchIndexable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; import java.util.List;
@SearchIndexable @SearchIndexable
@@ -72,12 +74,6 @@ public class PrivacyDashboardFragment extends DashboardFragment {
replaceEnterpriseStringSummary("work_policy_info", replaceEnterpriseStringSummary("work_policy_info",
WORK_PROFILE_PRIVACY_POLICY_INFO_SUMMARY, WORK_PROFILE_PRIVACY_POLICY_INFO_SUMMARY,
R.string.work_policy_privacy_settings_summary); R.string.work_policy_privacy_settings_summary);
}
@Override
protected int getPreferenceScreenResId() {
return R.xml.privacy_dashboard_settings;
} }
@Override @Override
@@ -90,6 +86,19 @@ public class PrivacyDashboardFragment extends DashboardFragment {
return buildPreferenceControllers(context, getSettingsLifecycle()); return buildPreferenceControllers(context, getSettingsLifecycle());
} }
@Override
protected int getPreferenceScreenResId() {
return getPreferenceScreenResId(getContext());
}
private static int getPreferenceScreenResId(Context context) {
if (SafetyCenterManagerWrapper.get().isEnabled(context)) {
return R.xml.privacy_advanced_settings;
} else {
return R.xml.privacy_dashboard_settings;
}
}
private static List<AbstractPreferenceController> buildPreferenceControllers( private static List<AbstractPreferenceController> buildPreferenceControllers(
Context context, Lifecycle lifecycle) { Context context, Lifecycle lifecycle) {
final List<AbstractPreferenceController> controllers = new ArrayList<>(); final List<AbstractPreferenceController> controllers = new ArrayList<>();
@@ -108,17 +117,19 @@ public class PrivacyDashboardFragment extends DashboardFragment {
} }
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider(R.xml.privacy_dashboard_settings) { new BaseSearchIndexProvider() {
@Override
public List<SearchIndexableResource> getXmlResourcesToIndex(
Context context, boolean enabled) {
final SearchIndexableResource sir = new SearchIndexableResource(context);
sir.xmlResId = getPreferenceScreenResId(context);
return Arrays.asList(sir);
}
@Override @Override
public List<AbstractPreferenceController> createPreferenceControllers( public List<AbstractPreferenceController> createPreferenceControllers(
Context context) { Context context) {
return buildPreferenceControllers(context, null); return buildPreferenceControllers(context, null);
} }
@Override
protected boolean isPageSearchEnabled(Context context) {
return !SafetyCenterManagerWrapper.get().isEnabled(context);
}
}; };
} }

View File

@@ -44,54 +44,79 @@ import org.mockito.MockitoAnnotations;
@RunWith(AndroidJUnit4.class) @RunWith(AndroidJUnit4.class)
public class PrivacyDashboardActivityTest { public class PrivacyDashboardActivityTest {
private static final String DEFAULT_FRAGMENT_CLASSNAME = "DefaultFragmentClassname"; private static final String DEFAULT_FRAGMENT_CLASSNAME = "DefaultFragmentClassname";
@Mock @Mock
private SafetyCenterManagerWrapper mSafetyCenterManagerWrapper; private SafetyCenterManagerWrapper mSafetyCenterManagerWrapper;
private Settings.PrivacyDashboardActivity mActivity; private Settings.PrivacyDashboardActivity mActivity;
private static final String ACTION_PRIVACY_ADVANCED_SETTINGS =
"android.settings.PRIVACY_ADVANCED_SETTINGS";
@Before @Before
public void setUp() throws Exception { public void setUp() {
MockitoAnnotations.initMocks(this); MockitoAnnotations.initMocks(this);
SafetyCenterManagerWrapper.sInstance = mSafetyCenterManagerWrapper;
}
@Test
public void onCreate_whenSafetyCenterEnabled_redirectsToSafetyCenter() throws Exception {
startActivityUsingIntent(android.provider.Settings.ACTION_PRIVACY_SETTINGS);
when(mSafetyCenterManagerWrapper.isEnabled(any(Context.class))).thenReturn(true);
final ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
mActivity.handleSafetyCenterRedirection();
verify(mActivity).startActivity(intentCaptor.capture());
assertThat(intentCaptor.getValue().getAction()).isEqualTo(Intent.ACTION_SAFETY_CENTER);
}
@Test
public void onCreateWithAdvancedIntent_whenSafetyCenterEnabled_doesntRedirectToSafetyCenter()
throws Exception {
startActivityUsingIntent(ACTION_PRIVACY_ADVANCED_SETTINGS);
when(mSafetyCenterManagerWrapper.isEnabled(any(Context.class))).thenReturn(true);
final ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
mActivity.handleSafetyCenterRedirection();
verify(mActivity, times(0)).startActivity(any());
}
@Test
public void onCreate_whenSafetyCenterDisabled_doesntRedirectToSafetyCenter() throws Exception {
startActivityUsingIntent(android.provider.Settings.ACTION_PRIVACY_SETTINGS);
when(mSafetyCenterManagerWrapper.isEnabled(any(Context.class))).thenReturn(false);
mActivity.handleSafetyCenterRedirection();
verify(mActivity, times(0)).startActivity(any());
}
@Test
public void onCreateWithAdvancedIntent_whenSafetyCenterDisabled_doesntRedirectToSafetyCenter()
throws Exception {
startActivityUsingIntent(ACTION_PRIVACY_ADVANCED_SETTINGS);
when(mSafetyCenterManagerWrapper.isEnabled(any(Context.class))).thenReturn(true);
final ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
mActivity.handleSafetyCenterRedirection();
verify(mActivity, times(0)).startActivity(any());
}
private void startActivityUsingIntent(String intentAction) throws Exception {
MockitoAnnotations.initMocks(this);
SafetyCenterManagerWrapper.sInstance = mSafetyCenterManagerWrapper; SafetyCenterManagerWrapper.sInstance = mSafetyCenterManagerWrapper;
final Intent intent = new Intent(); final Intent intent = new Intent();
intent.setAction(android.provider.Settings.ACTION_PRIVACY_SETTINGS); intent.setAction(intentAction);
intent.setClass(InstrumentationRegistry.getInstrumentation().getTargetContext(), intent.setClass(InstrumentationRegistry.getInstrumentation().getTargetContext(),
Settings.PrivacyDashboardActivity.class); Settings.PrivacyDashboardActivity.class);
intent.putExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT, DEFAULT_FRAGMENT_CLASSNAME); intent.putExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT, DEFAULT_FRAGMENT_CLASSNAME);
InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> { InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
try { try {
mActivity = Settings.PrivacyDashboardActivity activity =
spy((Settings.PrivacyDashboardActivity) InstrumentationRegistry (Settings.PrivacyDashboardActivity) InstrumentationRegistry
.getInstrumentation().newActivity( .getInstrumentation().newActivity(
getClass().getClassLoader(), getClass().getClassLoader(),
Settings.PrivacyDashboardActivity.class.getName(), Settings.PrivacyDashboardActivity.class.getName(),
intent)); intent);
activity.setIntent(intent);
mActivity = spy(activity);
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException(e); // nothing to do throw new RuntimeException(e); // nothing to do
} }
}); });
doNothing().when(mActivity).startActivity(any(Intent.class)); doNothing().when(mActivity).startActivity(any(Intent.class));
} }
@Test
public void onCreate_whenSafetyCenterEnabled_redirectsToSafetyCenter() {
when(mSafetyCenterManagerWrapper.isEnabled(any(Context.class))).thenReturn(true);
final ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
mActivity.handleSafetyCenterRedirection();
verify(mActivity).startActivity(intentCaptor.capture());
assertThat(intentCaptor.getValue().getAction()).isEqualTo(Intent.ACTION_SAFETY_CENTER);
}
@Test
public void onCreate_whenSafetyCenterDisabled_doesntRedirectToSafetyCenter() {
when(mSafetyCenterManagerWrapper.isEnabled(any(Context.class))).thenReturn(false);
mActivity.handleSafetyCenterRedirection();
verify(mActivity, times(0)).startActivity(any());
}
} }