Merge "Fix NPE in AddUserWhenLockedPreferenceController."
diff --git a/res/drawable/ic_add_blue_24dp.xml b/res/drawable/ic_add_blue_24dp.xml
new file mode 100644
index 0000000..a9a2f60
--- /dev/null
+++ b/res/drawable/ic_add_blue_24dp.xml
@@ -0,0 +1,26 @@
+<!--
+ Copyright (C) 2020 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
+ -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:fillColor="#4285F4"
+ android:pathData="M20,13h-7v7h-2v-7H4v-2h7V4h2v7h7V13z"/>
+</vector>
+
diff --git a/res/drawable/ic_check_box_anim.xml b/res/drawable/ic_check_box_anim.xml
new file mode 100644
index 0000000..f6aed8f
--- /dev/null
+++ b/res/drawable/ic_check_box_anim.xml
@@ -0,0 +1,25 @@
+<!--
+ Copyright (C) 2020 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
+ -->
+
+<animated-selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item
+ android:id="@+id/checked"
+ android:state_checked="true"
+ android:drawable="@drawable/ic_check_box_blue_24dp" />
+ <item
+ android:id="@+id/unchecked"
+ android:drawable="@drawable/ic_check_box_outline_24dp" />
+</animated-selector>
diff --git a/res/drawable/ic_check_box_blue_24dp.xml b/res/drawable/ic_check_box_blue_24dp.xml
new file mode 100644
index 0000000..43cae69
--- /dev/null
+++ b/res/drawable/ic_check_box_blue_24dp.xml
@@ -0,0 +1,26 @@
+<!--
+ Copyright (C) 2020 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
+ -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M19,3L5,3c-1.11,0 -2,0.9 -2,2v14c0,1.1 0.89,2 2,2h14c1.11,0 2,-0.9 2,-2L21,5c0,-1.1 -0.89,-2 -2,-2zM10,17l-5,-5 1.41,-1.41L10,14.17l7.59,-7.59L19,8l-9,9z"
+ android:fillColor="#4285F4"/>
+</vector>
+
diff --git a/res/drawable/ic_check_box_outline_24dp.xml b/res/drawable/ic_check_box_outline_24dp.xml
new file mode 100644
index 0000000..f6f453a
--- /dev/null
+++ b/res/drawable/ic_check_box_outline_24dp.xml
@@ -0,0 +1,26 @@
+<!--
+ Copyright (C) 2020 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
+ -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M19,5v14H5V5h14m0,-2H5c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2V5c0,-1.1 -0.9,-2 -2,-2z"
+ android:fillColor="#757575"/>
+</vector>
+
diff --git a/res/drawable/ic_speaker_group_black_24dp.xml b/res/drawable/ic_speaker_group_black_24dp.xml
new file mode 100644
index 0000000..ae0d562
--- /dev/null
+++ b/res/drawable/ic_speaker_group_black_24dp.xml
@@ -0,0 +1,31 @@
+<!--
+ Copyright (C) 2020 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
+ -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M18.2,1L9.8,1C8.81,1 8,1.81 8,2.8v14.4c0,0.99 0.81,1.79 1.8,1.79l8.4,0.01c0.99,0 1.8,-0.81 1.8,-1.8L20,2.8c0,-0.99 -0.81,-1.8 -1.8,-1.8zM14,3c1.1,0 2,0.89 2,2s-0.9,2 -2,2 -2,-0.89 -2,-2 0.9,-2 2,-2zM14,16.5c-2.21,0 -4,-1.79 -4,-4s1.79,-4 4,-4 4,1.79 4,4 -1.79,4 -4,4z"
+ android:fillColor="#000000"/>
+ <path
+ android:pathData="M14,12.5m-2.5,0a2.5,2.5 0,1 1,5 0a2.5,2.5 0,1 1,-5 0"
+ android:fillColor="#000000"/>
+ <path
+ android:pathData="M6,5H4v16c0,1.1 0.89,2 2,2h10v-2H6V5z"
+ android:fillColor="#000000"/>
+</vector>
diff --git a/res/values/config.xml b/res/values/config.xml
index 42bc0d6..2373b25 100755
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -206,6 +206,9 @@
com.android.settings.intelligence
</string>
+ <!-- Whether the confirmation for sim deletion is defaulted to be on or off-->
+ <bool name="config_sim_deletion_confirmation_default_on">false</bool>
+
<!-- Package Installer package name -->
<string name="config_package_installer_package_name" translatable="false">
com.android.packageinstaller
diff --git a/res/values/strings.xml b/res/values/strings.xml
index adf414f2..ac77cc5 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -3767,7 +3767,12 @@
<!-- Tethering setting summary when hotspot and tethering are off [CHAR LIMIT=NONE]-->
<string name="tether_settings_summary_off">Not sharing internet with other devices</string>
+ <!-- Tethering interface options [CHAR LIMIT=NONE]-->
+ <string name="tethering_interface_options">Tethering</string>
+
<!-- Disable Wifi Hotspot option-->
+ <!-- Don't use Wi-Fi hotspot title [CHAR LIMIT=NONE]-->
+ <string name="disable_wifi_hotspot_title">Don\u2019t use Wi\u2011Fi hotspot</string>
<!-- Don't use Wi-Fi hotspot summary when USB tethering is chosen [CHAR LIMIT=NONE]-->
<string name="disable_wifi_hotspot_when_usb_on">Only share internet via USB</string>
<!-- Don't use Wi-Fi hotspot summary when Bluetooth tethering is chosen [CHAR LIMIT=NONE]-->
@@ -9013,6 +9018,11 @@
<!-- [CHAR LIMIT=60] Unlock setting for screen pinning -->
<string name="screen_pinning_unlock_none">Lock device when unpinning</string>
+ <!-- [CHAR LIMIT=60] turn eSim deletion confirmation on/off -->
+ <string name="confirm_sim_deletion_title">Confirm SIM deletion</string>
+ <!-- [CHAR LIMIT=NONE] eSim deletion confirmation description -->
+ <string name="confirm_sim_deletion_description">Verify it\u0027s you before erasing a downloaded SIM</string>
+
<!-- Opening string on the dialog that prompts the user to confirm that they really want to delete their existing work profile. The administration app icon and name appear after the final colon. [CHAR LIMIT=NONE] -->
<string name="opening_paragraph_delete_profile_unknown_company">This work profile is managed by:</string>
<!-- Summary for work profile accounts group. [CHAR LIMIT=25] -->
@@ -11064,6 +11074,18 @@
<!-- Summary for media output settings when the media stream is being captured by something else. -->
<string name="media_output_summary_unavailable">Unavailable</string>
+ <!-- Title for the media output group dialog with media related devices [CHAR LIMIT=50] -->
+ <string name="media_output_group_panel_title">Add outputs</string>
+
+ <!-- Title for the media output slice with group devices [CHAR LIMIT=50] -->
+ <string name="media_output_group">Group</string>
+
+ <!-- Summary for media output group with only one device which is active [CHAR LIMIT=NONE] -->
+ <string name="media_output_group_panel_single_device_summary">1 device selected</string>
+
+ <!-- Summary for media output group with the active device count [CHAR LIMIT=NONE] -->
+ <string name="media_output_group_panel_multiple_devices_summary"><xliff:g id="count" example="2">%1$d</xliff:g> devices selected</string>
+
<!-- Title for HFP(hands free profile) output switch button in settings. -->
<string name="take_call_on_title">Take call on</string>
diff --git a/res/xml/all_tether_prefs.xml b/res/xml/all_tether_prefs.xml
index d16adc5..f552522 100644
--- a/res/xml/all_tether_prefs.xml
+++ b/res/xml/all_tether_prefs.xml
@@ -55,7 +55,7 @@
<PreferenceCategory
android:key="tethering_options_group"
- android:title="Tethering"
+ android:title="@string/tethering_interface_options"
settings:searchable="false">
<SwitchPreference
android:key="enable_usb_tethering"
@@ -73,7 +73,7 @@
<SwitchPreference
android:key="disable_wifi_tethering"
- android:title="Don't use Wi-Fi hotspot"
+ android:title="@string/disable_wifi_hotspot_title"
android:summary="@string/summary_placeholder"
settings:controller="com.android.settings.network.WifiTetherDisablePreferenceController"
settings:keywords="@string/keywords_hotspot_tethering" />
diff --git a/res/xml/security_dashboard_settings.xml b/res/xml/security_dashboard_settings.xml
index d417bb2..7610b32 100644
--- a/res/xml/security_dashboard_settings.xml
+++ b/res/xml/security_dashboard_settings.xml
@@ -147,4 +147,11 @@
android:summary="@string/summary_placeholder"
android:fragment="com.android.settings.security.ScreenPinningSettings" />
-</PreferenceScreen>
+ <SwitchPreference
+ android:order="90"
+ android:key="confirm_sim_deletion"
+ android:title="@string/confirm_sim_deletion_title"
+ android:summary="@string/confirm_sim_deletion_description"
+ settings:controller="com.android.settings.security.ConfirmSimDeletionPreferenceController"/>
+
+</PreferenceScreen>
\ No newline at end of file
diff --git a/res/xml/sound_settings.xml b/res/xml/sound_settings.xml
index a24a95f..2c42111 100644
--- a/res/xml/sound_settings.xml
+++ b/res/xml/sound_settings.xml
@@ -22,13 +22,14 @@
settings:keywords="@string/keywords_sounds"
settings:initialExpandedChildrenCount="9">
- <!-- Remote volume -->
- <com.android.settings.notification.RemoteVolumeSeekBarPreference
- android:key="remote_volume"
- android:icon="@drawable/ic_volume_remote"
- android:title="@string/remote_media_volume_option_title"
+ <!-- Remote volume group -->
+ <PreferenceCategory
+ android:key="remote_media_group"
+ android:title=""
android:order="-185"
- settings:controller="com.android.settings.notification.RemoteVolumePreferenceController"/>
+ settings:allowDividerBelow="true"
+ settings:controller="com.android.settings.notification.RemoteVolumeGroupController">
+ </PreferenceCategory>
<!-- Media volume -->
<com.android.settings.notification.VolumeSeekBarPreference
diff --git a/src/com/android/settings/accessibility/ShortcutPreference.java b/src/com/android/settings/accessibility/ShortcutPreference.java
index 2a62439..00b63b6 100644
--- a/src/com/android/settings/accessibility/ShortcutPreference.java
+++ b/src/com/android/settings/accessibility/ShortcutPreference.java
@@ -165,6 +165,9 @@
setWidgetLayoutResource(R.layout.preference_widget_settings);
setIconSpaceReserved(false);
mAutoEnabledSettings = true;
+
+ // Disable whole component to let each child component can be addressed.
+ setSelectable(false);
}
private void callOnSettingsClicked() {
diff --git a/src/com/android/settings/network/telephony/DeleteSimProfilePreferenceController.java b/src/com/android/settings/network/telephony/DeleteSimProfilePreferenceController.java
index daabf8b..b6a78a1 100644
--- a/src/com/android/settings/network/telephony/DeleteSimProfilePreferenceController.java
+++ b/src/com/android/settings/network/telephony/DeleteSimProfilePreferenceController.java
@@ -18,15 +18,18 @@
import android.content.Context;
import android.content.Intent;
+import android.provider.Settings;
import android.telephony.SubscriptionInfo;
import android.telephony.euicc.EuiccManager;
import androidx.fragment.app.Fragment;
import androidx.preference.Preference;
-import androidx.preference.PreferenceScreen;
+import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.network.SubscriptionUtil;
+import com.android.settings.security.ConfirmSimDeletionPreferenceController;
+import com.android.settings.wifi.dpp.WifiDppUtils;
/** This controls a preference allowing the user to delete the profile for an eSIM. */
public class DeleteSimProfilePreferenceController extends BasePreferenceController {
@@ -34,16 +37,19 @@
private SubscriptionInfo mSubscriptionInfo;
private Fragment mParentFragment;
private int mRequestCode;
+ private boolean mConfirmationDefaultOn;
public DeleteSimProfilePreferenceController(Context context, String preferenceKey) {
super(context, preferenceKey);
+ mConfirmationDefaultOn =
+ context.getResources()
+ .getBoolean(R.bool.config_sim_deletion_confirmation_default_on);
}
public void init(int subscriptionId, Fragment parentFragment, int requestCode) {
mParentFragment = parentFragment;
- for (SubscriptionInfo info : SubscriptionUtil.getAvailableSubscriptions(
- mContext)) {
+ for (SubscriptionInfo info : SubscriptionUtil.getAvailableSubscriptions(mContext)) {
if (info.getSubscriptionId() == subscriptionId && info.isEmbedded()) {
mSubscriptionInfo = info;
break;
@@ -53,16 +59,27 @@
}
@Override
- public void displayPreference(PreferenceScreen screen) {
- super.displayPreference(screen);
- final Preference pref = screen.findPreference(getPreferenceKey());
- pref.setOnPreferenceClickListener(p -> {
- final Intent intent = new Intent(EuiccManager.ACTION_DELETE_SUBSCRIPTION_PRIVILEGED);
- intent.putExtra(EuiccManager.EXTRA_SUBSCRIPTION_ID,
- mSubscriptionInfo.getSubscriptionId());
- mParentFragment.startActivityForResult(intent, mRequestCode);
- return true;
- });
+ public boolean handlePreferenceTreeClick(Preference preference) {
+ boolean confirmDeletion =
+ Settings.Global.getInt(
+ mContext.getContentResolver(),
+ ConfirmSimDeletionPreferenceController.KEY_CONFIRM_SIM_DELETION,
+ mConfirmationDefaultOn ? 1 : 0)
+ == 1;
+ if (confirmDeletion) {
+ WifiDppUtils.showLockScreen(mContext, () -> deleteSim());
+ } else {
+ deleteSim();
+ }
+
+ return true;
+ }
+
+ private void deleteSim() {
+ final Intent intent = new Intent(EuiccManager.ACTION_DELETE_SUBSCRIPTION_PRIVILEGED);
+ intent.putExtra(EuiccManager.EXTRA_SUBSCRIPTION_ID, mSubscriptionInfo.getSubscriptionId());
+ mParentFragment.startActivityForResult(intent, mRequestCode);
+ // result handled in MobileNetworkSettings
}
@Override
@@ -73,5 +90,4 @@
return CONDITIONALLY_UNAVAILABLE;
}
}
-
}
diff --git a/src/com/android/settings/network/telephony/MobileNetworkSettings.java b/src/com/android/settings/network/telephony/MobileNetworkSettings.java
index 199564d..e5ba96a 100644
--- a/src/com/android/settings/network/telephony/MobileNetworkSettings.java
+++ b/src/com/android/settings/network/telephony/MobileNetworkSettings.java
@@ -274,9 +274,11 @@
break;
case REQUEST_CODE_DELETE_SUBSCRIPTION:
- final Activity activity = getActivity();
- if (activity != null && !activity.isFinishing()) {
- activity.finish();
+ if (resultCode != Activity.RESULT_CANCELED) {
+ final Activity activity = getActivity();
+ if (activity != null && !activity.isFinishing()) {
+ activity.finish();
+ }
}
break;
diff --git a/src/com/android/settings/notification/RemoteVolumePreferenceController.java b/src/com/android/settings/notification/RemoteVolumePreferenceController.java
deleted file mode 100644
index bb41975..0000000
--- a/src/com/android/settings/notification/RemoteVolumePreferenceController.java
+++ /dev/null
@@ -1,300 +0,0 @@
-/*
- * Copyright (C) 2019 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.notification;
-
-import android.content.Context;
-import android.media.session.MediaController;
-import android.media.session.MediaSession;
-import android.media.session.MediaSessionManager;
-import android.net.Uri;
-import android.os.Looper;
-import android.text.TextUtils;
-import android.util.Log;
-
-import androidx.annotation.VisibleForTesting;
-import androidx.lifecycle.OnLifecycleEvent;
-import androidx.preference.PreferenceScreen;
-
-import com.android.settings.R;
-import com.android.settings.slices.SliceBackgroundWorker;
-import com.android.settingslib.core.lifecycle.Lifecycle;
-import com.android.settingslib.volume.MediaSessions;
-
-import java.io.IOException;
-import java.util.List;
-import java.util.Objects;
-
-public class RemoteVolumePreferenceController extends VolumeSeekBarPreferenceController {
-
- private static final String KEY_REMOTE_VOLUME = "remote_volume";
- private static final String TAG = "RemoteVolumePrefCtr";
- @VisibleForTesting
- static final int REMOTE_VOLUME = 100;
-
- private MediaSessions mMediaSessions;
- @VisibleForTesting
- MediaSession.Token mActiveToken;
- @VisibleForTesting
- MediaController mMediaController;
-
- @VisibleForTesting
- MediaSessions.Callbacks mCallbacks = new MediaSessions.Callbacks() {
- @Override
- public void onRemoteUpdate(MediaSession.Token token, String name,
- MediaController.PlaybackInfo pi) {
- if (mActiveToken == null) {
- updateToken(token);
- }
- if (Objects.equals(mActiveToken, token)) {
- updatePreference(mPreference, mActiveToken, pi);
- }
- }
-
- @Override
- public void onRemoteRemoved(MediaSession.Token t) {
- if (Objects.equals(mActiveToken, t)) {
- updateToken(null);
- if (mPreference != null) {
- mPreference.setVisible(false);
- }
- }
- }
-
- @Override
- public void onRemoteVolumeChanged(MediaSession.Token token, int flags) {
- if (Objects.equals(mActiveToken, token)) {
- if (mPreference == null) {
- Log.e(TAG,"Preference is null");
- return;
- }
- if (mMediaController == null) {
- Log.e(TAG,"MediaController is null");
- return;
- }
- final MediaController.PlaybackInfo pi = mMediaController.getPlaybackInfo();
- if (pi == null) {
- Log.e(TAG,"PlaybackInfo is null");
- return;
- }
- mPreference.setProgress(pi.getCurrentVolume());
- }
- }
- };
-
- public RemoteVolumePreferenceController(Context context) {
- super(context, KEY_REMOTE_VOLUME);
- mMediaSessions = new MediaSessions(context, Looper.getMainLooper(), mCallbacks);
- updateToken(getActiveRemoteToken(mContext));
- }
-
- @Override
- public int getAvailabilityStatus() {
- // Always return true to make it indexed in database
- return AVAILABLE_UNSEARCHABLE;
- }
-
- /**
- * Return {@link android.media.session.MediaSession.Token} for active remote token, or
- * {@code null} if there is no active remote token.
- */
- public static MediaSession.Token getActiveRemoteToken(Context context) {
- final MediaSessionManager sessionManager = context.getSystemService(
- MediaSessionManager.class);
- final List<MediaController> controllers = sessionManager.getActiveSessions(null);
- for (MediaController mediaController : controllers) {
- final MediaController.PlaybackInfo pi = mediaController.getPlaybackInfo();
- if (isRemote(pi)) {
- return mediaController.getSessionToken();
- }
- }
-
- // No active remote media at this point
- return null;
- }
-
- @Override
- public void displayPreference(PreferenceScreen screen) {
- super.displayPreference(screen);
- mPreference.setVisible(mActiveToken != null);
- if (mMediaController != null) {
- updatePreference(mPreference, mActiveToken, mMediaController.getPlaybackInfo());
- }
- }
-
- @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
- public void onResume() {
- super.onResume();
- mMediaSessions.init();
- }
-
- @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
- public void onPause() {
- super.onPause();
- mMediaSessions.destroy();
- }
-
- @Override
- public int getSliderPosition() {
- if (mPreference != null) {
- return mPreference.getProgress();
- }
- if (mMediaController == null) {
- return 0;
- }
- final MediaController.PlaybackInfo playbackInfo = mMediaController.getPlaybackInfo();
- return playbackInfo != null ? playbackInfo.getCurrentVolume() : 0;
- }
-
- @Override
- public boolean setSliderPosition(int position) {
- if (mPreference != null) {
- mPreference.setProgress(position);
- }
- if (mMediaController == null) {
- return false;
- }
- mMediaController.setVolumeTo(position, 0);
- return true;
- }
-
- @Override
- public int getMax() {
- if (mPreference != null) {
- return mPreference.getMax();
- }
- if (mMediaController == null) {
- return 0;
- }
- final MediaController.PlaybackInfo playbackInfo = mMediaController.getPlaybackInfo();
- return playbackInfo != null ? playbackInfo.getMaxVolume() : 0;
- }
-
- @Override
- public int getMin() {
- if (mPreference != null) {
- return mPreference.getMin();
- }
- return 0;
- }
-
- @Override
- public boolean isSliceable() {
- return TextUtils.equals(getPreferenceKey(), KEY_REMOTE_VOLUME);
- }
-
- @Override
- public boolean isPublicSlice() {
- return true;
- }
-
- @Override
- public boolean useDynamicSliceSummary() {
- return true;
- }
-
- @Override
- public String getPreferenceKey() {
- return KEY_REMOTE_VOLUME;
- }
-
- @Override
- public int getAudioStream() {
- // This can be anything because remote volume controller doesn't rely on it.
- return REMOTE_VOLUME;
- }
-
- @Override
- public int getMuteIcon() {
- return R.drawable.ic_volume_remote_mute;
- }
-
- public static boolean isRemote(MediaController.PlaybackInfo pi) {
- return pi != null
- && pi.getPlaybackType() == MediaController.PlaybackInfo.PLAYBACK_TYPE_REMOTE;
- }
-
- @Override
- public Class<? extends SliceBackgroundWorker> getBackgroundWorkerClass() {
- return RemoteVolumeSliceWorker.class;
- }
-
- private void updatePreference(VolumeSeekBarPreference seekBarPreference,
- MediaSession.Token token, MediaController.PlaybackInfo playbackInfo) {
- if (seekBarPreference == null || token == null || playbackInfo == null) {
- return;
- }
-
- seekBarPreference.setMax(playbackInfo.getMaxVolume());
- seekBarPreference.setVisible(true);
- setSliderPosition(playbackInfo.getCurrentVolume());
- }
-
- private void updateToken(MediaSession.Token token) {
- mActiveToken = token;
- if (token != null) {
- mMediaController = new MediaController(mContext, mActiveToken);
- } else {
- mMediaController = null;
- }
- }
-
- /**
- * Listener for background change to remote volume, which listens callback
- * from {@code MediaSessions}
- */
- public static class RemoteVolumeSliceWorker extends SliceBackgroundWorker<Void> implements
- MediaSessions.Callbacks {
-
- private MediaSessions mMediaSessions;
-
- public RemoteVolumeSliceWorker(Context context, Uri uri) {
- super(context, uri);
- mMediaSessions = new MediaSessions(context, Looper.getMainLooper(), this);
- }
-
- @Override
- protected void onSlicePinned() {
- mMediaSessions.init();
- }
-
- @Override
- protected void onSliceUnpinned() {
- mMediaSessions.destroy();
- }
-
- @Override
- public void close() throws IOException {
- mMediaSessions = null;
- }
-
- @Override
- public void onRemoteUpdate(MediaSession.Token token, String name,
- MediaController.PlaybackInfo pi) {
- notifySliceChange();
- }
-
- @Override
- public void onRemoteRemoved(MediaSession.Token t) {
- notifySliceChange();
- }
-
- @Override
- public void onRemoteVolumeChanged(MediaSession.Token token, int flags) {
- notifySliceChange();
- }
- }
-}
diff --git a/src/com/android/settings/notification/SoundSettings.java b/src/com/android/settings/notification/SoundSettings.java
index 7d14691..ad11f55 100644
--- a/src/com/android/settings/notification/SoundSettings.java
+++ b/src/com/android/settings/notification/SoundSettings.java
@@ -179,7 +179,6 @@
volumeControllers.add(use(RingVolumePreferenceController.class));
volumeControllers.add(use(NotificationVolumePreferenceController.class));
volumeControllers.add(use(CallVolumePreferenceController.class));
- volumeControllers.add(use(RemoteVolumePreferenceController.class));
use(HandsFreeProfileOutputPreferenceController.class).setCallback(listPreference ->
onPreferenceDataChanged(listPreference));
@@ -190,6 +189,7 @@
controller.setCallback(mVolumeCallback);
getSettingsLifecycle().addObserver(controller);
}
+ getSettingsLifecycle().addObserver(use(RemoteVolumeGroupController.class));
}
// === Volumes ===
diff --git a/src/com/android/settings/security/ConfirmSimDeletionPreferenceController.java b/src/com/android/settings/security/ConfirmSimDeletionPreferenceController.java
new file mode 100644
index 0000000..f24d8db
--- /dev/null
+++ b/src/com/android/settings/security/ConfirmSimDeletionPreferenceController.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2020 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.app.KeyguardManager;
+import android.content.Context;
+import android.provider.Settings;
+
+import androidx.preference.Preference;
+import androidx.preference.TwoStatePreference;
+
+import com.android.settings.R;
+import com.android.settings.core.TogglePreferenceController;
+import com.android.settings.network.telephony.MobileNetworkUtils;
+
+/** Enable/disable user confirmation before deleting an eSim */
+public class ConfirmSimDeletionPreferenceController extends TogglePreferenceController {
+ public static final String KEY_CONFIRM_SIM_DELETION = "confirm_sim_deletion";
+ private boolean mConfirmationDefaultOn;
+
+ public ConfirmSimDeletionPreferenceController(Context context, String key) {
+ super(context, key);
+ mConfirmationDefaultOn =
+ context.getResources()
+ .getBoolean(R.bool.config_sim_deletion_confirmation_default_on);
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ // hide if eSim is not supported on the device
+ return MobileNetworkUtils.showEuiccSettings(mContext) ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
+ }
+
+ private boolean getGlobalState() {
+ return Settings.Global.getInt(
+ mContext.getContentResolver(),
+ KEY_CONFIRM_SIM_DELETION,
+ mConfirmationDefaultOn ? 1 : 0)
+ == 1;
+ }
+
+ @Override
+ public boolean isChecked() {
+ return getGlobalState();
+ }
+
+ @Override
+ public boolean setChecked(boolean isChecked) {
+ Settings.Global.putInt(
+ mContext.getContentResolver(), KEY_CONFIRM_SIM_DELETION, isChecked ? 1 : 0);
+ return true;
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+
+ final KeyguardManager keyguardManager = mContext.getSystemService(KeyguardManager.class);
+ if (!keyguardManager.isKeyguardSecure()) {
+ preference.setEnabled(false);
+ if (preference instanceof TwoStatePreference) {
+ ((TwoStatePreference) preference).setChecked(false);
+ }
+ preference.setSummary(R.string.disabled_because_no_backup_security);
+ } else {
+ preference.setEnabled(true);
+ if (preference instanceof TwoStatePreference) {
+ ((TwoStatePreference) preference).setChecked(getGlobalState());
+ }
+ preference.setSummary(R.string.confirm_sim_deletion_description);
+ }
+ }
+}
diff --git a/src/com/android/settings/security/SecuritySettings.java b/src/com/android/settings/security/SecuritySettings.java
index da8f003..effbd70 100644
--- a/src/com/android/settings/security/SecuritySettings.java
+++ b/src/com/android/settings/security/SecuritySettings.java
@@ -20,7 +20,6 @@
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.content.Intent;
-import android.provider.SearchIndexableResource;
import com.android.settings.R;
import com.android.settings.biometrics.face.FaceProfileStatusPreferenceController;
diff --git a/tests/robotests/src/com/android/settings/network/telephony/DeleteSimProfilePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/telephony/DeleteSimProfilePreferenceControllerTest.java
index ca8fcf8..401a92e 100644
--- a/tests/robotests/src/com/android/settings/network/telephony/DeleteSimProfilePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/network/telephony/DeleteSimProfilePreferenceControllerTest.java
@@ -25,6 +25,7 @@
import android.content.Context;
import android.content.Intent;
+import android.provider.Settings;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.euicc.EuiccManager;
@@ -34,6 +35,7 @@
import androidx.preference.PreferenceScreen;
import com.android.settings.network.SubscriptionUtil;
+import com.android.settings.security.ConfirmSimDeletionPreferenceController;
import org.junit.After;
import org.junit.Before;
@@ -118,7 +120,11 @@
public void onPreferenceClick_startsIntent() {
mController.init(SUB_ID, mFragment, REQUEST_CODE);
mController.displayPreference(mScreen);
- mPreference.performClick();
+ // turn off confirmation before click
+ Settings.Global.putInt(mContext.getContentResolver(),
+ ConfirmSimDeletionPreferenceController.KEY_CONFIRM_SIM_DELETION, 0);
+
+ mController.handlePreferenceTreeClick(mPreference);
final ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
verify(mFragment).startActivityForResult(intentCaptor.capture(), eq(REQUEST_CODE));
diff --git a/tests/robotests/src/com/android/settings/network/telephony/MobileNetworkSettingsTest.java b/tests/robotests/src/com/android/settings/network/telephony/MobileNetworkSettingsTest.java
index 9bf8370..a4c3672 100644
--- a/tests/robotests/src/com/android/settings/network/telephony/MobileNetworkSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/network/telephony/MobileNetworkSettingsTest.java
@@ -26,6 +26,7 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.app.Activity;
import android.app.usage.NetworkStatsManager;
import android.content.Context;
import android.net.NetworkPolicyManager;
@@ -111,12 +112,12 @@
public void onActivityResult_noActivity_noCrash() {
when(mFragment.getActivity()).thenReturn(null);
// this should not crash
- mFragment.onActivityResult(REQUEST_CODE_DELETE_SUBSCRIPTION, 0, null);
+ mFragment.onActivityResult(REQUEST_CODE_DELETE_SUBSCRIPTION, Activity.RESULT_OK, null);
}
@Test
public void onActivityResult_deleteSubscription_activityFinishes() {
- mFragment.onActivityResult(REQUEST_CODE_DELETE_SUBSCRIPTION, 0, null);
+ mFragment.onActivityResult(REQUEST_CODE_DELETE_SUBSCRIPTION, Activity.RESULT_OK, null);
verify(mActivity).finish();
}
diff --git a/tests/robotests/src/com/android/settings/notification/RemoteVolumePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/RemoteVolumePreferenceControllerTest.java
deleted file mode 100644
index 44fc04f..0000000
--- a/tests/robotests/src/com/android/settings/notification/RemoteVolumePreferenceControllerTest.java
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * Copyright (C) 2019 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.notification;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-import android.media.session.ISessionController;
-import android.media.session.MediaController;
-import android.media.session.MediaSession;
-import android.media.session.MediaSessionManager;
-
-import com.android.settings.R;
-import com.android.settings.core.BasePreferenceController;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Answers;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-
-import java.util.ArrayList;
-import java.util.List;
-
-@RunWith(RobolectricTestRunner.class)
-public class RemoteVolumePreferenceControllerTest {
- private static final int CURRENT_POS = 5;
- private static final int MAX_POS = 10;
-
- @Mock
- private MediaSessionManager mMediaSessionManager;
- @Mock
- private MediaController mMediaController;
- @Mock(answer = Answers.RETURNS_DEEP_STUBS)
- private ISessionController mStub;
- @Mock(answer = Answers.RETURNS_DEEP_STUBS)
- private ISessionController mStub2;
- private MediaSession.Token mToken;
- private MediaSession.Token mToken2;
- private RemoteVolumePreferenceController mController;
- private Context mContext;
- private List<MediaController> mActiveSessions;
- private MediaController.PlaybackInfo mPlaybackInfo;
-
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
-
- mContext = spy(RuntimeEnvironment.application);
- when(mContext.getSystemService(MediaSessionManager.class)).thenReturn(mMediaSessionManager);
- mActiveSessions = new ArrayList<>();
- mActiveSessions.add(mMediaController);
- when(mMediaSessionManager.getActiveSessions(null)).thenReturn(
- mActiveSessions);
- mToken = new MediaSession.Token(mStub);
- mToken2 = new MediaSession.Token(mStub2);
-
- mController = new RemoteVolumePreferenceController(mContext);
- mPlaybackInfo = new MediaController.PlaybackInfo(
- MediaController.PlaybackInfo.PLAYBACK_TYPE_REMOTE, 0, MAX_POS, CURRENT_POS, null);
- when(mMediaController.getPlaybackInfo()).thenReturn(mPlaybackInfo);
- when(mMediaController.getSessionToken()).thenReturn(mToken);
- }
-
- @Test
- public void getActiveRemoteToken_containRemoteMedia_returnToken() {
- when(mMediaController.getPlaybackInfo()).thenReturn(
- new MediaController.PlaybackInfo(MediaController.PlaybackInfo.PLAYBACK_TYPE_REMOTE,
- 0, 0, 0, null));
- assertThat(mController.getActiveRemoteToken(mContext)).isEqualTo(mToken);
- }
-
- @Test
- public void getActiveRemoteToken_noRemoteMedia_returnNull() {
- when(mMediaController.getPlaybackInfo()).thenReturn(
- new MediaController.PlaybackInfo(MediaController.PlaybackInfo.PLAYBACK_TYPE_LOCAL,
- 0, 0, 0, null));
- assertThat(mController.getActiveRemoteToken(mContext)).isNull();
- }
-
- @Test
- public void isAvailable_returnAvailableUnsearchable() {
- assertThat(mController.isAvailable()).isTrue();
- assertThat(mController.getAvailabilityStatus()).isEqualTo(
- BasePreferenceController.AVAILABLE_UNSEARCHABLE);
- }
-
- @Test
- public void getMuteIcon_returnMuteIcon() {
- assertThat(mController.getMuteIcon()).isEqualTo(R.drawable.ic_volume_remote_mute);
- }
-
- @Test
- public void getAudioStream_returnRemoteVolume() {
- assertThat(mController.getAudioStream()).isEqualTo(
- RemoteVolumePreferenceController.REMOTE_VOLUME);
- }
-
- @Test
- public void getSliderPosition_controllerNull_returnZero() {
- mController.mMediaController = null;
-
- assertThat(mController.getSliderPosition()).isEqualTo(0);
- }
-
- @Test
- public void getSliderPosition_controllerExists_returnValue() {
- mController.mMediaController = mMediaController;
-
- assertThat(mController.getSliderPosition()).isEqualTo(CURRENT_POS);
- }
-
- @Test
- public void getMinValue_controllerNull_returnZero() {
- mController.mMediaController = null;
-
- assertThat(mController.getMin()).isEqualTo(0);
- }
-
- @Test
- public void getMinValue_controllerExists_returnValue() {
- mController.mMediaController = mMediaController;
-
- assertThat(mController.getMin()).isEqualTo(0);
- }
-
- @Test
- public void getMaxValue_controllerNull_returnZero() {
- mController.mMediaController = null;
-
- assertThat(mController.getMax()).isEqualTo(0);
- }
-
- @Test
- public void getMaxValue_controllerExists_returnValue() {
- mController.mMediaController = mMediaController;
-
- assertThat(mController.getMax()).isEqualTo(MAX_POS);
- }
-
- @Test
- public void setSliderPosition_controllerNull_returnFalse() {
- mController.mMediaController = null;
-
- assertThat(mController.setSliderPosition(CURRENT_POS)).isFalse();
- }
-
- @Test
- public void setSliderPosition_controllerExists_returnTrue() {
- mController.mMediaController = mMediaController;
-
- assertThat(mController.setSliderPosition(CURRENT_POS)).isTrue();
- verify(mMediaController).setVolumeTo(CURRENT_POS, 0 /* flags */);
- }
-
- @Test
- public void onRemoteUpdate_firstToken_updateTokenAndPreference() {
- mController.mPreference = new VolumeSeekBarPreference(mContext);
- mController.mActiveToken = null;
-
- mController.mCallbacks.onRemoteUpdate(mToken, "token", mPlaybackInfo);
-
- assertThat(mController.mActiveToken).isEqualTo(mToken);
- assertThat(mController.mPreference.isVisible()).isTrue();
- assertThat(mController.mPreference.getMax()).isEqualTo(MAX_POS);
- assertThat(mController.mPreference.getProgress()).isEqualTo(CURRENT_POS);
- }
-
- @Test
- public void onRemoteUpdate_differentToken_doNothing() {
- mController.mActiveToken = mToken;
-
- mController.mCallbacks.onRemoteUpdate(mToken2, "token2", mPlaybackInfo);
-
- assertThat(mController.mActiveToken).isEqualTo(mToken);
- }
-
- @Test
- public void onRemoteRemoved_tokenRemoved_setInvisible() {
- mController.mPreference = new VolumeSeekBarPreference(mContext);
- mController.mActiveToken = mToken;
-
- mController.mCallbacks.onRemoteRemoved(mToken);
-
- assertThat(mController.mActiveToken).isNull();
- assertThat(mController.mPreference.isVisible()).isFalse();
- }
-
- @Test
- public void onRemoteVolumeChanged_volumeChanged_updateIt() {
- mController.mPreference = new VolumeSeekBarPreference(mContext);
- mController.mPreference.setMax(MAX_POS);
- mController.mActiveToken = mToken;
- mController.mMediaController = mMediaController;
-
- mController.mCallbacks.onRemoteVolumeChanged(mToken, 0 /* flags */);
-
- assertThat(mController.mPreference.getProgress()).isEqualTo(CURRENT_POS);
- }
-
- @Test
- public void isPublicSlice_returnTrue() {
- assertThat(mController.isPublicSlice()).isTrue();
- }
-}
diff --git a/tests/robotests/src/com/android/settings/notification/SoundSettingsTest.java b/tests/robotests/src/com/android/settings/notification/SoundSettingsTest.java
index 56d0828..b6f06f4 100644
--- a/tests/robotests/src/com/android/settings/notification/SoundSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/notification/SoundSettingsTest.java
@@ -25,13 +25,13 @@
import android.content.Context;
import android.media.AudioManager;
-import android.os.Handler;
import android.os.UserManager;
import android.preference.SeekBarVolumizer;
import com.android.settings.R;
import com.android.settings.testutils.XmlTestUtils;
import com.android.settings.testutils.shadow.ShadowAudioHelper;
+import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
import com.android.settings.testutils.shadow.ShadowDeviceConfig;
import com.android.settings.testutils.shadow.ShadowUserManager;
@@ -48,7 +48,8 @@
public class SoundSettingsTest {
@Test
- @Config(shadows = {ShadowUserManager.class, ShadowAudioHelper.class, ShadowDeviceConfig.class})
+ @Config(shadows = {ShadowUserManager.class, ShadowAudioHelper.class, ShadowDeviceConfig.class,
+ ShadowBluetoothAdapter.class})
public void getNonIndexableKeys_existInXmlLayout() {
final Context context = spy(RuntimeEnvironment.application);
AudioManager audioManager = mock(AudioManager.class);