diff --git a/res/layout/private_space_education_screen.xml b/res/layout/private_space_education_screen.xml index 8fb486e1549..6b651030265 100644 --- a/res/layout/private_space_education_screen.xml +++ b/res/layout/private_space_education_screen.xml @@ -93,10 +93,19 @@ android:layout_height="18dp" android:src="@drawable/ic_info_outline_24dp" /> + diff --git a/res/values/strings.xml b/res/values/strings.xml index f26939eeb46..42d425f3adf 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -1311,6 +1311,9 @@ Install apps\nYour private space has its own Play Store so you can install apps easily. Apps in your private space won\'t appear in permission manager, privacy dashboard, and other settings when your private space is locked.\n\nYour private space can\'t be moved to a new device. You\'ll need to set up another private space if you want to use it on another device.\n\nAnyone that connects your device to a computer or installs harmful apps on your device may be able to access your private space. + + Learn more about private space + https://support.google.com/android?p=private_space Setting up private space\u2026 diff --git a/res/xml/private_space_settings.xml b/res/xml/private_space_settings.xml index 93c016bd621..86537cc3505 100644 --- a/res/xml/private_space_settings.xml +++ b/res/xml/private_space_settings.xml @@ -81,10 +81,12 @@ - + settings:searchable="false" + settings:controller="com.android.settings.privatespace.PrivateSpaceFooterPreferenceController"/> + diff --git a/src/com/android/settings/privatespace/PrivateSpaceEducation.java b/src/com/android/settings/privatespace/PrivateSpaceEducation.java index cf22895a70b..a21aac3c82d 100644 --- a/src/com/android/settings/privatespace/PrivateSpaceEducation.java +++ b/src/com/android/settings/privatespace/PrivateSpaceEducation.java @@ -19,10 +19,12 @@ package com.android.settings.privatespace; import android.app.Activity; import android.app.settings.SettingsEnums; import android.os.Bundle; +import android.text.util.Linkify; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.TextView; import androidx.annotation.Nullable; import androidx.navigation.fragment.NavHostFragment; @@ -34,6 +36,8 @@ import com.google.android.setupcompat.template.FooterBarMixin; import com.google.android.setupcompat.template.FooterButton; import com.google.android.setupdesign.GlifLayout; +import java.util.regex.Pattern; + /** Fragment educating about the usage of Private Space. */ public class PrivateSpaceEducation extends InstrumentedFragment { private static final String TAG = "PrivateSpaceEducation"; @@ -66,6 +70,13 @@ public class PrivateSpaceEducation extends InstrumentedFragment { .setTheme(com.google.android.setupdesign.R.style.SudGlifButton_Secondary) .build()); + TextView infoTextView = rootView.findViewById(R.id.learn_more); + Pattern pattern = Pattern.compile(infoTextView.getText().toString()); + Linkify.addLinks( + infoTextView, + pattern, + getContext().getString(R.string.private_space_learn_more_url)); + return rootView; } diff --git a/src/com/android/settings/privatespace/PrivateSpaceFooterPreferenceController.java b/src/com/android/settings/privatespace/PrivateSpaceFooterPreferenceController.java new file mode 100644 index 00000000000..71139bab62b --- /dev/null +++ b/src/com/android/settings/privatespace/PrivateSpaceFooterPreferenceController.java @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2024 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.content.Context; +import android.text.TextUtils; + +import androidx.annotation.NonNull; +import androidx.annotation.VisibleForTesting; +import androidx.preference.PreferenceScreen; + +import com.android.settings.R; +import com.android.settings.core.BasePreferenceController; +import com.android.settingslib.HelpUtils; +import com.android.settingslib.widget.FooterPreference; + +/** Preference controller for private space settings footer. */ +public class PrivateSpaceFooterPreferenceController extends BasePreferenceController { + public PrivateSpaceFooterPreferenceController( + @NonNull Context context, @NonNull String preferenceKey) { + super(context, preferenceKey); + } + + @Override + public void displayPreference(@NonNull PreferenceScreen screen) { + super.displayPreference(screen); + FooterPreference preference = screen.findPreference(getPreferenceKey()); + setupFooter(preference); + } + + @Override + public int getAvailabilityStatus() { + return android.multiuser.Flags.enablePrivateSpaceFeatures() + ? AVAILABLE + : UNSUPPORTED_ON_DEVICE; + } + + @VisibleForTesting + void setupFooter(FooterPreference preference) { + final String helpUri = mContext.getString(R.string.private_space_learn_more_url); + if (!TextUtils.isEmpty(helpUri) && preference != null) { + preference.setLearnMoreAction( + v -> { + mContext.startActivity( + HelpUtils.getHelpIntent( + mContext, helpUri, /* backupContext= */ "")); + }); + preference.setLearnMoreText(mContext.getString(R.string.private_space_learn_more_text)); + } + } +} diff --git a/tests/unit/src/com/android/settings/privatespace/PrivateSpaceFooterPreferenceControllerTest.java b/tests/unit/src/com/android/settings/privatespace/PrivateSpaceFooterPreferenceControllerTest.java new file mode 100644 index 00000000000..30215da1fad --- /dev/null +++ b/tests/unit/src/com/android/settings/privatespace/PrivateSpaceFooterPreferenceControllerTest.java @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2024 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.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.verify; + +import android.content.Context; +import android.platform.test.flag.junit.SetFlagsRule; + +import androidx.test.core.app.ApplicationProvider; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import com.android.settingslib.widget.FooterPreference; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +@RunWith(AndroidJUnit4.class) +public class PrivateSpaceFooterPreferenceControllerTest { + @Mock private Context mContext; + @Mock FooterPreference mFooterPreference; + @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); + private PrivateSpaceFooterPreferenceController mController; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mContext = ApplicationProvider.getApplicationContext(); + final String preferenceKey = "private_space_footer"; + + mController = new PrivateSpaceFooterPreferenceController(mContext, preferenceKey); + } + + @Test + public void getAvailabilityStatus_whenFlagsEnabled_returnsAvailable() { + mSetFlagsRule.enableFlags(android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES); + + assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE); + } + + @Test + public void getAvailabilityStatus_whenFlagsDisabled_returnsUnsupportedOnDevice() { + mSetFlagsRule.disableFlags(android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES); + + assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE); + } + + @Test + public void setUpFooter_setsLearnMoreTextAndAction() { + mSetFlagsRule.enableFlags(android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES); + + mController.setupFooter(mFooterPreference); + verify(mFooterPreference).setLearnMoreAction(any()); + verify(mFooterPreference).setLearnMoreText("Learn more about private space"); + } +}