From c80dfbccb65e05a2708de28b43bbfe23aa099b92 Mon Sep 17 00:00:00 2001 From: Wa Gao Date: Sat, 7 Oct 2023 00:15:17 +0000 Subject: [PATCH] Add the new content protection preference option and subpage in Settings -> Security & privacy -> More security & privacy settings. Bug: 302189945 Test: robotests m -j256 Settings atest SettingsRoboTests:ContentProtectionPreferenceControllerTest atest SettingsRoboTests:ContentProtectionPreferenceFragmentTest Change-Id: I620d73f8674c1340f9b11cd910620f1d5afb0ec1 --- ...ent_protection_preference_illustration.xml | 95 ++++++++++++++++++ ...ent_protection_preference_illustration.xml | 96 +++++++++++++++++++ ...content_protection_preference_fragment.xml | 47 +++++++++ res/xml/more_security_privacy_settings.xml | 11 ++- ...ContentProtectionPreferenceController.java | 37 +++++++ .../ContentProtectionPreferenceFragment.java | 64 +++++++++++++ ...entProtectionPreferenceControllerTest.java | 70 ++++++++++++++ ...ntentProtectionPreferenceFragmentTest.java | 92 ++++++++++++++++++ 8 files changed, 511 insertions(+), 1 deletion(-) create mode 100644 res/drawable-night/content_protection_preference_illustration.xml create mode 100644 res/drawable/content_protection_preference_illustration.xml create mode 100644 res/layout/content_protection_preference_fragment.xml create mode 100644 src/com/android/settings/security/ContentProtectionPreferenceController.java create mode 100644 src/com/android/settings/security/ContentProtectionPreferenceFragment.java create mode 100644 tests/robotests/src/com/android/settings/security/ContentProtectionPreferenceControllerTest.java create mode 100644 tests/robotests/src/com/android/settings/security/ContentProtectionPreferenceFragmentTest.java diff --git a/res/drawable-night/content_protection_preference_illustration.xml b/res/drawable-night/content_protection_preference_illustration.xml new file mode 100644 index 00000000000..ebc74231e8c --- /dev/null +++ b/res/drawable-night/content_protection_preference_illustration.xml @@ -0,0 +1,95 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/res/drawable/content_protection_preference_illustration.xml b/res/drawable/content_protection_preference_illustration.xml new file mode 100644 index 00000000000..1083c1f9e5a --- /dev/null +++ b/res/drawable/content_protection_preference_illustration.xml @@ -0,0 +1,96 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/res/layout/content_protection_preference_fragment.xml b/res/layout/content_protection_preference_fragment.xml new file mode 100644 index 00000000000..a412d8618a4 --- /dev/null +++ b/res/layout/content_protection_preference_fragment.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + diff --git a/res/xml/more_security_privacy_settings.xml b/res/xml/more_security_privacy_settings.xml index 8358c734c59..822b03dde5b 100644 --- a/res/xml/more_security_privacy_settings.xml +++ b/res/xml/more_security_privacy_settings.xml @@ -119,6 +119,15 @@ android:key="security_category" android:title="@string/security_header" /> + + \ No newline at end of file + diff --git a/src/com/android/settings/security/ContentProtectionPreferenceController.java b/src/com/android/settings/security/ContentProtectionPreferenceController.java new file mode 100644 index 00000000000..01298003f6b --- /dev/null +++ b/src/com/android/settings/security/ContentProtectionPreferenceController.java @@ -0,0 +1,37 @@ +/* + * 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.security; + +import static android.view.contentprotection.flags.Flags.settingUiEnabled; + +import android.content.Context; + +import androidx.annotation.NonNull; + +import com.android.settings.core.BasePreferenceController; + +public class ContentProtectionPreferenceController extends BasePreferenceController { + + public ContentProtectionPreferenceController(@NonNull Context context, @NonNull String key) { + super(context, key); + } + + @Override + public int getAvailabilityStatus() { + // TODO(b/306565942): Add a resource value check. + return settingUiEnabled() ? AVAILABLE : UNSUPPORTED_ON_DEVICE; + } +} diff --git a/src/com/android/settings/security/ContentProtectionPreferenceFragment.java b/src/com/android/settings/security/ContentProtectionPreferenceFragment.java new file mode 100644 index 00000000000..a58f6e5efb0 --- /dev/null +++ b/src/com/android/settings/security/ContentProtectionPreferenceFragment.java @@ -0,0 +1,64 @@ +/* + * 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.security; + +import android.content.Context; +import android.app.settings.SettingsEnums; + +import com.android.settings.dashboard.DashboardFragment; +import com.android.settings.R; +import com.android.settings.SettingsPreferenceFragment; +import com.android.settings.search.BaseSearchIndexProvider; +import com.android.settingslib.search.SearchIndexable; + +import android.os.Bundle; + +@SearchIndexable +public class ContentProtectionPreferenceFragment extends DashboardFragment { + private static final String TAG = "ContentProtectionPreferenceFragment"; + + // Required by @SearchIndexable to make the fragment and preferences to be indexed. + // Do not rename. + public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new BaseSearchIndexProvider(R.layout.content_protection_preference_fragment); + + @Override + public void onAttach(Context context) { + super.onAttach(context); + } + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + // TODO(b/304681048): Update the toggles' behavior according to user's profile + } + + @Override + public int getMetricsCategory() { + return SettingsEnums.CONTENT_PROTECTION_PREFERENCE; + } + + @Override + protected int getPreferenceScreenResId() { + return R.layout.content_protection_preference_fragment; + } + + @Override + protected String getLogTag() { + return TAG; + } +} diff --git a/tests/robotests/src/com/android/settings/security/ContentProtectionPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/security/ContentProtectionPreferenceControllerTest.java new file mode 100644 index 00000000000..5cc931e557e --- /dev/null +++ b/tests/robotests/src/com/android/settings/security/ContentProtectionPreferenceControllerTest.java @@ -0,0 +1,70 @@ +/* + * 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.security; + +import static android.view.contentprotection.flags.Flags.FLAG_SETTING_UI_ENABLED; +import static com.google.common.truth.Truth.assertThat; + +import android.content.ContentResolver; +import android.content.Context; +import android.platform.test.flag.junit.SetFlagsRule; +import android.provider.Settings; + +import androidx.preference.Preference; + +import com.android.settings.R; + +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.MockitoAnnotations; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; + +@RunWith(RobolectricTestRunner.class) +public class ContentProtectionPreferenceControllerTest { + + @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); + + private Context mContext; + private ContentProtectionPreferenceController mController; + private Preference mPreference; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mContext = RuntimeEnvironment.application; + mController = new ContentProtectionPreferenceController(mContext, "key"); + mPreference = new Preference(mContext); + mPreference.setKey(mController.getPreferenceKey()); + } + + @Test + public void isAvailable_flagSettingUiDisabled_isFalse() { + mSetFlagsRule.disableFlags(FLAG_SETTING_UI_ENABLED); + assertThat(mController.isAvailable()).isFalse(); + } + + @Test + public void isAvailable_flagSettingUiEnabled_isTrue() { + mSetFlagsRule.enableFlags(FLAG_SETTING_UI_ENABLED); + assertThat(mController.isAvailable()).isTrue(); + } +} diff --git a/tests/robotests/src/com/android/settings/security/ContentProtectionPreferenceFragmentTest.java b/tests/robotests/src/com/android/settings/security/ContentProtectionPreferenceFragmentTest.java new file mode 100644 index 00000000000..431dd0ca533 --- /dev/null +++ b/tests/robotests/src/com/android/settings/security/ContentProtectionPreferenceFragmentTest.java @@ -0,0 +1,92 @@ +/* + * 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.security; + +import static android.app.settings.SettingsEnums.CONTENT_PROTECTION_PREFERENCE; +import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.spy; + +import android.content.Context; +import android.provider.SearchIndexableResource; + +import com.android.settings.R; +import com.android.settings.testutils.XmlTestUtils; +import com.android.settings.testutils.shadow.ShadowDashboardFragment; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; + +import java.util.List; + +@RunWith(RobolectricTestRunner.class) +@Config(shadows = ShadowDashboardFragment.class) +public class ContentProtectionPreferenceFragmentTest { + + @Mock + private ContentProtectionPreferenceFragment mMockFragment; + private Context mContext; + + @Before + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + mContext = spy(RuntimeEnvironment.application); + mMockFragment = spy(new ContentProtectionPreferenceFragment()); + + doReturn(mContext).when(mMockFragment).getContext(); + } + + @Test + public void getMetricsCategory() { + assertThat(mMockFragment.getMetricsCategory()).isEqualTo(CONTENT_PROTECTION_PREFERENCE); + } + + @Test + public void getPreferenceScreenResId(){ + assertThat(mMockFragment.getPreferenceScreenResId()) + .isEqualTo(R.layout.content_protection_preference_fragment); + } + + @Test + public void getNonIndexableKeys_existInXmlLayout() { + final List nonIndexableKeys = + ContentProtectionPreferenceFragment.SEARCH_INDEX_DATA_PROVIDER + .getNonIndexableKeys(mContext); + final List allKeys = + XmlTestUtils.getKeysFromPreferenceXml(mContext, + R.layout.content_protection_preference_fragment); + + assertThat(allKeys).containsAtLeastElementsIn(nonIndexableKeys); + } + + @Test + public void searchIndexProvider_shouldIndexResource() { + final List indexRes = + ContentProtectionPreferenceFragment.SEARCH_INDEX_DATA_PROVIDER + .getXmlResourcesToIndex(mContext, /* enabled = */ true); + + assertThat(indexRes).isNotNull(); + assertThat(indexRes).isNotEmpty(); + assertThat(indexRes.get(0).xmlResId).isEqualTo(mMockFragment.getPreferenceScreenResId()); + } +}