Merge changes Icda934a2,Ic07b18b3
* changes:
[Large Screen] Launch MobileNetworkSettings by SubSettingsLauncher
[Large Screen] Launch MobileNetworkActivity as a fragment for split mode
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index c49ee73..79821d3 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -685,12 +685,12 @@
<activity android:name=".network.telephony.ToggleSubscriptionDialogActivity"
android:exported="false"
android:permission="android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS"
- android:theme="@*android:style/Theme.DeviceDefault.Dialog.Alert.DayNight" />
+ android:theme="@style/Theme.AlertDialog"/>
<activity android:name=".network.telephony.DeleteEuiccSubscriptionDialogActivity"
android:exported="false"
android:permission="android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS"
- android:theme="@*android:style/Theme.DeviceDefault.Dialog.Alert.DayNight" />
+ android:theme="@style/Theme.AlertDialog"/>
<activity
android:name="Settings$TetherSettingsActivity"
@@ -4272,14 +4272,14 @@
android:exported="false"
android:permission="android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS"
android:launchMode="singleInstance"
- android:theme="@*android:style/Theme.DeviceDefault.Dialog.Alert.DayNight" />
+ android:theme="@style/Theme.AlertDialog"/>
<activity
android:name=".sim.DsdsDialogActivity"
android:exported="false"
android:permission="android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS"
android:launchMode="singleInstance"
- android:theme="@*android:style/Theme.DeviceDefault.Dialog.Alert.DayNight" />
+ android:theme="@style/Theme.AlertDialog"/>
<service android:name=".sim.SimNotificationService"
android:permission="android.permission.BIND_JOB_SERVICE" />
diff --git a/res/drawable/ic_settings_safety_center.xml b/res/drawable/ic_settings_safety_center.xml
new file mode 100644
index 0000000..f43359f
--- /dev/null
+++ b/res/drawable/ic_settings_safety_center.xml
@@ -0,0 +1,29 @@
+<!--
+ ~ Copyright (C) 2021 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.
+ -->
+<!-- TODO(b/208624929): Update to an UX approved icon. -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:tint="?android:attr/colorControlNormal">
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M12,15m-2,0a2,2 0,1 1,4 0a2,2 0,1 1,-4 0"/>
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M18.5,1C16.01,1 14,3.01 14,5.5V8H6c-1.1,0 -2,0.9 -2,2v10c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2V10c0,-1.1 -0.9,-2 -2,-2h-2V5.5C16,4.12 17.12,3 18.5,3C19.88,3 21,4.12 21,5.5V6h2V5.5C23,3.01 20.99,1 18.5,1zM18,10v10H6V10H18z"/>
+</vector>
\ No newline at end of file
diff --git a/res/layout/sim_confirm_dialog_multiple_enabled_profiles_supported.xml b/res/layout/sim_confirm_dialog_multiple_enabled_profiles_supported.xml
new file mode 100644
index 0000000..4404482
--- /dev/null
+++ b/res/layout/sim_confirm_dialog_multiple_enabled_profiles_supported.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 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.
+-->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ style="@style/Theme.Material3.DayNight.Dialog.Alert">
+ <TextView
+ android:id="@+id/msg"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"/>
+ <ListView
+ android:id="@+id/carrier_list"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"/>
+
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:minWidth="56dp"
+ android:gravity="start|top"
+ android:orientation="horizontal"
+ android:paddingEnd="12dp"
+ android:paddingTop="16dp"
+ android:paddingBottom="4dp"
+ android:baselineAligned="true">
+ <ImageView
+ android:src="@drawable/ic_info_outline_24dp"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:tint="?android:attr/textColorTertiary"/>
+
+ <TextView
+ android:id="@+id/info_outline"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingTop="16dp"
+ android:paddingBottom="8dp"
+ android:text="@string/sim_action_switch_sub_dialog_info_outline_for_turning_off"
+ android:textColor="?android:attr/textColorSecondary" />
+ </LinearLayout>
+</LinearLayout>
\ No newline at end of file
diff --git a/res/values/menu_keys.xml b/res/values/menu_keys.xml
index e69664a..2841b69 100755
--- a/res/values/menu_keys.xml
+++ b/res/values/menu_keys.xml
@@ -26,6 +26,7 @@
<string name="menu_key_display" translatable="false">top_level_display</string>
<string name="menu_key_wallpaper" translatable="false">top_level_wallpaper</string>
<string name="menu_key_accessibility" translatable="false">top_level_accessibility</string>
+ <string name="menu_key_safety_center" translatable="false">top_level_safety_center</string>
<string name="menu_key_security" translatable="false">top_level_security</string>
<string name="menu_key_privacy" translatable="false">top_level_privacy</string>
<string name="menu_key_location" translatable="false">top_level_location</string>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 05ed9c7..ed867d2 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -722,6 +722,12 @@
<string name="security_status_title">Security status</string>
<!-- Summary for Security settings, explaining a few important settings under it [CHAR LIMIT=NONE] -->
<string name="security_dashboard_summary">Screen lock, Find My Device, app security</string>
+ <!-- TODO(b/208624929): Update to an UX approved title and char limit. -->
+ <!-- Main Settings screen setting title for the item that takes you to the safety center [CHAR LIMIT=60] -->
+ <string name="safety_center_title">Security & privacy</string>
+ <!-- TODO(b/208624929): Update to an UX approved summary and char limit. -->
+ <!-- Main Settings screen setting summary for the item that takes you to the safety center [CHAR LIMIT=60] -->
+ <string name="safety_center_summary">Permissions, screen lock, app security</string>
<!-- Face enrollment and settings --><skip />
<!-- Note: Update FaceEnrollParentalConsent.CONSENT_STRING_RESOURCES when any _consent_ strings are added or removed. -->
diff --git a/res/xml/top_level_settings.xml b/res/xml/top_level_settings.xml
index 042ce43..280c3f3 100644
--- a/res/xml/top_level_settings.xml
+++ b/res/xml/top_level_settings.xml
@@ -117,6 +117,15 @@
settings:controller="com.android.settings.accessibility.TopLevelAccessibilityPreferenceController"/>
<com.android.settings.widget.HomepagePreference
+ android:icon="@drawable/ic_settings_safety_center"
+ android:key="top_level_safety_center"
+ android:order="-55"
+ android:title="@string/safety_center_title"
+ android:summary="@string/safety_center_summary"
+ settings:highlightableMenuKey="@string/menu_key_safety_center"
+ settings:controller="com.android.settings.safetycenter.TopLevelSafetyCenterEntryPreferenceController"/>
+
+ <com.android.settings.widget.HomepagePreference
android:fragment="com.android.settings.security.SecuritySettings"
android:icon="@drawable/ic_settings_security_white"
android:key="top_level_security"
@@ -133,7 +142,8 @@
android:order="-40"
android:title="@string/privacy_dashboard_title"
android:summary="@string/privacy_dashboard_summary"
- settings:highlightableMenuKey="@string/menu_key_privacy"/>
+ settings:highlightableMenuKey="@string/menu_key_privacy"
+ settings:controller="com.android.settings.privacy.TopLevelPrivacyEntryPreferenceController"/>
<com.android.settings.widget.HomepagePreference
android:fragment="com.android.settings.location.LocationSettings"
diff --git a/src/com/android/settings/homepage/SettingsHomepageActivity.java b/src/com/android/settings/homepage/SettingsHomepageActivity.java
index 9076053..183a2fb 100644
--- a/src/com/android/settings/homepage/SettingsHomepageActivity.java
+++ b/src/com/android/settings/homepage/SettingsHomepageActivity.java
@@ -311,7 +311,7 @@
}
private void launchDeepLinkIntentToRight() {
- if (!ActivityEmbeddingUtils.isEmbeddingActivityEnabled(this)) {
+ if (!mIsEmbeddingActivityEnabled) {
return;
}
diff --git a/src/com/android/settings/homepage/TopLevelSettings.java b/src/com/android/settings/homepage/TopLevelSettings.java
index f2e5a35..f76a3de 100644
--- a/src/com/android/settings/homepage/TopLevelSettings.java
+++ b/src/com/android/settings/homepage/TopLevelSettings.java
@@ -19,12 +19,14 @@
import static com.android.settings.search.actionbar.SearchMenuController.NEED_SEARCH_ICON_IN_ACTION_BAR;
import static com.android.settingslib.search.SearchIndexable.MOBILE;
+import android.app.ActivityManager;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.text.TextUtils;
+import android.util.Log;
import androidx.fragment.app.Fragment;
import androidx.preference.Preference;
@@ -53,6 +55,7 @@
private static final String SAVED_HIGHLIGHT_MIXIN = "highlight_mixin";
private static final String PREF_KEY_SUPPORT = "top_level_support";
+ private boolean mIsEmbeddingActivityEnabled;
private TopLevelHighlightMixin mHighlightMixin;
private boolean mFirstStarted = true;
@@ -122,7 +125,9 @@
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
- if (!ActivityEmbeddingUtils.isEmbeddingActivityEnabled(getContext())) {
+ mIsEmbeddingActivityEnabled =
+ ActivityEmbeddingUtils.isEmbeddingActivityEnabled(getContext());
+ if (!mIsEmbeddingActivityEnabled) {
return;
}
@@ -138,15 +143,23 @@
public void onStart() {
if (mFirstStarted) {
mFirstStarted = false;
- } else if (!ActivityEmbeddingUtils.isTwoPaneResolution(getActivity())) {
+ } else if (mIsEmbeddingActivityEnabled && isOnlyOneActivityInTask()
+ && !ActivityEmbeddingUtils.isTwoPaneResolution(getActivity())) {
// Set default highlight menu key for 1-pane homepage since it will show the placeholder
// page once changing back to 2-pane.
+ Log.i(TAG, "Set default menu key");
setHighlightMenuKey(getString(SettingsHomepageActivity.DEFAULT_HIGHLIGHT_MENU_KEY),
/* scrollNeeded= */ false);
}
super.onStart();
}
+ private boolean isOnlyOneActivityInTask() {
+ final ActivityManager.RunningTaskInfo taskInfo = getSystemService(ActivityManager.class)
+ .getRunningTasks(1).get(0);
+ return taskInfo.numActivities == 1;
+ }
+
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
@@ -225,8 +238,7 @@
@Override
protected RecyclerView.Adapter onCreateAdapter(PreferenceScreen preferenceScreen) {
- if (!ActivityEmbeddingUtils.isEmbeddingActivityEnabled(getContext())
- || !(getActivity() instanceof SettingsHomepageActivity)) {
+ if (!mIsEmbeddingActivityEnabled || !(getActivity() instanceof SettingsHomepageActivity)) {
return super.onCreateAdapter(preferenceScreen);
}
return mHighlightMixin.onCreateAdapter(this, preferenceScreen);
diff --git a/src/com/android/settings/network/telephony/AlertDialogFragment.java b/src/com/android/settings/network/telephony/AlertDialogFragment.java
index 5940789..aaccc2d 100644
--- a/src/com/android/settings/network/telephony/AlertDialogFragment.java
+++ b/src/com/android/settings/network/telephony/AlertDialogFragment.java
@@ -16,13 +16,14 @@
package com.android.settings.network.telephony;
-import android.app.Activity;
-import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.text.TextUtils;
+import androidx.appcompat.app.AlertDialog;
+import androidx.fragment.app.FragmentActivity;
+
/** Fragment to show an alert dialog which only has the positive button. */
public class AlertDialogFragment extends BaseDialogFragment
implements DialogInterface.OnClickListener {
@@ -37,13 +38,13 @@
* @param title
* @param msg
*/
- public static void show(Activity activity, String title, String msg) {
+ public static void show(FragmentActivity activity, String title, String msg) {
AlertDialogFragment fragment = new AlertDialogFragment();
Bundle arguments = new Bundle();
arguments.putString(ARG_TITLE, title);
arguments.putString(ARG_MSG, msg);
fragment.setArguments(arguments);
- fragment.show(activity.getFragmentManager(), TAG);
+ fragment.show(activity.getSupportFragmentManager(), TAG);
}
@Override
@@ -55,7 +56,7 @@
if (!TextUtils.isEmpty(getArguments().getString(ARG_MSG))) {
builder.setMessage(getArguments().getString(ARG_MSG));
}
- return builder.show();
+ return builder.create();
}
@Override
diff --git a/src/com/android/settings/network/telephony/BaseDialogFragment.java b/src/com/android/settings/network/telephony/BaseDialogFragment.java
index 7da3259..0465cef 100644
--- a/src/com/android/settings/network/telephony/BaseDialogFragment.java
+++ b/src/com/android/settings/network/telephony/BaseDialogFragment.java
@@ -17,11 +17,11 @@
package com.android.settings.network.telephony;
import android.app.Activity;
-import android.app.DialogFragment;
-import android.app.Fragment;
import android.os.Bundle;
import androidx.annotation.Nullable;
+import androidx.fragment.app.DialogFragment;
+import androidx.fragment.app.Fragment;
/**
* Base dialog fragment class with the functionality to make a fragment or an activity as a listener
diff --git a/src/com/android/settings/network/telephony/ConfirmDialogFragment.java b/src/com/android/settings/network/telephony/ConfirmDialogFragment.java
index 04382da..bad981a 100644
--- a/src/com/android/settings/network/telephony/ConfirmDialogFragment.java
+++ b/src/com/android/settings/network/telephony/ConfirmDialogFragment.java
@@ -16,13 +16,24 @@
package com.android.settings.network.telephony;
-import android.app.Activity;
-import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+import android.widget.TextView;
+
+import androidx.appcompat.app.AlertDialog;
+import androidx.fragment.app.FragmentActivity;
+
+import com.android.settings.R;
+
+import java.util.ArrayList;
/** Fragment to show a confirm dialog. The caller should implement onConfirmListener. */
public class ConfirmDialogFragment extends BaseDialogFragment
@@ -32,6 +43,7 @@
private static final String ARG_MSG = "msg";
private static final String ARG_POS_BUTTON_STRING = "pos_button_string";
private static final String ARG_NEG_BUTTON_STRING = "neg_button_string";
+ private static final String ARG_LIST = "list";
/**
* Interface defining the method that will be invoked when the user has done with the dialog.
@@ -51,7 +63,7 @@
/** Displays a confirmation dialog which has confirm and cancel buttons. */
public static <T> void show(
- Activity activity,
+ FragmentActivity activity,
Class<T> callbackInterfaceClass,
int tagInCaller,
String title,
@@ -66,7 +78,29 @@
arguments.putString(ARG_NEG_BUTTON_STRING, negButtonString);
setListener(activity, null, callbackInterfaceClass, tagInCaller, arguments);
fragment.setArguments(arguments);
- fragment.show(activity.getFragmentManager(), TAG);
+ fragment.show(activity.getSupportFragmentManager(), TAG);
+ }
+
+ /** Displays a confirmation dialog which has confirm and cancel buttons and carrier list.*/
+ public static <T> void show(
+ FragmentActivity activity,
+ Class<T> callbackInterfaceClass,
+ int tagInCaller,
+ String title,
+ String msg,
+ String posButtonString,
+ String negButtonString,
+ ArrayList<String> list) {
+ ConfirmDialogFragment fragment = new ConfirmDialogFragment();
+ Bundle arguments = new Bundle();
+ arguments.putString(ARG_TITLE, title);
+ arguments.putCharSequence(ARG_MSG, msg);
+ arguments.putString(ARG_POS_BUTTON_STRING, posButtonString);
+ arguments.putString(ARG_NEG_BUTTON_STRING, negButtonString);
+ arguments.putStringArrayList(ARG_LIST, list);
+ setListener(activity, null, callbackInterfaceClass, tagInCaller, arguments);
+ fragment.setArguments(arguments);
+ fragment.show(activity.getSupportFragmentManager(), TAG);
}
@Override
@@ -75,18 +109,56 @@
String message = getArguments().getString(ARG_MSG);
String posBtnString = getArguments().getString(ARG_POS_BUTTON_STRING);
String negBtnString = getArguments().getString(ARG_NEG_BUTTON_STRING);
+ ArrayList<String> list = getArguments().getStringArrayList(ARG_LIST);
- Log.i("Showing dialog with title = %s", title);
+ Log.i(TAG, "Showing dialog with title =" + title);
AlertDialog.Builder builder =
new AlertDialog.Builder(getContext())
.setTitle(title)
.setPositiveButton(posBtnString, this)
.setNegativeButton(negBtnString, this);
- if (!TextUtils.isEmpty(message)) {
- builder.setMessage(message);
+ if (list != null && !list.isEmpty()) {
+ Log.i(TAG, "list =" + list.toString());
+
+ View content = LayoutInflater.from(getContext()).inflate(
+ R.layout.sim_confirm_dialog_multiple_enabled_profiles_supported, null);
+
+ TextView dialogMessage = content.findViewById(R.id.msg);
+ if (!TextUtils.isEmpty(message) && dialogMessage != null) {
+ dialogMessage.setText(message);
+ }
+
+ final ArrayAdapter<String> arrayAdapterItems = new ArrayAdapter<String>(
+ getContext(), android.R.layout.select_dialog_item, list);
+ final ListView lvItems = content.findViewById(R.id.carrier_list);
+ if (lvItems != null) {
+ lvItems.setAdapter(arrayAdapterItems);
+ lvItems.setChoiceMode(ListView.CHOICE_MODE_NONE);
+ lvItems.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view, int position,
+ long id) {
+ Log.i(TAG, "list onClick =" + position);
+ Log.i(TAG, "list item =" + list.get(position));
+
+ if (position == list.size() - 1) {
+ // user select the "cancel" item;
+ informCaller(false, -1);
+ } else {
+ informCaller(true, position);
+ }
+ }
+ });
+ }
+ builder.setView(content);
+ } else {
+ if (!TextUtils.isEmpty(message)) {
+ builder.setMessage(message);
+ }
}
- AlertDialog dialog = builder.show();
+
+ AlertDialog dialog = builder.create();
dialog.setCanceledOnTouchOutside(false);
return dialog;
}
diff --git a/src/com/android/settings/network/telephony/SubscriptionActionDialogActivity.java b/src/com/android/settings/network/telephony/SubscriptionActionDialogActivity.java
index 7ff0d9a..288f1ac 100644
--- a/src/com/android/settings/network/telephony/SubscriptionActionDialogActivity.java
+++ b/src/com/android/settings/network/telephony/SubscriptionActionDialogActivity.java
@@ -16,12 +16,13 @@
package com.android.settings.network.telephony;
-import android.app.Activity;
import android.os.Bundle;
import android.telephony.SubscriptionManager;
+import androidx.fragment.app.FragmentActivity;
+
/** The base class for subscription action dialogs */
-public class SubscriptionActionDialogActivity extends Activity {
+public class SubscriptionActionDialogActivity extends FragmentActivity {
private static final String TAG = "SubscriptionActionDialogActivity";
// Arguments
diff --git a/src/com/android/settings/network/telephony/ToggleSubscriptionDialogActivity.java b/src/com/android/settings/network/telephony/ToggleSubscriptionDialogActivity.java
index f8dee8b..cc2986d 100644
--- a/src/com/android/settings/network/telephony/ToggleSubscriptionDialogActivity.java
+++ b/src/com/android/settings/network/telephony/ToggleSubscriptionDialogActivity.java
@@ -455,6 +455,31 @@
private void showMepSwitchSimConfirmDialog() {
Log.i(TAG, "showMepSwitchSimConfirmDialog");
+ final CharSequence displayName = SubscriptionUtil.getUniqueSubscriptionDisplayName(
+ mSubInfo, this);
+ String title = getString(R.string.sim_action_switch_sub_dialog_mep_title, displayName);
+ final StringBuilder switchDialogMsg = new StringBuilder();
+ switchDialogMsg.append(
+ getString(R.string.sim_action_switch_sub_dialog_mep_text, displayName));
+ if (isRtlMode) {
+ /* There are two lines of message in the dialog, and the RTL symbols must be added
+ * before and after each sentence, so use the line break symbol to find the position.
+ * (Each message are all with two line break symbols)
+ */
+ switchDialogMsg.insert(0, RTL_MARK)
+ .insert(switchDialogMsg.indexOf(LINE_BREAK) - LINE_BREAK_OFFSET_ONE, RTL_MARK)
+ .insert(switchDialogMsg.indexOf(LINE_BREAK) + LINE_BREAK_OFFSET_TWO, RTL_MARK)
+ .insert(switchDialogMsg.length(), RTL_MARK);
+ }
+ ConfirmDialogFragment.show(
+ this,
+ ConfirmDialogFragment.OnConfirmListener.class,
+ DIALOG_TAG_ENABLE_SIM_CONFIRMATION_MEP,
+ title,
+ switchDialogMsg.toString(),
+ null,
+ null,
+ getSwitchDialogBodyList());
}
private String getSwitchDialogPosBtnText() {
diff --git a/src/com/android/settings/notification/zen/ZenModeRuleSettingsBase.java b/src/com/android/settings/notification/zen/ZenModeRuleSettingsBase.java
index 170c699..5ce8b48 100644
--- a/src/com/android/settings/notification/zen/ZenModeRuleSettingsBase.java
+++ b/src/com/android/settings/notification/zen/ZenModeRuleSettingsBase.java
@@ -59,6 +59,7 @@
@Override
public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
mContext = getActivity();
final Intent intent = getActivity().getIntent();
@@ -81,7 +82,6 @@
return;
}
- super.onCreate(icicle);
mCustomBehaviorPreference = getPreferenceScreen().findPreference(CUSTOM_BEHAVIOR_KEY);
mCustomBehaviorPreference.setOnPreferenceClickListener(
new Preference.OnPreferenceClickListener() {
diff --git a/src/com/android/settings/privacy/TopLevelPrivacyEntryPreferenceController.java b/src/com/android/settings/privacy/TopLevelPrivacyEntryPreferenceController.java
new file mode 100644
index 0000000..dcc68ff
--- /dev/null
+++ b/src/com/android/settings/privacy/TopLevelPrivacyEntryPreferenceController.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 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.privacy;
+
+import android.annotation.NonNull;
+import android.content.Context;
+
+import com.android.settings.core.BasePreferenceController;
+import com.android.settings.safetycenter.SafetyCenterStatus;
+
+/** The preference controller for the top level privacy tile. */
+public class TopLevelPrivacyEntryPreferenceController extends BasePreferenceController {
+
+ public TopLevelPrivacyEntryPreferenceController(@NonNull Context context, @NonNull String key) {
+ super(context, key);
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ if (!SafetyCenterStatus.isEnabled()) {
+ return AVAILABLE;
+ }
+ return CONDITIONALLY_UNAVAILABLE;
+ }
+}
diff --git a/src/com/android/settings/safetycenter/SafetyCenterStatus.java b/src/com/android/settings/safetycenter/SafetyCenterStatus.java
new file mode 100644
index 0000000..d96bb32
--- /dev/null
+++ b/src/com/android/settings/safetycenter/SafetyCenterStatus.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2021 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.safetycenter;
+
+import android.provider.DeviceConfig;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+/** Knows whether safety center is enabled or disabled. */
+public class SafetyCenterStatus {
+
+ /** Whether SafetyCenter page is enabled. */
+ @VisibleForTesting
+ public static final String SAFETY_CENTER_IS_ENABLED = "safety_center_is_enabled";
+
+ /** Returns true is SafetyCenter page is enabled, false otherwise. */
+ public static boolean isEnabled() {
+ // TODO(b/208625216): use SafetyManager API instead
+ return DeviceConfig.getBoolean(
+ DeviceConfig.NAMESPACE_PRIVACY, SAFETY_CENTER_IS_ENABLED, false);
+ }
+}
diff --git a/src/com/android/settings/safetycenter/TopLevelSafetyCenterEntryPreferenceController.java b/src/com/android/settings/safetycenter/TopLevelSafetyCenterEntryPreferenceController.java
new file mode 100644
index 0000000..b3b49b0
--- /dev/null
+++ b/src/com/android/settings/safetycenter/TopLevelSafetyCenterEntryPreferenceController.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2021 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.safetycenter;
+
+import android.content.ActivityNotFoundException;
+import android.content.Context;
+import android.content.Intent;
+import android.text.TextUtils;
+import android.util.Log;
+
+import androidx.preference.Preference;
+
+import com.android.settings.core.BasePreferenceController;
+
+/** Controller for the SafetyCenter entry in top level Settings. */
+public class TopLevelSafetyCenterEntryPreferenceController extends BasePreferenceController {
+
+ private static final String TAG = "TopLevelSafetyCenterEntryPreferenceController";
+
+ public TopLevelSafetyCenterEntryPreferenceController(Context context, String preferenceKey) {
+ super(context, preferenceKey);
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ if (SafetyCenterStatus.isEnabled()) {
+ return AVAILABLE;
+ }
+ return CONDITIONALLY_UNAVAILABLE;
+ }
+
+ @Override
+ public boolean handlePreferenceTreeClick(Preference preference) {
+ if (!TextUtils.equals(preference.getKey(), getPreferenceKey())) {
+ return super.handlePreferenceTreeClick(preference);
+ }
+
+ try {
+ mContext.startActivity(new Intent(Intent.ACTION_SAFETY_CENTER));
+ } catch (ActivityNotFoundException e) {
+ Log.e(TAG, "Unable to open safety center", e);
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/src/com/android/settings/security/TopLevelSecurityEntryPreferenceController.java b/src/com/android/settings/security/TopLevelSecurityEntryPreferenceController.java
index 964482e..2d98606 100644
--- a/src/com/android/settings/security/TopLevelSecurityEntryPreferenceController.java
+++ b/src/com/android/settings/security/TopLevelSecurityEntryPreferenceController.java
@@ -24,6 +24,7 @@
import com.android.settings.core.BasePreferenceController;
import com.android.settings.core.SubSettingLauncher;
import com.android.settings.overlay.FeatureFactory;
+import com.android.settings.safetycenter.SafetyCenterStatus;
public class TopLevelSecurityEntryPreferenceController extends BasePreferenceController {
@@ -37,7 +38,10 @@
@Override
public int getAvailabilityStatus() {
- return AVAILABLE;
+ if (!SafetyCenterStatus.isEnabled()) {
+ return AVAILABLE;
+ }
+ return CONDITIONALLY_UNAVAILABLE;
}
@Override
diff --git a/src/com/android/settings/sim/SimDialogActivity.java b/src/com/android/settings/sim/SimDialogActivity.java
index e5457ae..f9aca77 100644
--- a/src/com/android/settings/sim/SimDialogActivity.java
+++ b/src/com/android/settings/sim/SimDialogActivity.java
@@ -160,8 +160,10 @@
final TelephonyManager telephonyManager = getSystemService(
TelephonyManager.class).createForSubscriptionId(subId);
subscriptionManager.setDefaultDataSubId(subId);
- telephonyManager.setDataEnabled(true);
- Toast.makeText(this, R.string.data_switch_started, Toast.LENGTH_LONG).show();
+ if (subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+ telephonyManager.setDataEnabled(true);
+ Toast.makeText(this, R.string.data_switch_started, Toast.LENGTH_LONG).show();
+ }
}
private void setDefaultCallsSubId(final int subId) {
diff --git a/tests/unit/src/com/android/settings/privacy/TopLevelPrivacyEntryPreferenceControllerTest.java b/tests/unit/src/com/android/settings/privacy/TopLevelPrivacyEntryPreferenceControllerTest.java
new file mode 100644
index 0000000..570df73
--- /dev/null
+++ b/tests/unit/src/com/android/settings/privacy/TopLevelPrivacyEntryPreferenceControllerTest.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2021 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.privacy;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.provider.DeviceConfig;
+import android.provider.Settings;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import com.android.settings.safetycenter.SafetyCenterStatus;
+import com.android.settings.security.TopLevelSecurityEntryPreferenceController;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+
+@RunWith(AndroidJUnit4.class)
+public class TopLevelPrivacyEntryPreferenceControllerTest {
+
+ private static final String PREFERENCE_KEY = "top_level_privacy";
+
+ private TopLevelPrivacyEntryPreferenceController mTopLevelPrivacyEntryPreferenceController;
+
+ @Mock
+ private Context mContext;
+
+ @Before
+ public void setUp() {
+ DeviceConfig.resetToDefaults(Settings.RESET_MODE_PACKAGE_DEFAULTS,
+ DeviceConfig.NAMESPACE_PRIVACY);
+
+ mTopLevelPrivacyEntryPreferenceController =
+ new TopLevelPrivacyEntryPreferenceController(mContext, PREFERENCE_KEY);
+ }
+
+ @After
+ public void tearDown() {
+ DeviceConfig.resetToDefaults(Settings.RESET_MODE_PACKAGE_DEFAULTS,
+ DeviceConfig.NAMESPACE_PRIVACY);
+ }
+
+ @Test
+ public void getAvailabilityStatus_whenSafetyCenterEnabled_returnsUnavailable() {
+ DeviceConfig.setProperty(
+ DeviceConfig.NAMESPACE_PRIVACY,
+ SafetyCenterStatus.SAFETY_CENTER_IS_ENABLED,
+ /* value = */ Boolean.toString(true),
+ /* makeDefault = */ false);
+
+ assertThat(mTopLevelPrivacyEntryPreferenceController.getAvailabilityStatus())
+ .isEqualTo(TopLevelSecurityEntryPreferenceController.CONDITIONALLY_UNAVAILABLE);
+ }
+
+ @Test
+ public void getAvailabilityStatus_whenSafetyCenterDisabled_returnsAvailable() {
+ DeviceConfig.setProperty(
+ DeviceConfig.NAMESPACE_PRIVACY,
+ SafetyCenterStatus.SAFETY_CENTER_IS_ENABLED,
+ /* value = */ Boolean.toString(false),
+ /* makeDefault = */ false);
+
+ assertThat(mTopLevelPrivacyEntryPreferenceController.getAvailabilityStatus())
+ .isEqualTo(TopLevelSecurityEntryPreferenceController.AVAILABLE);
+ }
+}
diff --git a/tests/unit/src/com/android/settings/safetycenter/SafetyCenterStatusTest.java b/tests/unit/src/com/android/settings/safetycenter/SafetyCenterStatusTest.java
new file mode 100644
index 0000000..f36fbe1
--- /dev/null
+++ b/tests/unit/src/com/android/settings/safetycenter/SafetyCenterStatusTest.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2021 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.safetycenter;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.provider.DeviceConfig;
+import android.provider.Settings;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class SafetyCenterStatusTest {
+
+ @Before
+ public void setUp() {
+ DeviceConfig.resetToDefaults(Settings.RESET_MODE_PACKAGE_DEFAULTS,
+ DeviceConfig.NAMESPACE_PRIVACY);
+ }
+
+ @After
+ public void tearDown() {
+ DeviceConfig.resetToDefaults(Settings.RESET_MODE_PACKAGE_DEFAULTS,
+ DeviceConfig.NAMESPACE_PRIVACY);
+ }
+
+ @Test
+ public void isEnabled_whenFlagTrue_returnsTrue() {
+ DeviceConfig.setProperty(
+ DeviceConfig.NAMESPACE_PRIVACY,
+ SafetyCenterStatus.SAFETY_CENTER_IS_ENABLED,
+ /* value = */ Boolean.toString(true),
+ /* makeDefault = */ false);
+
+ assertThat(SafetyCenterStatus.isEnabled()).isTrue();
+ }
+
+ @Test
+ public void isEnabled_whenFlagFalse_returnsFalse() {
+ DeviceConfig.setProperty(
+ DeviceConfig.NAMESPACE_PRIVACY,
+ SafetyCenterStatus.SAFETY_CENTER_IS_ENABLED,
+ /* value = */ Boolean.toString(false),
+ /* makeDefault = */ false);
+
+ assertThat(SafetyCenterStatus.isEnabled()).isFalse();
+ }
+}
diff --git a/tests/unit/src/com/android/settings/safetycenter/TopLevelSafetyCenterEntryPreferenceControllerTest.java b/tests/unit/src/com/android/settings/safetycenter/TopLevelSafetyCenterEntryPreferenceControllerTest.java
new file mode 100644
index 0000000..907fb99
--- /dev/null
+++ b/tests/unit/src/com/android/settings/safetycenter/TopLevelSafetyCenterEntryPreferenceControllerTest.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2021 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.safetycenter;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.verify;
+
+import android.content.ActivityNotFoundException;
+import android.content.Context;
+import android.content.Intent;
+import android.provider.DeviceConfig;
+import android.provider.Settings;
+
+import androidx.preference.Preference;
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@RunWith(AndroidJUnit4.class)
+public class TopLevelSafetyCenterEntryPreferenceControllerTest {
+
+ private static final String PREFERENCE_KEY = "top_level_safety_center";
+
+ private TopLevelSafetyCenterEntryPreferenceController
+ mTopLevelSafetyCenterEntryPreferenceController;
+ private Preference mPreference;
+
+ @Mock
+ private Context mContext;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ mPreference = new Preference(ApplicationProvider.getApplicationContext());
+ mPreference.setKey(PREFERENCE_KEY);
+
+ doNothing().when(mContext).startActivity(any(Intent.class));
+ mTopLevelSafetyCenterEntryPreferenceController =
+ new TopLevelSafetyCenterEntryPreferenceController(mContext, PREFERENCE_KEY);
+ DeviceConfig.resetToDefaults(Settings.RESET_MODE_PACKAGE_DEFAULTS,
+ DeviceConfig.NAMESPACE_PRIVACY);
+ }
+
+ @After
+ public void tearDown() {
+ DeviceConfig.resetToDefaults(Settings.RESET_MODE_PACKAGE_DEFAULTS,
+ DeviceConfig.NAMESPACE_PRIVACY);
+ }
+
+ @Test
+ public void handlePreferenceTreeClick_forDifferentPreferenceKey_isNotHandled() {
+ Preference preference = new Preference(ApplicationProvider.getApplicationContext());
+ preference.setKey("some_other_preference");
+
+ boolean preferenceHandled =
+ mTopLevelSafetyCenterEntryPreferenceController.handlePreferenceTreeClick(
+ preference);
+
+ assertThat(preferenceHandled).isFalse();
+ }
+
+ @Test
+ public void handlePreferenceTreeClick_launchesIntendedIntent() {
+ final ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
+
+ boolean preferenceHandled = mTopLevelSafetyCenterEntryPreferenceController
+ .handlePreferenceTreeClick(mPreference);
+
+ assertThat(preferenceHandled).isTrue();
+ verify(mContext).startActivity(intentCaptor.capture());
+ assertThat(intentCaptor.getValue().getAction()).isEqualTo(Intent.ACTION_SAFETY_CENTER);
+ }
+
+ @Test
+ public void handlePreferenceTreeClick_onStartActivityThrows_returnsFalse() {
+ doThrow(ActivityNotFoundException.class)
+ .when(mContext).startActivity(any(Intent.class));
+
+ boolean preferenceHandled = mTopLevelSafetyCenterEntryPreferenceController
+ .handlePreferenceTreeClick(mPreference);
+
+ assertThat(preferenceHandled).isFalse();
+ }
+
+ @Test
+ public void getAvailabilityStatus_whenSafetyCenterDisabled_returnsUnavailable() {
+ DeviceConfig.setProperty(
+ DeviceConfig.NAMESPACE_PRIVACY,
+ SafetyCenterStatus.SAFETY_CENTER_IS_ENABLED,
+ /* value = */ Boolean.toString(false),
+ /* makeDefault = */ false);
+
+ assertThat(mTopLevelSafetyCenterEntryPreferenceController.getAvailabilityStatus())
+ .isEqualTo(TopLevelSafetyCenterEntryPreferenceController.CONDITIONALLY_UNAVAILABLE);
+ }
+
+ @Test
+ public void getAvailabilityStatus_whenSafetyCenterEnabled_returnsAvailable() {
+ DeviceConfig.setProperty(
+ DeviceConfig.NAMESPACE_PRIVACY,
+ SafetyCenterStatus.SAFETY_CENTER_IS_ENABLED,
+ /* value = */ Boolean.toString(true),
+ /* makeDefault = */ false);
+
+ assertThat(mTopLevelSafetyCenterEntryPreferenceController.getAvailabilityStatus())
+ .isEqualTo(TopLevelSafetyCenterEntryPreferenceController.AVAILABLE);
+ }
+}
diff --git a/tests/unit/src/com/android/settings/security/TopLevelSecurityEntryPreferenceControllerTest.java b/tests/unit/src/com/android/settings/security/TopLevelSecurityEntryPreferenceControllerTest.java
index a9acd2a..7e83ca7 100644
--- a/tests/unit/src/com/android/settings/security/TopLevelSecurityEntryPreferenceControllerTest.java
+++ b/tests/unit/src/com/android/settings/security/TopLevelSecurityEntryPreferenceControllerTest.java
@@ -25,14 +25,18 @@
import android.content.Context;
import android.content.Intent;
+import android.provider.DeviceConfig;
+import android.provider.Settings;
import androidx.preference.Preference;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.settings.SettingsActivity;
+import com.android.settings.safetycenter.SafetyCenterStatus;
import com.android.settings.testutils.FakeFeatureFactory;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -60,6 +64,9 @@
mFeatureFactory = FakeFeatureFactory.setupForTest();
mSecuritySettingsFeatureProvider = mFeatureFactory.getSecuritySettingsFeatureProvider();
+ DeviceConfig.resetToDefaults(Settings.RESET_MODE_PACKAGE_DEFAULTS,
+ DeviceConfig.NAMESPACE_PRIVACY);
+
mPreference = new Preference(ApplicationProvider.getApplicationContext());
mPreference.setKey(PREFERENCE_KEY);
@@ -68,6 +75,12 @@
new TopLevelSecurityEntryPreferenceController(mContext, PREFERENCE_KEY);
}
+ @After
+ public void tearDown() {
+ DeviceConfig.resetToDefaults(Settings.RESET_MODE_PACKAGE_DEFAULTS,
+ DeviceConfig.NAMESPACE_PRIVACY);
+ }
+
@Test
public void handlePreferenceTreeClick_forDifferentPreferenceKey_isNotHandled() {
Preference preference = new Preference(ApplicationProvider.getApplicationContext());
@@ -121,4 +134,28 @@
assertThat(preferenceHandled).isFalse();
}
+
+ @Test
+ public void getAvailabilityStatus_whenSafetyCenterEnabled_returnsUnavailable() {
+ DeviceConfig.setProperty(
+ DeviceConfig.NAMESPACE_PRIVACY,
+ SafetyCenterStatus.SAFETY_CENTER_IS_ENABLED,
+ /* value = */ Boolean.toString(true),
+ /* makeDefault = */ false);
+
+ assertThat(mTopLevelSecurityEntryPreferenceController.getAvailabilityStatus())
+ .isEqualTo(TopLevelSecurityEntryPreferenceController.CONDITIONALLY_UNAVAILABLE);
+ }
+
+ @Test
+ public void getAvailabilityStatus_whenSafetyCenterDisabled_returnsAvailable() {
+ DeviceConfig.setProperty(
+ DeviceConfig.NAMESPACE_PRIVACY,
+ SafetyCenterStatus.SAFETY_CENTER_IS_ENABLED,
+ /* value = */ Boolean.toString(false),
+ /* makeDefault = */ false);
+
+ assertThat(mTopLevelSecurityEntryPreferenceController.getAvailabilityStatus())
+ .isEqualTo(TopLevelSecurityEntryPreferenceController.AVAILABLE);
+ }
}