From 9ba74049fc08851003da788c7af1337f1a83eb54 Mon Sep 17 00:00:00 2001 From: Tim Peng Date: Mon, 21 Dec 2020 16:29:05 +0800 Subject: [PATCH 01/23] Add the explicitly mutable flag for creating a PendingIntent in MediaOutputSlice Bug: 175124820 Test: make -j50 RunSettingsRoboTests Merged-In: Ic37b37bdbe6de6bdbad741985d3a920334240d80 Change-Id: I49bc2f1fe903422e08ef3b98993f1b60df458d9c --- src/com/android/settings/media/MediaOutputSlice.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/com/android/settings/media/MediaOutputSlice.java b/src/com/android/settings/media/MediaOutputSlice.java index 2cc7a49b4e6..ae7e0e80a50 100644 --- a/src/com/android/settings/media/MediaOutputSlice.java +++ b/src/com/android/settings/media/MediaOutputSlice.java @@ -147,7 +147,8 @@ public class MediaOutputSlice implements CustomSliceable { .setSourceMetricsCategory(SettingsEnums.PANEL_MEDIA_OUTPUT) .toIntent(); final SliceAction primarySliceAction = SliceAction.createDeeplink( - PendingIntent.getActivity(mContext, 0 /* requestCode */, intent, 0 /* flags */), + PendingIntent.getActivity(mContext, 0 /* requestCode */, intent, + PendingIntent.FLAG_IMMUTABLE), IconCompat.createWithResource(mContext, R.drawable.ic_add_24dp/*ic_add_blue_24dp*/), ListBuilder.ICON_IMAGE, mContext.getText(R.string.bluetooth_pairing_pref_title)); @@ -248,7 +249,8 @@ public class MediaOutputSlice implements CustomSliceable { .putExtra(MEDIA_DEVICE_ID, id) .setClass(mContext, SliceBroadcastReceiver.class); - return PendingIntent.getBroadcast(mContext, requestCode, intent, 0); + return PendingIntent.getBroadcast(mContext, requestCode, intent, + PendingIntent.FLAG_IMMUTABLE); } private SliceAction getEndItemSliceAction() { @@ -261,7 +263,8 @@ public class MediaOutputSlice implements CustomSliceable { ? 0 : getWorker().getPackageName().hashCode(); return SliceAction.createDeeplink( - PendingIntent.getActivity(mContext, requestCode, intent, 0 /* flags */), + PendingIntent.getActivity(mContext, requestCode, intent, + PendingIntent.FLAG_IMMUTABLE), IconCompat.createWithResource(mContext, R.drawable.ic_add_blue_24dp), ListBuilder.ICON_IMAGE, mContext.getText(R.string.add)); @@ -350,7 +353,7 @@ public class MediaOutputSlice implements CustomSliceable { intent.putExtra(MEDIA_DEVICE_ID, id); intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); return PendingIntent.getBroadcast(context, requestCode, intent, - PendingIntent.FLAG_UPDATE_CURRENT); + PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE); } @Override From 58b0f2d5b3ab4e7002b870aedc971a2d8d9e8e44 Mon Sep 17 00:00:00 2001 From: Weng Su Date: Fri, 29 Jan 2021 17:24:51 +0800 Subject: [PATCH 02/23] [Security Report] Fix Settings WifiScanModeActivity Overlaid issue - Disallowed non system overlay windows - Screenshot https://screenshot.googleplex.com/77fJ9QN6pV4zFYc Bug: 174047492 Test: manual test Merged-In: Ia7acad6d456ce5ebea2d982d4cb063d4f28cbfff Change-Id: Ia7acad6d456ce5ebea2d982d4cb063d4f28cbfff (cherry picked from commit d47d8e4fc5959ea5cc57dc074d572a81ec6ddcb0) --- src/com/android/settings/wifi/WifiScanModeActivity.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/com/android/settings/wifi/WifiScanModeActivity.java b/src/com/android/settings/wifi/WifiScanModeActivity.java index 024dc104125..9d502810d5a 100644 --- a/src/com/android/settings/wifi/WifiScanModeActivity.java +++ b/src/com/android/settings/wifi/WifiScanModeActivity.java @@ -25,6 +25,7 @@ import android.content.pm.PackageManager; import android.net.wifi.WifiManager; import android.os.Bundle; import android.text.TextUtils; +import android.view.WindowManager; import androidx.appcompat.app.AlertDialog; import androidx.fragment.app.DialogFragment; @@ -43,6 +44,8 @@ public class WifiScanModeActivity extends FragmentActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + getWindow().addSystemFlags( + WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS); Intent intent = getIntent(); if (savedInstanceState == null) { if (intent != null && WifiManager.ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE From faa5f6b5f6b67421f1327690f358f2fc5ee12c33 Mon Sep 17 00:00:00 2001 From: Weng Su Date: Fri, 29 Jan 2021 17:24:51 +0800 Subject: [PATCH 03/23] [Security Report] Fix Settings WifiScanModeActivity Overlaid issue - Disallowed non system overlay windows - Screenshot https://screenshot.googleplex.com/77fJ9QN6pV4zFYc Bug: 174047492 Test: manual test Merged-In: Ia7acad6d456ce5ebea2d982d4cb063d4f28cbfff Change-Id: Ia7acad6d456ce5ebea2d982d4cb063d4f28cbfff (cherry picked from commit d47d8e4fc5959ea5cc57dc074d572a81ec6ddcb0) --- src/com/android/settings/wifi/WifiScanModeActivity.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/com/android/settings/wifi/WifiScanModeActivity.java b/src/com/android/settings/wifi/WifiScanModeActivity.java index 53427299df1..33cedde7c4b 100644 --- a/src/com/android/settings/wifi/WifiScanModeActivity.java +++ b/src/com/android/settings/wifi/WifiScanModeActivity.java @@ -26,6 +26,7 @@ import android.net.wifi.WifiManager; import android.os.Bundle; import android.provider.Settings; import android.text.TextUtils; +import android.view.WindowManager; import androidx.appcompat.app.AlertDialog; import androidx.fragment.app.DialogFragment; @@ -44,6 +45,8 @@ public class WifiScanModeActivity extends FragmentActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + getWindow().addSystemFlags( + WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS); Intent intent = getIntent(); if (savedInstanceState == null) { if (intent != null && intent.getAction() From 32d5d3a3a34fae28410a77b058f75371d15019e6 Mon Sep 17 00:00:00 2001 From: Weng Su Date: Fri, 29 Jan 2021 17:24:51 +0800 Subject: [PATCH 04/23] [Security Report] Fix Settings WifiScanModeActivity Overlaid issue - Disallowed non system overlay windows - Screenshot https://screenshot.googleplex.com/77fJ9QN6pV4zFYc Bug: 174047492 Test: manual test Merged-In: Ia7acad6d456ce5ebea2d982d4cb063d4f28cbfff Change-Id: Ia7acad6d456ce5ebea2d982d4cb063d4f28cbfff (cherry picked from commit d47d8e4fc5959ea5cc57dc074d572a81ec6ddcb0) --- src/com/android/settings/wifi/WifiScanModeActivity.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/com/android/settings/wifi/WifiScanModeActivity.java b/src/com/android/settings/wifi/WifiScanModeActivity.java index 2c0d0d5713d..7b4fa7a91c2 100644 --- a/src/com/android/settings/wifi/WifiScanModeActivity.java +++ b/src/com/android/settings/wifi/WifiScanModeActivity.java @@ -27,6 +27,7 @@ import android.content.pm.PackageManager; import android.net.wifi.WifiManager; import android.os.Bundle; import android.provider.Settings; +import android.view.WindowManager; import com.android.internal.logging.nano.MetricsProto; import com.android.settings.R; @@ -42,6 +43,8 @@ public class WifiScanModeActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + getWindow().addSystemFlags( + WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS); Intent intent = getIntent(); if (savedInstanceState == null) { if (intent != null && intent.getAction() From 05d6fa9bcb90886ac2611f86bb7d2af7078eb3ad Mon Sep 17 00:00:00 2001 From: Weng Su Date: Fri, 29 Jan 2021 17:24:51 +0800 Subject: [PATCH 05/23] [Security Report] Fix Settings WifiScanModeActivity Overlaid issue - Disallowed non system overlay windows - Screenshot https://screenshot.googleplex.com/77fJ9QN6pV4zFYc Bug: 174047492 Test: manual test Merged-In: Ia7acad6d456ce5ebea2d982d4cb063d4f28cbfff Change-Id: Ia7acad6d456ce5ebea2d982d4cb063d4f28cbfff (cherry picked from commit d47d8e4fc5959ea5cc57dc074d572a81ec6ddcb0) --- src/com/android/settings/wifi/WifiScanModeActivity.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/com/android/settings/wifi/WifiScanModeActivity.java b/src/com/android/settings/wifi/WifiScanModeActivity.java index 53427299df1..33cedde7c4b 100644 --- a/src/com/android/settings/wifi/WifiScanModeActivity.java +++ b/src/com/android/settings/wifi/WifiScanModeActivity.java @@ -26,6 +26,7 @@ import android.net.wifi.WifiManager; import android.os.Bundle; import android.provider.Settings; import android.text.TextUtils; +import android.view.WindowManager; import androidx.appcompat.app.AlertDialog; import androidx.fragment.app.DialogFragment; @@ -44,6 +45,8 @@ public class WifiScanModeActivity extends FragmentActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + getWindow().addSystemFlags( + WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS); Intent intent = getIntent(); if (savedInstanceState == null) { if (intent != null && intent.getAction() From ea29704e402a41ee133af188e4b2af3a8e842819 Mon Sep 17 00:00:00 2001 From: Zoey Chen Date: Mon, 22 Feb 2021 21:25:43 +0800 Subject: [PATCH 06/23] [Telephony] Use TelephonyCallback instead of PhoneStateListener part5 Since the redesign of PhoneStateListener, use TelephonyCallback to get the callback of EVENT_* Bug: 167684594 Test: make and atest NetworkProviderWorkerTest Change-Id: I52af54045872bbf13e64d5d94c8b027ec702abb9 --- .../network/AllowedNetworkTypesListener.java | 17 +++++++------- ...nabledNetworkModePreferenceController.java | 2 +- .../NetworkPreferenceCategoryController.java | 2 +- .../telephony/NetworkProviderWorker.java | 22 +++++++++---------- .../cdma/CdmaBasePreferenceController.java | 2 +- .../gsm/AutoSelectPreferenceController.java | 2 +- ...NetworkSelectPagePreferenceController.java | 2 +- .../AllowedNetworkTypesListenerTest.java | 10 ++++----- .../telephony/NetworkProviderWorkerTest.java | 12 +++++----- 9 files changed, 36 insertions(+), 35 deletions(-) diff --git a/src/com/android/settings/network/AllowedNetworkTypesListener.java b/src/com/android/settings/network/AllowedNetworkTypesListener.java index a11f3b41301..a9ed8be7327 100644 --- a/src/com/android/settings/network/AllowedNetworkTypesListener.java +++ b/src/com/android/settings/network/AllowedNetworkTypesListener.java @@ -18,6 +18,7 @@ package com.android.settings.network; import android.content.Context; import android.telephony.PhoneStateListener; +import android.telephony.TelephonyCallback; import android.telephony.TelephonyManager; import android.util.Log; @@ -28,14 +29,14 @@ import java.util.concurrent.Executor; /** - * {@link PhoneStateListener} to listen to Allowed Network Types changed + * {@link TelephonyCallback} to listen to Allowed Network Types changed */ -public class AllowedNetworkTypesListener extends PhoneStateListener implements - PhoneStateListener.AllowedNetworkTypesChangedListener { +public class AllowedNetworkTypesListener extends TelephonyCallback implements + TelephonyCallback.AllowedNetworkTypesListener { private static final String LOG_TAG = "NetworkModeListener"; @VisibleForTesting - AllowedNetworkTypesListener.OnAllowedNetworkTypesChangedListener mListener; + OnAllowedNetworkTypesListener mListener; private long mAllowedNetworkType = -1; private Executor mExecutor; @@ -44,7 +45,7 @@ public class AllowedNetworkTypesListener extends PhoneStateListener implements mExecutor = executor; } - public void setAllowedNetworkTypesChangedListener(OnAllowedNetworkTypesChangedListener lsn) { + public void setAllowedNetworkTypesListener(OnAllowedNetworkTypesListener lsn) { mListener = lsn; } @@ -56,7 +57,7 @@ public class AllowedNetworkTypesListener extends PhoneStateListener implements public void register(Context context, int subId) { TelephonyManager telephonyManager = context.getSystemService( TelephonyManager.class).createForSubscriptionId(subId); - telephonyManager.registerPhoneStateListener(mExecutor, this); + telephonyManager.registerTelephonyCallback(mExecutor, this); } /** @@ -67,7 +68,7 @@ public class AllowedNetworkTypesListener extends PhoneStateListener implements public void unregister(Context context, int subId) { TelephonyManager telephonyManager = context.getSystemService( TelephonyManager.class).createForSubscriptionId(subId); - telephonyManager.unregisterPhoneStateListener(this); + telephonyManager.unregisterTelephonyCallback(this); } @Override @@ -84,7 +85,7 @@ public class AllowedNetworkTypesListener extends PhoneStateListener implements /** * Listener for update of Preferred Network Mode change */ - public interface OnAllowedNetworkTypesChangedListener { + public interface OnAllowedNetworkTypesListener { /** * Notify the allowed network type changed. */ diff --git a/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java b/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java index 5680bf60140..f0d4a431c0b 100644 --- a/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java +++ b/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java @@ -151,7 +151,7 @@ public class EnabledNetworkModePreferenceController extends if (mAllowedNetworkTypesListener == null) { mAllowedNetworkTypesListener = new AllowedNetworkTypesListener( mContext.getMainExecutor()); - mAllowedNetworkTypesListener.setAllowedNetworkTypesChangedListener( + mAllowedNetworkTypesListener.setAllowedNetworkTypesListener( () -> updatePreference()); } diff --git a/src/com/android/settings/network/telephony/NetworkPreferenceCategoryController.java b/src/com/android/settings/network/telephony/NetworkPreferenceCategoryController.java index 25651f5379e..4ebcb7a59d6 100644 --- a/src/com/android/settings/network/telephony/NetworkPreferenceCategoryController.java +++ b/src/com/android/settings/network/telephony/NetworkPreferenceCategoryController.java @@ -45,7 +45,7 @@ public class NetworkPreferenceCategoryController extends PreferenceCategoryContr mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; mAllowedNetworkTypesListener = new AllowedNetworkTypesListener( context.getMainExecutor()); - mAllowedNetworkTypesListener.setAllowedNetworkTypesChangedListener( + mAllowedNetworkTypesListener.setAllowedNetworkTypesListener( () -> updatePreference()); } diff --git a/src/com/android/settings/network/telephony/NetworkProviderWorker.java b/src/com/android/settings/network/telephony/NetworkProviderWorker.java index 50c56cf659f..50293cb5c05 100644 --- a/src/com/android/settings/network/telephony/NetworkProviderWorker.java +++ b/src/com/android/settings/network/telephony/NetworkProviderWorker.java @@ -25,9 +25,9 @@ import android.database.ContentObserver; import android.net.Uri; import android.os.Handler; import android.os.Looper; -import android.telephony.PhoneStateListener; import android.telephony.ServiceState; import android.telephony.SubscriptionManager; +import android.telephony.TelephonyCallback; import android.telephony.TelephonyDisplayInfo; import android.telephony.TelephonyManager; import android.util.Log; @@ -63,7 +63,7 @@ public class NetworkProviderWorker extends WifiScanWorker implements private final Context mContext; final Handler mHandler; @VisibleForTesting - final PhoneStateListener mPhoneStateListener; + final NetworkProviderTelephonyCallback mTelephonyCallback; private TelephonyManager mTelephonyManager; private Config mConfig = null; private TelephonyDisplayInfo mTelephonyDisplayInfo = @@ -83,7 +83,7 @@ public class NetworkProviderWorker extends WifiScanWorker implements mTelephonyManager = mContext.getSystemService( TelephonyManager.class).createForSubscriptionId(mDefaultDataSubid); - mPhoneStateListener = new NetworkProviderPhoneStateListener(); + mTelephonyCallback = new NetworkProviderTelephonyCallback(); mSubscriptionsListener = new SubscriptionsChangeListener(context, this); mDataEnabledListener = new MobileDataEnabledListener(context, this); mConnectivityListener = new DataConnectivityListener(context, this); @@ -101,7 +101,7 @@ public class NetworkProviderWorker extends WifiScanWorker implements mDataEnabledListener.start(mDefaultDataSubid); mConnectivityListener.start(); mSignalStrengthListener.resume(); - mTelephonyManager.registerPhoneStateListener(mHandler::post, mPhoneStateListener); + mTelephonyManager.registerTelephonyCallback(mHandler::post, mTelephonyCallback); super.onSlicePinned(); } @@ -112,7 +112,7 @@ public class NetworkProviderWorker extends WifiScanWorker implements mDataEnabledListener.stop(); mConnectivityListener.stop(); mSignalStrengthListener.pause(); - mTelephonyManager.unregisterPhoneStateListener(mPhoneStateListener); + mTelephonyManager.unregisterTelephonyCallback(mTelephonyCallback); super.onSliceUnpinned(); } @@ -142,12 +142,12 @@ public class NetworkProviderWorker extends WifiScanWorker implements return; } if (SubscriptionManager.isUsableSubscriptionId(defaultDataSubId)) { - mTelephonyManager.unregisterPhoneStateListener(mPhoneStateListener); + mTelephonyManager.unregisterTelephonyCallback(mTelephonyCallback); mMobileDataObserver.unregister(mContext); mSignalStrengthListener.updateSubscriptionIds(Collections.singleton(defaultDataSubId)); mTelephonyManager = mTelephonyManager.createForSubscriptionId(defaultDataSubId); - mTelephonyManager.registerPhoneStateListener(mHandler::post, mPhoneStateListener); + mTelephonyManager.registerTelephonyCallback(mHandler::post, mTelephonyCallback); mMobileDataObserver.register(mContext, mDefaultDataSubid); mConfig = getConfig(mContext); } else { @@ -217,10 +217,10 @@ public class NetworkProviderWorker extends WifiScanWorker implements } } - class NetworkProviderPhoneStateListener extends PhoneStateListener implements - PhoneStateListener.DataConnectionStateChangedListener, - PhoneStateListener.DisplayInfoChangedListener, - PhoneStateListener.ServiceStateChangedListener { + class NetworkProviderTelephonyCallback extends TelephonyCallback implements + TelephonyCallback.DataConnectionStateListener, + TelephonyCallback.DisplayInfoListener, + TelephonyCallback.ServiceStateListener { @Override public void onServiceStateChanged(ServiceState state) { Log.d(TAG, "onServiceStateChanged voiceState=" + state.getState() diff --git a/src/com/android/settings/network/telephony/cdma/CdmaBasePreferenceController.java b/src/com/android/settings/network/telephony/cdma/CdmaBasePreferenceController.java index 06c3edb8478..4d1d319027c 100644 --- a/src/com/android/settings/network/telephony/cdma/CdmaBasePreferenceController.java +++ b/src/com/android/settings/network/telephony/cdma/CdmaBasePreferenceController.java @@ -77,7 +77,7 @@ public abstract class CdmaBasePreferenceController extends TelephonyBasePreferen if (mAllowedNetworkTypesListener == null) { mAllowedNetworkTypesListener = new AllowedNetworkTypesListener( mContext.getMainExecutor()); - mAllowedNetworkTypesListener.setAllowedNetworkTypesChangedListener( + mAllowedNetworkTypesListener.setAllowedNetworkTypesListener( () -> updatePreference()); } } diff --git a/src/com/android/settings/network/telephony/gsm/AutoSelectPreferenceController.java b/src/com/android/settings/network/telephony/gsm/AutoSelectPreferenceController.java index 19302daec3e..997235c8a0c 100644 --- a/src/com/android/settings/network/telephony/gsm/AutoSelectPreferenceController.java +++ b/src/com/android/settings/network/telephony/gsm/AutoSelectPreferenceController.java @@ -81,7 +81,7 @@ public class AutoSelectPreferenceController extends TelephonyTogglePreferenceCon mUiHandler = new Handler(Looper.getMainLooper()); mAllowedNetworkTypesListener = new AllowedNetworkTypesListener( new HandlerExecutor(mUiHandler)); - mAllowedNetworkTypesListener.setAllowedNetworkTypesChangedListener( + mAllowedNetworkTypesListener.setAllowedNetworkTypesListener( () -> updatePreference()); } diff --git a/src/com/android/settings/network/telephony/gsm/OpenNetworkSelectPagePreferenceController.java b/src/com/android/settings/network/telephony/gsm/OpenNetworkSelectPagePreferenceController.java index 1b77c6dd309..cdeb1e58fb9 100644 --- a/src/com/android/settings/network/telephony/gsm/OpenNetworkSelectPagePreferenceController.java +++ b/src/com/android/settings/network/telephony/gsm/OpenNetworkSelectPagePreferenceController.java @@ -60,7 +60,7 @@ public class OpenNetworkSelectPagePreferenceController extends mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; mAllowedNetworkTypesListener = new AllowedNetworkTypesListener( context.getMainExecutor()); - mAllowedNetworkTypesListener.setAllowedNetworkTypesChangedListener( + mAllowedNetworkTypesListener.setAllowedNetworkTypesListener( () -> updatePreference()); } diff --git a/tests/unit/src/com/android/settings/network/AllowedNetworkTypesListenerTest.java b/tests/unit/src/com/android/settings/network/AllowedNetworkTypesListenerTest.java index 3387368e64a..d8f3c783fe7 100644 --- a/tests/unit/src/com/android/settings/network/AllowedNetworkTypesListenerTest.java +++ b/tests/unit/src/com/android/settings/network/AllowedNetworkTypesListenerTest.java @@ -25,8 +25,8 @@ import static org.mockito.Mockito.when; import android.content.Context; import android.os.HandlerExecutor; -import android.telephony.PhoneStateListener; import android.telephony.RadioAccessFamily; +import android.telephony.TelephonyCallback; import android.telephony.TelephonyManager; import android.test.mock.MockContentResolver; @@ -53,7 +53,7 @@ public class AllowedNetworkTypesListenerTest { private AllowedNetworkTypesListener mAllowedNetworkTypesListener; @Mock - private AllowedNetworkTypesListener.OnAllowedNetworkTypesChangedListener mListener; + private AllowedNetworkTypesListener.OnAllowedNetworkTypesListener mListener; @Mock private TelephonyManager mTelephonyManager; @@ -87,15 +87,15 @@ public class AllowedNetworkTypesListenerTest { public void register_shouldRegisterContentObserver() { mAllowedNetworkTypesListener.register(mContext, SUB_ID); - verify(mTelephonyManager, times(1)).registerPhoneStateListener(any(HandlerExecutor.class), - any(PhoneStateListener.class)); + verify(mTelephonyManager, times(1)).registerTelephonyCallback(any(HandlerExecutor.class), + any(TelephonyCallback.class)); } @Test public void unregister_shouldUnregisterContentObserver() { mAllowedNetworkTypesListener.unregister(mContext, SUB_ID); - verify(mTelephonyManager).unregisterPhoneStateListener( + verify(mTelephonyManager).unregisterTelephonyCallback( mAllowedNetworkTypesListener); } } diff --git a/tests/unit/src/com/android/settings/network/telephony/NetworkProviderWorkerTest.java b/tests/unit/src/com/android/settings/network/telephony/NetworkProviderWorkerTest.java index 2ce9a513daf..97f8e11f796 100644 --- a/tests/unit/src/com/android/settings/network/telephony/NetworkProviderWorkerTest.java +++ b/tests/unit/src/com/android/settings/network/telephony/NetworkProviderWorkerTest.java @@ -207,22 +207,22 @@ public class NetworkProviderWorkerTest { @Test @UiThreadTest - public void onServiceStateChanged_notifyPhoneStateListener_callUpdateSlice() { + public void onServiceStateChanged_notifyTelephonyCallback_callUpdateSlice() { mMockNetworkProviderWorker.onSlicePinned(); mMockNetworkProviderWorker.receiveNotification(false); - mMockNetworkProviderWorker.mPhoneStateListener.onServiceStateChanged(new ServiceState()); + mMockNetworkProviderWorker.mTelephonyCallback.onServiceStateChanged(new ServiceState()); assertThat(mMockNetworkProviderWorker.hasNotification()).isTrue(); } @Test @UiThreadTest - public void onDisplayInfoChanged_notifyPhoneStateListener_callUpdateSlice() { + public void onDisplayInfoChanged_notifyTelephonyCallback_callUpdateSlice() { mMockNetworkProviderWorker.onSlicePinned(); mMockNetworkProviderWorker.receiveNotification(false); - mMockNetworkProviderWorker.mPhoneStateListener.onDisplayInfoChanged( + mMockNetworkProviderWorker.mTelephonyCallback.onDisplayInfoChanged( new TelephonyDisplayInfo(14, 0)); assertThat(mMockNetworkProviderWorker.hasNotification()).isTrue(); @@ -230,11 +230,11 @@ public class NetworkProviderWorkerTest { @Test @UiThreadTest - public void onDataConnectionStateChanged_notifyPhoneStateListener_callUpdateSlice() { + public void onDataConnectionStateChanged_notifyTelephonyCallback_callUpdateSlice() { mMockNetworkProviderWorker.onSlicePinned(); mMockNetworkProviderWorker.receiveNotification(false); - mMockNetworkProviderWorker.mPhoneStateListener.onDataConnectionStateChanged( + mMockNetworkProviderWorker.mTelephonyCallback.onDataConnectionStateChanged( TelephonyManager.DATA_DISCONNECTED, TelephonyManager.NETWORK_TYPE_LTE); assertThat(mMockNetworkProviderWorker.hasNotification()).isTrue(); From e92bcb3287f28a9a2a598b8b0361ae80a2fe2627 Mon Sep 17 00:00:00 2001 From: Janis Danisevskis Date: Mon, 25 Jan 2021 14:56:47 -0800 Subject: [PATCH 07/23] Keystore 2.0: Update Wifi settings to use mostly public keystore API. Test: N/A Bug: 171305607 Bug: 171305388 Merged-In: Ib794c5f2d904c2b187d7d5fd00b81afc852d0052 Change-Id: Ib794c5f2d904c2b187d7d5fd00b81afc852d0052 --- .../utils/AndroidKeystoreAliasLoader.java | 123 ++++++++++++++++++ .../settings/wifi/WifiConfigController.java | 33 +++-- .../settings/wifi/WifiConfigController2.java | 32 +++-- .../wifi/WifiConfigController2Test.java | 42 ++---- .../wifi/WifiConfigControllerTest.java | 26 +--- 5 files changed, 167 insertions(+), 89 deletions(-) create mode 100644 src/com/android/settings/utils/AndroidKeystoreAliasLoader.java diff --git a/src/com/android/settings/utils/AndroidKeystoreAliasLoader.java b/src/com/android/settings/utils/AndroidKeystoreAliasLoader.java new file mode 100644 index 00000000000..b9ccf291b74 --- /dev/null +++ b/src/com/android/settings/utils/AndroidKeystoreAliasLoader.java @@ -0,0 +1,123 @@ +/* + * 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.utils; + +import android.os.Process; +import android.security.keystore.AndroidKeyStoreProvider; +import android.security.keystore.KeyProperties; +import android.security.keystore2.AndroidKeyStoreLoadStoreParameter; +import android.util.Log; + +import java.security.Key; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.UnrecoverableKeyException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Enumeration; + +/** + * This class provides a portable and unified way to load the content of AndroidKeyStore through + * public API. + * @hide + */ +public class AndroidKeystoreAliasLoader { + private static final String TAG = "SettingsKeystoreUtils"; + + private final Collection mKeyCertAliases; + private final Collection mCaCertAliases; + /** + * This Constructor loads all aliases of asymmetric key pairs and certificates in the + * AndroidKeyStore within the given namespace. + * Viable namespaces are {@link KeyProperties#NAMESPACE_WIFI}, + * {@link KeyProperties#NAMESPACE_APPLICATION}, or null. The latter two are equivalent in + * that they will load the keystore content of the app's own namespace. In case of settings, + * this is the namespace of the AID_SYSTEM. + * + * @param namespace {@link KeyProperties#NAMESPACE_WIFI}, + * {@link KeyProperties#NAMESPACE_APPLICATION}, or null + * @hide + */ + public AndroidKeystoreAliasLoader(Integer namespace) { + mKeyCertAliases = new ArrayList<>(); + mCaCertAliases = new ArrayList<>(); + KeyStore keyStore = null; + final Enumeration aliases; + try { + if (namespace != null && namespace != KeyProperties.NAMESPACE_APPLICATION) { + if (AndroidKeyStoreProvider.isKeystore2Enabled()) { + keyStore = KeyStore.getInstance("AndroidKeyStore"); + keyStore.load(new AndroidKeyStoreLoadStoreParameter(namespace)); + } else { + // In the legacy case we pass in the WIFI UID because that is the only + // possible special namespace that existed as of this writing, + // and new namespaces must only be added using the new mechanism. + keyStore = AndroidKeyStoreProvider.getKeyStoreForUid(Process.WIFI_UID); + } + } else { + keyStore = KeyStore.getInstance("AndroidKeyStore"); + keyStore.load(null); + } + aliases = keyStore.aliases(); + } catch (Exception e) { + Log.e(TAG, "Failed to open Android Keystore.", e); + // Will return empty lists. + return; + } + + while (aliases.hasMoreElements()) { + final String alias = aliases.nextElement(); + try { + final Key key = keyStore.getKey(alias, null); + if (key != null) { + if (key instanceof PrivateKey) { + mKeyCertAliases.add(alias); + } + } else { + if (keyStore.getCertificate(alias) != null) { + mCaCertAliases.add(alias); + } + } + } catch (KeyStoreException | NoSuchAlgorithmException | UnrecoverableKeyException e) { + Log.e(TAG, "Failed to load alias: " + + alias + " from Android Keystore. Ignoring.", e); + } + } + } + + /** + * Returns the aliases of the key pairs and certificates stored in the Android KeyStore at the + * time the constructor was called. + * @return Collection of keystore aliases. + * @hide + */ + public Collection getKeyCertAliases() { + return mKeyCertAliases; + } + + /** + * Returns the aliases of the trusted certificates stored in the Android KeyStore at the + * time the constructor was called. + * @return Collection of keystore aliases. + * @hide + */ + public Collection getCaCertAliases() { + return mCaCertAliases; + } +} diff --git a/src/com/android/settings/wifi/WifiConfigController.java b/src/com/android/settings/wifi/WifiConfigController.java index d0b5a4094b2..6e96ae2fefa 100644 --- a/src/com/android/settings/wifi/WifiConfigController.java +++ b/src/com/android/settings/wifi/WifiConfigController.java @@ -35,8 +35,7 @@ import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.os.IBinder; import android.os.UserManager; -import android.security.Credentials; -import android.security.KeyStore; +import android.security.keystore.KeyProperties; import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.text.Editable; @@ -73,6 +72,7 @@ import com.android.net.module.util.NetUtils; import com.android.net.module.util.ProxyUtils; import com.android.settings.ProxySelector; import com.android.settings.R; +import com.android.settings.utils.AndroidKeystoreAliasLoader; import com.android.settings.wifi.details.WifiPrivacyPreferenceController; import com.android.settings.wifi.details2.WifiPrivacyPreferenceController2; import com.android.settings.wifi.dpp.WifiDppUtils; @@ -83,7 +83,7 @@ import com.android.settingslib.wifi.AccessPoint; import java.net.Inet4Address; import java.net.InetAddress; import java.util.ArrayList; -import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.List; @@ -1051,15 +1051,17 @@ public class WifiConfigController implements TextWatcher, if (refreshCertificates) { loadSims(); + final AndroidKeystoreAliasLoader androidKeystoreAliasLoader = + getAndroidKeystoreAliasLoader(); loadCertificates( mEapCaCertSpinner, - Credentials.CA_CERTIFICATE, + androidKeystoreAliasLoader.getCaCertAliases(), null /* noCertificateString */, false /* showMultipleCerts */, true /* showUsePreinstalledCertOption */); loadCertificates( mEapUserCertSpinner, - Credentials.USER_PRIVATE_KEY, + androidKeystoreAliasLoader.getKeyCertAliases(), mDoNotProvideEapUserCertString, false /* showMultipleCerts */, false /* showUsePreinstalledCertOption */); @@ -1142,10 +1144,13 @@ public class WifiConfigController implements TextWatcher, } else if (caCerts.length == 1) { setSelection(mEapCaCertSpinner, caCerts[0]); } else { + final AndroidKeystoreAliasLoader androidKeystoreAliasLoader = + getAndroidKeystoreAliasLoader(); + // Reload the cert spinner with an extra "multiple certificates added" item. loadCertificates( mEapCaCertSpinner, - Credentials.CA_CERTIFICATE, + androidKeystoreAliasLoader.getCaCertAliases(), null /* noCertificateString */, true /* showMultipleCerts */, true /* showUsePreinstalledCertOption */); @@ -1464,8 +1469,8 @@ public class WifiConfigController implements TextWatcher, } @VisibleForTesting - KeyStore getKeyStore() { - return KeyStore.getInstance(); + AndroidKeystoreAliasLoader getAndroidKeystoreAliasLoader() { + return new AndroidKeystoreAliasLoader(KeyProperties.NAMESPACE_WIFI); } @VisibleForTesting @@ -1509,7 +1514,7 @@ public class WifiConfigController implements TextWatcher, @VisibleForTesting void loadCertificates( Spinner spinner, - String prefix, + Collection choices, String noCertificateString, boolean showMultipleCerts, boolean showUsePreinstalledCertOption) { @@ -1524,14 +1529,8 @@ public class WifiConfigController implements TextWatcher, certs.add(mUseSystemCertsString); } - String[] certificateNames = null; - try { - certificateNames = getKeyStore().list(prefix, android.os.Process.WIFI_UID); - } catch (Exception e) { - Log.e(TAG, "can't get the certificate list from KeyStore"); - } - if (certificateNames != null && certificateNames.length != 0) { - certs.addAll(Arrays.stream(certificateNames) + if (choices != null && choices.size() != 0) { + certs.addAll(choices.stream() .filter(certificateName -> { for (String undesired : UNDESIRED_CERTIFICATES) { if (certificateName.startsWith(undesired)) { diff --git a/src/com/android/settings/wifi/WifiConfigController2.java b/src/com/android/settings/wifi/WifiConfigController2.java index 79acc597b00..467f32e60fe 100644 --- a/src/com/android/settings/wifi/WifiConfigController2.java +++ b/src/com/android/settings/wifi/WifiConfigController2.java @@ -33,8 +33,7 @@ import android.net.wifi.WifiEnterpriseConfig.Phase2; import android.net.wifi.WifiManager; import android.os.IBinder; import android.os.UserManager; -import android.security.Credentials; -import android.security.KeyStore; +import android.security.keystore.KeyProperties; import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.text.Editable; @@ -71,6 +70,7 @@ import com.android.net.module.util.NetUtils; import com.android.net.module.util.ProxyUtils; import com.android.settings.ProxySelector; import com.android.settings.R; +import com.android.settings.utils.AndroidKeystoreAliasLoader; import com.android.settings.wifi.details.WifiPrivacyPreferenceController; import com.android.settings.wifi.details2.WifiPrivacyPreferenceController2; import com.android.settings.wifi.dpp.WifiDppUtils; @@ -83,7 +83,7 @@ import com.android.wifitrackerlib.WifiEntry.ConnectedInfo; import java.net.Inet4Address; import java.net.InetAddress; import java.util.ArrayList; -import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.List; @@ -1034,15 +1034,17 @@ public class WifiConfigController2 implements TextWatcher, if (refreshCertificates) { loadSims(); + final AndroidKeystoreAliasLoader androidKeystoreAliasLoader = + getAndroidKeystoreAliasLoader(); loadCertificates( mEapCaCertSpinner, - Credentials.CA_CERTIFICATE, + androidKeystoreAliasLoader.getCaCertAliases(), null /* noCertificateString */, false /* showMultipleCerts */, true /* showUsePreinstalledCertOption */); loadCertificates( mEapUserCertSpinner, - Credentials.USER_PRIVATE_KEY, + androidKeystoreAliasLoader.getKeyCertAliases(), mDoNotProvideEapUserCertString, false /* showMultipleCerts */, false /* showUsePreinstalledCertOption */); @@ -1127,9 +1129,11 @@ public class WifiConfigController2 implements TextWatcher, setSelection(mEapCaCertSpinner, caCerts[0]); } else { // Reload the cert spinner with an extra "multiple certificates added" item. + final AndroidKeystoreAliasLoader androidKeystoreAliasLoader = + getAndroidKeystoreAliasLoader(); loadCertificates( mEapCaCertSpinner, - Credentials.CA_CERTIFICATE, + androidKeystoreAliasLoader.getCaCertAliases(), null /* noCertificateString */, true /* showMultipleCerts */, true /* showUsePreinstalledCertOption */); @@ -1448,8 +1452,8 @@ public class WifiConfigController2 implements TextWatcher, } @VisibleForTesting - KeyStore getKeyStore() { - return KeyStore.getInstance(); + AndroidKeystoreAliasLoader getAndroidKeystoreAliasLoader() { + return new AndroidKeystoreAliasLoader(KeyProperties.NAMESPACE_WIFI); } @VisibleForTesting @@ -1493,7 +1497,7 @@ public class WifiConfigController2 implements TextWatcher, @VisibleForTesting void loadCertificates( Spinner spinner, - String prefix, + Collection choices, String noCertificateString, boolean showMultipleCerts, boolean showUsePreinstalledCertOption) { @@ -1508,14 +1512,8 @@ public class WifiConfigController2 implements TextWatcher, certs.add(mUseSystemCertsString); } - String[] certificateNames = null; - try { - certificateNames = getKeyStore().list(prefix, android.os.Process.WIFI_UID); - } catch (Exception e) { - Log.e(TAG, "can't get the certificate list from KeyStore"); - } - if (certificateNames != null && certificateNames.length != 0) { - certs.addAll(Arrays.stream(certificateNames) + if (choices != null && choices.size() != 0) { + certs.addAll(choices.stream() .filter(certificateName -> { for (String undesired : UNDESIRED_CERTIFICATES) { if (certificateName.startsWith(undesired)) { diff --git a/tests/robotests/src/com/android/settings/wifi/WifiConfigController2Test.java b/tests/robotests/src/com/android/settings/wifi/WifiConfigController2Test.java index 869658264c2..a31e082e29c 100644 --- a/tests/robotests/src/com/android/settings/wifi/WifiConfigController2Test.java +++ b/tests/robotests/src/com/android/settings/wifi/WifiConfigController2Test.java @@ -18,9 +18,6 @@ package com.android.settings.wifi; import static com.google.common.truth.Truth.assertThat; -import static org.mockito.Mockito.anyInt; -import static org.mockito.Mockito.anyString; -import static org.mockito.Mockito.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import static org.robolectric.Shadows.shadowOf; @@ -33,9 +30,6 @@ import android.net.wifi.WifiEnterpriseConfig; import android.net.wifi.WifiEnterpriseConfig.Eap; import android.net.wifi.WifiEnterpriseConfig.Phase2; import android.net.wifi.WifiManager; -import android.os.ServiceSpecificException; -import android.security.Credentials; -import android.security.KeyStore; import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; @@ -50,9 +44,12 @@ import android.widget.TextView; import com.android.settings.R; import com.android.settings.testutils.shadow.ShadowConnectivityManager; +import com.android.settings.utils.AndroidKeystoreAliasLoader; import com.android.settings.wifi.details.WifiPrivacyPreferenceController; import com.android.wifitrackerlib.WifiEntry; +import com.google.common.collect.ImmutableList; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -78,7 +75,7 @@ public class WifiConfigController2Test { @Mock private WifiEntry mWifiEntry; @Mock - private KeyStore mKeyStore; + private AndroidKeystoreAliasLoader mAndroidKeystoreAliasLoader; private View mView; private Spinner mHiddenSettingsSpinner; private Spinner mEapCaCertSpinner; @@ -284,28 +281,12 @@ public class WifiConfigController2Test { assertThat(mController.getSignalString()).isNull(); } - @Test - public void loadCertificates_keyStoreListFail_shouldNotCrash() { - // Set up - when(mWifiEntry.getSecurity()).thenReturn(WifiEntry.SECURITY_EAP); - when(mKeyStore.list(anyString())) - .thenThrow(new ServiceSpecificException(-1, "permission error")); - - mController = new TestWifiConfigController2(mConfigUiBase, mView, mWifiEntry, - WifiConfigUiBase2.MODE_CONNECT); - - // Verify that the EAP method menu is visible. - assertThat(mView.findViewById(R.id.eap).getVisibility()).isEqualTo(View.VISIBLE); - // No Crash - } - @Test public void loadCertificates_undesiredCertificates_shouldNotLoadUndesiredCertificates() { final Spinner spinner = new Spinner(mContext); - when(mKeyStore.list(anyString())).thenReturn(WifiConfigController.UNDESIRED_CERTIFICATES); mController.loadCertificates(spinner, - "prefix", + Arrays.asList(WifiConfigController.UNDESIRED_CERTIFICATES), "doNotProvideEapUserCertString", false /* showMultipleCerts */, false /* showUsePreinstalledCertOption */); @@ -436,8 +417,8 @@ public class WifiConfigController2Test { } @Override - KeyStore getKeyStore() { - return mKeyStore; + AndroidKeystoreAliasLoader getAndroidKeystoreAliasLoader() { + return mAndroidKeystoreAliasLoader; } } @@ -883,6 +864,7 @@ public class WifiConfigController2Test { String savedUserCertificate) { final WifiConfiguration mockWifiConfig = mock(WifiConfiguration.class); final WifiEnterpriseConfig mockWifiEnterpriseConfig = mock(WifiEnterpriseConfig.class); + mockWifiConfig.enterpriseConfig = mockWifiEnterpriseConfig; when(mWifiEntry.isSaved()).thenReturn(true); when(mWifiEntry.getSecurity()).thenReturn(WifiEntry.SECURITY_EAP); @@ -893,15 +875,15 @@ public class WifiConfigController2Test { String[] savedCaCertificates = new String[]{savedCaCertificate}; when(mockWifiEnterpriseConfig.getCaCertificateAliases()) .thenReturn(savedCaCertificates); - when(mKeyStore.list(eq(Credentials.CA_CERTIFICATE), anyInt())) - .thenReturn(savedCaCertificates); + when(mAndroidKeystoreAliasLoader.getCaCertAliases()) + .thenReturn(ImmutableList.of(savedCaCertificate)); } if (savedUserCertificate != null) { String[] savedUserCertificates = new String[]{savedUserCertificate}; when(mockWifiEnterpriseConfig.getClientCertificateAlias()) .thenReturn(savedUserCertificate); - when(mKeyStore.list(eq(Credentials.USER_PRIVATE_KEY), anyInt())) - .thenReturn(savedUserCertificates); + when(mAndroidKeystoreAliasLoader.getKeyCertAliases()) + .thenReturn(ImmutableList.of(savedUserCertificate)); } mController = new TestWifiConfigController2(mConfigUiBase, mView, mWifiEntry, diff --git a/tests/robotests/src/com/android/settings/wifi/WifiConfigControllerTest.java b/tests/robotests/src/com/android/settings/wifi/WifiConfigControllerTest.java index 9e62b251850..40a0dd6cb86 100644 --- a/tests/robotests/src/com/android/settings/wifi/WifiConfigControllerTest.java +++ b/tests/robotests/src/com/android/settings/wifi/WifiConfigControllerTest.java @@ -18,7 +18,6 @@ package com.android.settings.wifi; import static com.google.common.truth.Truth.assertThat; -import static org.mockito.Mockito.anyString; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import static org.robolectric.Shadows.shadowOf; @@ -31,8 +30,6 @@ import android.net.wifi.WifiEnterpriseConfig; import android.net.wifi.WifiEnterpriseConfig.Eap; import android.net.wifi.WifiEnterpriseConfig.Phase2; import android.net.wifi.WifiManager; -import android.os.ServiceSpecificException; -import android.security.KeyStore; import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; @@ -74,8 +71,6 @@ public class WifiConfigControllerTest { private Context mContext; @Mock private AccessPoint mAccessPoint; - @Mock - private KeyStore mKeyStore; private View mView; private Spinner mHiddenSettingsSpinner; private ShadowSubscriptionManager mShadowSubscriptionManager; @@ -263,28 +258,12 @@ public class WifiConfigControllerTest { assertThat(mController.getSignalString()).isNull(); } - @Test - public void loadCertificates_keyStoreListFail_shouldNotCrash() { - // Set up - when(mAccessPoint.getSecurity()).thenReturn(AccessPoint.SECURITY_EAP); - when(mKeyStore.list(anyString())) - .thenThrow(new ServiceSpecificException(-1, "permission error")); - - mController = new TestWifiConfigController(mConfigUiBase, mView, mAccessPoint, - WifiConfigUiBase.MODE_CONNECT); - - // Verify that the EAP method menu is visible. - assertThat(mView.findViewById(R.id.eap).getVisibility()).isEqualTo(View.VISIBLE); - // No Crash - } - @Test public void loadCertificates_undesiredCertificates_shouldNotLoadUndesiredCertificates() { final Spinner spinner = new Spinner(mContext); - when(mKeyStore.list(anyString())).thenReturn(WifiConfigController.UNDESIRED_CERTIFICATES); mController.loadCertificates(spinner, - "prefix", + Arrays.asList(WifiConfigController.UNDESIRED_CERTIFICATES), "doNotProvideEapUserCertString", false /* showMultipleCerts */, false /* showUsePreinstalledCertOption */); @@ -413,9 +392,6 @@ public class WifiConfigControllerTest { boolean isSplitSystemUser() { return false; } - - @Override - KeyStore getKeyStore() { return mKeyStore; } } @Test From 146a0dab0144a348fefce24296ebfd1256ce0d72 Mon Sep 17 00:00:00 2001 From: Janis Danisevskis Date: Mon, 25 Jan 2021 14:59:38 -0800 Subject: [PATCH 08/23] Keystore 2.0: Make Legacy VPN settings ready for Keystore 2.0 Keystore 2.0 no longer stores vpn profiles. It still offers a Legacy VPN profile store, to access existing profiles. Test: N/A Bug: 171305607 Bug: 171305388 Merged-In: I40dea0b9c3824b56814ae4c2fb6c7663c7d97af5 Change-Id: I40dea0b9c3824b56814ae4c2fb6c7663c7d97af5 --- .../utils/AndroidKeystoreAliasLoader.java | 5 +++ .../android/settings/vpn2/ConfigDialog.java | 40 +++++++++++-------- .../settings/vpn2/ConfigDialogFragment.java | 10 ++--- .../android/settings/vpn2/VpnSettings.java | 16 ++++---- src/com/android/settings/vpn2/VpnUtils.java | 12 +++--- 5 files changed, 44 insertions(+), 39 deletions(-) diff --git a/src/com/android/settings/utils/AndroidKeystoreAliasLoader.java b/src/com/android/settings/utils/AndroidKeystoreAliasLoader.java index b9ccf291b74..bb9abb981be 100644 --- a/src/com/android/settings/utils/AndroidKeystoreAliasLoader.java +++ b/src/com/android/settings/utils/AndroidKeystoreAliasLoader.java @@ -28,6 +28,7 @@ import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.UnrecoverableKeyException; +import java.security.cert.Certificate; import java.util.ArrayList; import java.util.Collection; import java.util.Enumeration; @@ -88,6 +89,10 @@ public class AndroidKeystoreAliasLoader { if (key != null) { if (key instanceof PrivateKey) { mKeyCertAliases.add(alias); + final Certificate[] cert = keyStore.getCertificateChain(alias); + if (cert != null && cert.length >= 2) { + mCaCertAliases.add(alias); + } } } else { if (keyStore.getCertificate(alias) != null) { diff --git a/src/com/android/settings/vpn2/ConfigDialog.java b/src/com/android/settings/vpn2/ConfigDialog.java index a0c7a1e92fe..42bc67dc15a 100644 --- a/src/com/android/settings/vpn2/ConfigDialog.java +++ b/src/com/android/settings/vpn2/ConfigDialog.java @@ -24,8 +24,6 @@ import android.content.pm.PackageManager; import android.net.ProxyInfo; import android.os.Bundle; import android.os.SystemProperties; -import android.security.Credentials; -import android.security.KeyStore; import android.text.Editable; import android.text.TextWatcher; import android.view.View; @@ -42,10 +40,12 @@ import androidx.appcompat.app.AlertDialog; import com.android.internal.net.VpnProfile; import com.android.net.module.util.ProxyUtils; import com.android.settings.R; +import com.android.settings.utils.AndroidKeystoreAliasLoader; import java.net.InetAddress; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.List; /** @@ -58,7 +58,7 @@ import java.util.List; class ConfigDialog extends AlertDialog implements TextWatcher, View.OnClickListener, AdapterView.OnItemSelectedListener, CompoundButton.OnCheckedChangeListener { - private final KeyStore mKeyStore = KeyStore.getInstance(); + private static final String TAG = "ConfigDialog"; private final DialogInterface.OnClickListener mListener; private final VpnProfile mProfile; @@ -153,10 +153,13 @@ class ConfigDialog extends AlertDialog implements TextWatcher, mL2tpSecret.setTextAppearance(android.R.style.TextAppearance_DeviceDefault_Medium); mIpsecIdentifier.setText(mProfile.ipsecIdentifier); mIpsecSecret.setText(mProfile.ipsecSecret); - loadCertificates(mIpsecUserCert, Credentials.USER_PRIVATE_KEY, 0, mProfile.ipsecUserCert); - loadCertificates(mIpsecCaCert, Credentials.CA_CERTIFICATE, + AndroidKeystoreAliasLoader androidKeystoreAliasLoader = + new AndroidKeystoreAliasLoader(null); + loadCertificates(mIpsecUserCert, androidKeystoreAliasLoader.getKeyCertAliases(), 0, + mProfile.ipsecUserCert); + loadCertificates(mIpsecCaCert, androidKeystoreAliasLoader.getCaCertAliases(), R.string.vpn_no_ca_cert, mProfile.ipsecCaCert); - loadCertificates(mIpsecServerCert, Credentials.USER_CERTIFICATE, + loadCertificates(mIpsecServerCert, androidKeystoreAliasLoader.getKeyCertAliases(), R.string.vpn_no_server_cert, mProfile.ipsecServerCert); mSaveLogin.setChecked(mProfile.saveLogin); mAlwaysOnVpn.setChecked(mProfile.key.equals(VpnUtils.getLockdownVpn())); @@ -511,27 +514,30 @@ class ConfigDialog extends AlertDialog implements TextWatcher, typeSpinner.setAdapter(adapter); } - private void loadCertificates(Spinner spinner, String prefix, int firstId, String selected) { + private void loadCertificates(Spinner spinner, Collection choices, int firstId, + String selected) { Context context = getContext(); String first = (firstId == 0) ? "" : context.getString(firstId); - String[] certificates = mKeyStore.list(prefix); + String[] myChoices; - if (certificates == null || certificates.length == 0) { - certificates = new String[] {first}; + if (choices == null || choices.size() == 0) { + myChoices = new String[] {first}; } else { - String[] array = new String[certificates.length + 1]; - array[0] = first; - System.arraycopy(certificates, 0, array, 1, certificates.length); - certificates = array; + myChoices = new String[choices.size() + 1]; + myChoices[0] = first; + int i = 1; + for (String c : choices) { + myChoices[i++] = c; + } } ArrayAdapter adapter = new ArrayAdapter( - context, android.R.layout.simple_spinner_item, certificates); + context, android.R.layout.simple_spinner_item, myChoices); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); spinner.setAdapter(adapter); - for (int i = 1; i < certificates.length; ++i) { - if (certificates[i].equals(selected)) { + for (int i = 1; i < myChoices.length; ++i) { + if (myChoices[i].equals(selected)) { spinner.setSelection(i); break; } diff --git a/src/com/android/settings/vpn2/ConfigDialogFragment.java b/src/com/android/settings/vpn2/ConfigDialogFragment.java index f339a694c03..b8825fed6b8 100644 --- a/src/com/android/settings/vpn2/ConfigDialogFragment.java +++ b/src/com/android/settings/vpn2/ConfigDialogFragment.java @@ -25,7 +25,7 @@ import android.os.Bundle; import android.os.RemoteException; import android.os.UserHandle; import android.security.Credentials; -import android.security.KeyStore; +import android.security.LegacyVpnProfileStore; import android.util.Log; import android.view.View; import android.widget.Toast; @@ -151,9 +151,8 @@ public class ConfigDialogFragment extends InstrumentedDialogFragment implements return; } - // Delete from KeyStore - KeyStore keyStore = KeyStore.getInstance(); - keyStore.delete(Credentials.VPN + profile.key, KeyStore.UID_SELF); + // Delete from profile store. + LegacyVpnProfileStore.remove(Credentials.VPN + profile.key); updateLockdownVpn(false, profile); } @@ -188,8 +187,7 @@ public class ConfigDialogFragment extends InstrumentedDialogFragment implements } private void save(VpnProfile profile, boolean lockdown) { - KeyStore.getInstance().put(Credentials.VPN + profile.key, profile.encode(), - KeyStore.UID_SELF, /* flags */ 0); + LegacyVpnProfileStore.put(Credentials.VPN + profile.key, profile.encode()); // Flush out old version of profile disconnect(profile); diff --git a/src/com/android/settings/vpn2/VpnSettings.java b/src/com/android/settings/vpn2/VpnSettings.java index 0a3b2b01cd7..7635733d77f 100644 --- a/src/com/android/settings/vpn2/VpnSettings.java +++ b/src/com/android/settings/vpn2/VpnSettings.java @@ -41,7 +41,7 @@ import android.os.Message; import android.os.UserHandle; import android.os.UserManager; import android.security.Credentials; -import android.security.KeyStore; +import android.security.LegacyVpnProfileStore; import android.util.ArrayMap; import android.util.ArraySet; import android.util.Log; @@ -57,7 +57,6 @@ import com.android.internal.annotations.GuardedBy; import com.android.internal.net.LegacyVpnInfo; import com.android.internal.net.VpnConfig; import com.android.internal.net.VpnProfile; -import com.android.internal.util.ArrayUtils; import com.android.settings.R; import com.android.settings.RestrictedSettingsFragment; import com.android.settings.widget.GearPreference; @@ -94,8 +93,6 @@ public class VpnSettings extends RestrictedSettingsFragment implements private UserManager mUserManager; private VpnManager mVpnManager; - private final KeyStore mKeyStore = KeyStore.getInstance(); - private Map mLegacyVpnPreferences = new ArrayMap<>(); private Map mAppPreferences = new ArrayMap<>(); @@ -222,7 +219,7 @@ public class VpnSettings extends RestrictedSettingsFragment implements final Context context = activity.getApplicationContext(); // Run heavy RPCs before switching to UI thread - final List vpnProfiles = loadVpnProfiles(mKeyStore); + final List vpnProfiles = loadVpnProfiles(); final List vpnApps = getVpnApps(context, /* includeProfiles */ true); final Map connectedLegacyVpns = getConnectedLegacyVpns(); @@ -540,12 +537,13 @@ public class VpnSettings extends RestrictedSettingsFragment implements return result; } - static List loadVpnProfiles(KeyStore keyStore, int... excludeTypes) { + private static List loadVpnProfiles() { final ArrayList result = Lists.newArrayList(); - for (String key : keyStore.list(Credentials.VPN)) { - final VpnProfile profile = VpnProfile.decode(key, keyStore.get(Credentials.VPN + key)); - if (profile != null && !ArrayUtils.contains(excludeTypes, profile.type)) { + for (String key : LegacyVpnProfileStore.list(Credentials.VPN)) { + final VpnProfile profile = VpnProfile.decode(key, + LegacyVpnProfileStore.get(Credentials.VPN + key)); + if (profile != null) { result.add(profile); } } diff --git a/src/com/android/settings/vpn2/VpnUtils.java b/src/com/android/settings/vpn2/VpnUtils.java index 4c9338ccd68..d6a55781b5e 100644 --- a/src/com/android/settings/vpn2/VpnUtils.java +++ b/src/com/android/settings/vpn2/VpnUtils.java @@ -20,7 +20,7 @@ import android.net.VpnManager; import android.os.RemoteException; import android.provider.Settings; import android.security.Credentials; -import android.security.KeyStore; +import android.security.LegacyVpnProfileStore; import com.android.internal.net.LegacyVpnInfo; import com.android.internal.net.VpnConfig; @@ -28,27 +28,25 @@ import com.android.internal.net.VpnConfig; /** * Utility functions for vpn. * - * Keystore methods should only be called in system user + * LegacyVpnProfileStore methods should only be called in system user */ public class VpnUtils { private static final String TAG = "VpnUtils"; public static String getLockdownVpn() { - final byte[] value = KeyStore.getInstance().get( - Credentials.LOCKDOWN_VPN, true /* suppressKeyNotFoundWarning */); + final byte[] value = LegacyVpnProfileStore.get(Credentials.LOCKDOWN_VPN); return value == null ? null : new String(value); } public static void clearLockdownVpn(Context context) { - KeyStore.getInstance().delete(Credentials.LOCKDOWN_VPN); + LegacyVpnProfileStore.remove(Credentials.LOCKDOWN_VPN); // Always notify VpnManager after keystore update getVpnManager(context).updateLockdownVpn(); } public static void setLockdownVpn(Context context, String lockdownKey) { - KeyStore.getInstance().put(Credentials.LOCKDOWN_VPN, lockdownKey.getBytes(), - KeyStore.UID_SELF, /* flags */ 0); + LegacyVpnProfileStore.put(Credentials.LOCKDOWN_VPN, lockdownKey.getBytes()); // Always notify VpnManager after keystore update getVpnManager(context).updateLockdownVpn(); } From 50fc7d15ef3ebeff935ded56066d941ae6e26cf3 Mon Sep 17 00:00:00 2001 From: Hugh Chen Date: Thu, 4 Mar 2021 15:11:40 +0800 Subject: [PATCH 09/23] Fix "USB tethering" doesn't work after reconnecting USB Before this CL, if users selects usb tethering option and reconnects usb it would not start entitlement check. Because we only start entitlement checks when users select it. This CL will start entitlement checks when usb tethering option is selected and reconnects usb. Bug: 176037347 Test: make -j42 RunSettingsRoboTests Change-Id: I3a2ad392a1cae9cf97355ef3cd4fb8c23de18673 --- .../usb/UsbDefaultFragment.java | 22 +++++++++++++--- .../usb/UsbDefaultFragmentTest.java | 26 +++++++++++++++++++ 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/src/com/android/settings/connecteddevice/usb/UsbDefaultFragment.java b/src/com/android/settings/connecteddevice/usb/UsbDefaultFragment.java index 668ec3f2ce2..de08f38524f 100644 --- a/src/com/android/settings/connecteddevice/usb/UsbDefaultFragment.java +++ b/src/com/android/settings/connecteddevice/usb/UsbDefaultFragment.java @@ -64,14 +64,24 @@ public class UsbDefaultFragment extends RadioButtonPickerFragment { private UsbConnectionBroadcastReceiver mUsbReceiver; private Handler mHandler = new Handler(); + private boolean mIsConnected = false; @VisibleForTesting UsbConnectionBroadcastReceiver.UsbConnectionListener mUsbConnectionListener = (connected, functions, powerRole, dataRole) -> { + final long defaultFunctions = mUsbBackend.getDefaultUsbFunctions(); + Log.d(TAG, "UsbConnectionListener() connected : " + connected + ", functions : " + + functions + ", defaultFunctions : " + defaultFunctions); + if (connected && !mIsConnected && defaultFunctions == UsbManager.FUNCTION_RNDIS) { + startTethering(); + } + if (mIsStartTethering) { mCurrentFunctions = functions; refresh(functions); + mIsStartTethering = false; } + mIsConnected = connected; }; @Override @@ -146,9 +156,7 @@ public class UsbDefaultFragment extends RadioButtonPickerFragment { if (functions == UsbManager.FUNCTION_RNDIS) { // We need to have entitlement check for usb tethering, so use API in // TetheringManager. - mIsStartTethering = true; - mTetheringManager.startTethering(TETHERING_USB, new HandlerExecutor(mHandler), - mOnStartTetheringCallback); + startTethering(); } else { mIsStartTethering = false; mCurrentFunctions = functions; @@ -159,6 +167,13 @@ public class UsbDefaultFragment extends RadioButtonPickerFragment { return true; } + private void startTethering() { + Log.d(TAG, "startTethering()"); + mIsStartTethering = true; + mTetheringManager.startTethering(TETHERING_USB, new HandlerExecutor(mHandler), + mOnStartTetheringCallback); + } + @Override public void onPause() { super.onPause(); @@ -171,6 +186,7 @@ public class UsbDefaultFragment extends RadioButtonPickerFragment { @Override public void onTetheringStarted() { + Log.d(TAG, "onTetheringStarted()"); // Set default usb functions again to make internal data persistent mCurrentFunctions = UsbManager.FUNCTION_RNDIS; mUsbBackend.setDefaultUsbFunctions(UsbManager.FUNCTION_RNDIS); diff --git a/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbDefaultFragmentTest.java b/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbDefaultFragmentTest.java index c751e98d965..31081507bf9 100644 --- a/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbDefaultFragmentTest.java +++ b/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbDefaultFragmentTest.java @@ -224,6 +224,32 @@ public class UsbDefaultFragmentTest { assertThat(mFragment.mCurrentFunctions).isEqualTo(UsbManager.FUNCTION_MIDI); } + @Test + public void usbIsPluginAndUsbTetheringIsOn_startTetheringIsInvoked() { + when(mUsbBackend.getDefaultUsbFunctions()).thenReturn(UsbManager.FUNCTION_RNDIS); + + mFragment.mUsbConnectionListener.onUsbConnectionChanged(false /* connected */, + UsbManager.FUNCTION_RNDIS, POWER_ROLE_SINK, DATA_ROLE_DEVICE); + mFragment.mUsbConnectionListener.onUsbConnectionChanged(true /* connected */, + UsbManager.FUNCTION_RNDIS, POWER_ROLE_SINK, DATA_ROLE_DEVICE); + + verify(mTetheringManager).startTethering(eq(TetheringManager.TETHERING_USB), + any(), + eq(mFragment.mOnStartTetheringCallback)); + } + + @Test + public void usbIsNotPluginAndUsbTetheringIsOn_startTetheringIsNotInvoked() { + when(mUsbBackend.getDefaultUsbFunctions()).thenReturn(UsbManager.FUNCTION_RNDIS); + + mFragment.mUsbConnectionListener.onUsbConnectionChanged(false /* connected */, + UsbManager.FUNCTION_RNDIS, POWER_ROLE_SINK, DATA_ROLE_DEVICE); + + verify(mTetheringManager, never()).startTethering(eq(TetheringManager.TETHERING_USB), + any(), + eq(mFragment.mOnStartTetheringCallback)); + } + public static class TestFragment extends UsbDefaultFragment { public final PreferenceScreen mScreen; From 698b4b3ca0ca049693f43ddfe3e2d39b78a1acca Mon Sep 17 00:00:00 2001 From: Weng Su Date: Thu, 4 Mar 2021 03:03:44 +0800 Subject: [PATCH 10/23] [Provider Model] Ethernet default network with APM enabled on Panel - Move the connected Wi-Fi network into Wi-Fi list - Screenshot: https://screenshot.googleplex.com/ALgpHTy8RWUYjSk Bug: 178926547 Bug: 179106406 Test: manual test atest -c ProviderModelSliceTest Change-Id: Idd0e0ab52d6fc88633d5b2eddabb00036e077c88 --- .../settings/network/ProviderModelSlice.java | 20 +++++++++---- .../network/ProviderModelSliceTest.java | 28 ++++++++++++++++--- 2 files changed, 38 insertions(+), 10 deletions(-) diff --git a/src/com/android/settings/network/ProviderModelSlice.java b/src/com/android/settings/network/ProviderModelSlice.java index c020f06d4ec..a1fdb1cebf4 100644 --- a/src/com/android/settings/network/ProviderModelSlice.java +++ b/src/com/android/settings/network/ProviderModelSlice.java @@ -83,8 +83,9 @@ public class ProviderModelSlice extends WifiSlice { // Second section: Add a carrier item. // Third section: Add the Wi-Fi items which are not connected. // Fourth section: If device has connection problem, this row show the message for user. + boolean hasEthernet = isEthernetConnected(); final ListBuilder listBuilder = mHelper.createListBuilder(getUri()); - if (mHelper.isAirplaneModeEnabled() && !mWifiManager.isWifiEnabled()) { + if (mHelper.isAirplaneModeEnabled() && !mWifiManager.isWifiEnabled() && !hasEthernet) { log("Airplane mode is enabled."); return listBuilder.build(); } @@ -104,12 +105,12 @@ public class ProviderModelSlice extends WifiSlice { log("hasCarrier: " + hasCarrier); // First section: Add a Ethernet or Wi-Fi item which state is connected. - if (isEthernetConnected()) { + final WifiSliceItem connectedWifiItem = mHelper.getConnectedWifiItem(wifiList); + if (hasEthernet) { log("get Ethernet item which is connected"); listBuilder.addRow(createEthernetRow()); maxListSize--; } else { - final WifiSliceItem connectedWifiItem = mHelper.getConnectedWifiItem(wifiList); if (connectedWifiItem != null) { log("get Wi-Fi item which is connected"); listBuilder.addRow(getWifiSliceItemRow(connectedWifiItem)); @@ -126,7 +127,14 @@ public class ProviderModelSlice extends WifiSlice { maxListSize--; } - // Third section: Add the Wi-Fi items which are not connected. + // Third section: Add the connected Wi-Fi item to Wi-Fi list if the Ethernet is connected. + if (connectedWifiItem != null && hasEthernet) { + log("get Wi-Fi item which is connected"); + listBuilder.addRow(getWifiSliceItemRow(connectedWifiItem)); + maxListSize--; + } + + // Fourth section: Add the Wi-Fi items which are not connected. if (wifiList != null && wifiList.size() > 0) { log("get Wi-Fi items which are not connected. Wi-Fi items : " + wifiList.size()); @@ -140,7 +148,7 @@ public class ProviderModelSlice extends WifiSlice { } } - // Fourth section: If device has connection problem, this row show the message for user. + // Fifth section: If device has connection problem, this row show the message for user. // 1) show non_carrier_network_unavailable: // - while no wifi item // 2) show all_network_unavailable: @@ -154,7 +162,7 @@ public class ProviderModelSlice extends WifiSlice { resId = R.string.all_network_unavailable; } - if (!hasCarrier) { + if (!hasCarrier && !hasEthernet) { // If there is no item in ProviderModelItem, slice needs a header. listBuilder.setHeader(mHelper.createHeader( NetworkProviderSettings.ACTION_NETWORK_PROVIDER_SETTINGS)); diff --git a/tests/unit/src/com/android/settings/network/ProviderModelSliceTest.java b/tests/unit/src/com/android/settings/network/ProviderModelSliceTest.java index 476d8547a71..705f60ec972 100644 --- a/tests/unit/src/com/android/settings/network/ProviderModelSliceTest.java +++ b/tests/unit/src/com/android/settings/network/ProviderModelSliceTest.java @@ -264,7 +264,7 @@ public class ProviderModelSliceTest { @Test @UiThreadTest - public void getSlice_connectedEthernet_getOneEthernetAndOneCarrierAndTwoWiFi() { + public void getSlice_haveEthernetAndCarrierAndTwoDisconnectedWifi_getFourRow() { mWifiList.clear(); mockWifiItemCondition(mMockWifiSliceItem1, "wifi1", "wifi1", WifiEntry.CONNECTED_STATE_DISCONNECTED, "wifi1_key", true); @@ -273,9 +273,29 @@ public class ProviderModelSliceTest { WifiEntry.CONNECTED_STATE_DISCONNECTED, "wifi2_key", true); mWifiList.add(mMockWifiSliceItem2); mMockNetworkProviderWorker.updateSelfResults(mWifiList); - when(mProviderModelSliceHelper.isAirplaneModeEnabled()).thenReturn(false); - when(mProviderModelSliceHelper.hasCarrier()).thenReturn(true); - when(mProviderModelSliceHelper.isDataSimActive()).thenReturn(true); + mockHelperCondition(false, true, true, null); + when(mMockNetworkProviderWorker.isEthernetConnected()).thenReturn(true); + + final Slice slice = mMockProviderModelSlice.getSlice(); + + assertThat(slice).isNotNull(); + assertThat(mMockProviderModelSlice.hasCreateEthernetRow()).isTrue(); + verify(mListBuilder, times(1)).addRow(mMockCarrierRowBuild); + verify(mListBuilder, times(4)).addRow(any(ListBuilder.RowBuilder.class)); + } + + @Test + @UiThreadTest + public void getSlice_haveEthernetAndCarrierAndConnectedWifiAndDisconnectedWifi_getFourRow() { + mWifiList.clear(); + mockWifiItemCondition(mMockWifiSliceItem1, "wifi1", "wifi1", + WifiEntry.CONNECTED_STATE_CONNECTED, "wifi1_key", true); + mWifiList.add(mMockWifiSliceItem1); + mockWifiItemCondition(mMockWifiSliceItem2, "wifi2", "wifi2", + WifiEntry.CONNECTED_STATE_DISCONNECTED, "wifi2_key", true); + mWifiList.add(mMockWifiSliceItem2); + mMockNetworkProviderWorker.updateSelfResults(mWifiList); + mockHelperCondition(false, true, true, mWifiList.get(0)); when(mMockNetworkProviderWorker.isEthernetConnected()).thenReturn(true); final Slice slice = mMockProviderModelSlice.getSlice(); From fc435e3736ae8b4e1043f686397338082c871c3e Mon Sep 17 00:00:00 2001 From: SongFerngWang Date: Tue, 12 Jan 2021 21:20:36 +0800 Subject: [PATCH 11/23] Replace allowedNetworkTypes with allowedNetworkTypesForReason - Replace getAllowedNetworkTypes with getallowedNetworkTypesForReason(ALLOWED_NETWORK_TYPES_REASON_CARRIER) - Replace "Settings.Global.PREFERRED_NETWORK_MODE" with "getAllowedNetworkTypesForReason(USER)" - Move EnabledNetworkModePreferenceControllerTest from robotests to unit - Replace KEY_NR_ENABLED_BOOL with KEY_CARRIER_NR_AVAILABILITY_INT - Rename PreferredNetworkModeContentObserver to AllowedNetworkTypesListener Bug: 161434786 Test: build pass. (PASS)atest CdmaSystemSelectPreferenceControllerTest (PASS)atest PreferredNetworkModePreferenceControllerTest (PASS)atest AllowedNetworkTypesListenerTest (PASS)atest EnabledNetworkModePreferenceControllerTest (PASS)atest MobileNetworkUtilsTest Change-Id: I2b981569ad11cf70a558c1952cc2e077464328d8 Merged-In: I2b981569ad11cf70a558c1952cc2e077464328d8 --- .../network/AllowedNetworkTypesListener.java | 93 ++++++++ .../PreferredNetworkModeContentObserver.java | 66 ------ ...nabledNetworkModePreferenceController.java | 42 ++-- .../Enhanced4gBasePreferenceController.java | 5 +- .../network/telephony/MobileNetworkUtils.java | 36 +-- .../NetworkPreferenceCategoryController.java | 16 +- ...ferredNetworkModePreferenceController.java | 19 +- .../cdma/CdmaBasePreferenceController.java | 56 ++--- .../CdmaSystemSelectPreferenceController.java | 10 +- .../gsm/AutoSelectPreferenceController.java | 14 +- ...NetworkSelectPagePreferenceController.java | 16 +- ...edNetworkModePreferenceControllerTest.java | 39 ++-- .../AllowedNetworkTypesListenerTest.java | 101 ++++++++ ...edNetworkModePreferenceControllerTest.java | 215 +++++++++++------- ...eferredNetworkModeContentObserverTest.java | 83 ------- .../telephony/MobileNetworkUtilsTest.java | 61 +++-- ...aSystemSelectPreferenceControllerTest.java | 23 +- 17 files changed, 478 insertions(+), 417 deletions(-) create mode 100644 src/com/android/settings/network/AllowedNetworkTypesListener.java delete mode 100644 src/com/android/settings/network/PreferredNetworkModeContentObserver.java create mode 100644 tests/unit/src/com/android/settings/network/AllowedNetworkTypesListenerTest.java rename tests/{robotests/src/com/android/settings/network/telephony => unit/src/com/android/settings/network}/EnabledNetworkModePreferenceControllerTest.java (68%) delete mode 100644 tests/unit/src/com/android/settings/network/PreferredNetworkModeContentObserverTest.java diff --git a/src/com/android/settings/network/AllowedNetworkTypesListener.java b/src/com/android/settings/network/AllowedNetworkTypesListener.java new file mode 100644 index 00000000000..a11f3b41301 --- /dev/null +++ b/src/com/android/settings/network/AllowedNetworkTypesListener.java @@ -0,0 +1,93 @@ +/* + * 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.network; + +import android.content.Context; +import android.telephony.PhoneStateListener; +import android.telephony.TelephonyManager; +import android.util.Log; + +import androidx.annotation.VisibleForTesting; + +import java.util.Map; +import java.util.concurrent.Executor; + + +/** + * {@link PhoneStateListener} to listen to Allowed Network Types changed + */ +public class AllowedNetworkTypesListener extends PhoneStateListener implements + PhoneStateListener.AllowedNetworkTypesChangedListener { + private static final String LOG_TAG = "NetworkModeListener"; + + @VisibleForTesting + AllowedNetworkTypesListener.OnAllowedNetworkTypesChangedListener mListener; + private long mAllowedNetworkType = -1; + private Executor mExecutor; + + public AllowedNetworkTypesListener(Executor executor) { + super(); + mExecutor = executor; + } + + public void setAllowedNetworkTypesChangedListener(OnAllowedNetworkTypesChangedListener lsn) { + mListener = lsn; + } + + /** + * Register a PhoneStateListener for Allowed Network Types changed. + * @param context the Context + * @param subId the subscription id. + */ + public void register(Context context, int subId) { + TelephonyManager telephonyManager = context.getSystemService( + TelephonyManager.class).createForSubscriptionId(subId); + telephonyManager.registerPhoneStateListener(mExecutor, this); + } + + /** + * Unregister a PhoneStateListener for Allowed Network Types changed. + * @param context the Context + * @param subId the subscription id. + */ + public void unregister(Context context, int subId) { + TelephonyManager telephonyManager = context.getSystemService( + TelephonyManager.class).createForSubscriptionId(subId); + telephonyManager.unregisterPhoneStateListener(this); + } + + @Override + public void onAllowedNetworkTypesChanged(Map allowedNetworkTypesList) { + long newAllowedNetworkType = allowedNetworkTypesList.get( + TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER); + if (mListener != null && mAllowedNetworkType != newAllowedNetworkType) { + mListener.onAllowedNetworkTypesChanged(); + Log.d(LOG_TAG, "onAllowedNetworkChanged: " + mAllowedNetworkType); + } + mAllowedNetworkType = newAllowedNetworkType; + } + + /** + * Listener for update of Preferred Network Mode change + */ + public interface OnAllowedNetworkTypesChangedListener { + /** + * Notify the allowed network type changed. + */ + void onAllowedNetworkTypesChanged(); + } +} diff --git a/src/com/android/settings/network/PreferredNetworkModeContentObserver.java b/src/com/android/settings/network/PreferredNetworkModeContentObserver.java deleted file mode 100644 index 9d07eb444a3..00000000000 --- a/src/com/android/settings/network/PreferredNetworkModeContentObserver.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * 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.network; - -import android.content.Context; -import android.database.ContentObserver; -import android.net.Uri; -import android.os.Handler; -import android.provider.Settings; - -import androidx.annotation.VisibleForTesting; - -/** - * {@link ContentObserver} to listen to Preferred Network Mode change - */ -public class PreferredNetworkModeContentObserver extends ContentObserver { - @VisibleForTesting - OnPreferredNetworkModeChangedListener mListener; - - public PreferredNetworkModeContentObserver(Handler handler) { - super(handler); - } - - public void setPreferredNetworkModeChangedListener(OnPreferredNetworkModeChangedListener lsn) { - mListener = lsn; - } - - @Override - public void onChange(boolean selfChange) { - super.onChange(selfChange); - if (mListener != null) { - mListener.onPreferredNetworkModeChanged(); - } - } - - public void register(Context context, int subId) { - final Uri uri = Settings.Global.getUriFor( - Settings.Global.PREFERRED_NETWORK_MODE + subId); - context.getContentResolver().registerContentObserver(uri, false, this); - } - - public void unregister(Context context) { - context.getContentResolver().unregisterContentObserver(this); - } - - /** - * Listener for update of Preferred Network Mode change - */ - public interface OnPreferredNetworkModeChangedListener { - void onPreferredNetworkModeChanged(); - } -} diff --git a/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java b/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java index 8a32a95712c..217bfbde5df 100644 --- a/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java +++ b/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java @@ -20,10 +20,7 @@ import static androidx.lifecycle.Lifecycle.Event.ON_START; import static androidx.lifecycle.Lifecycle.Event.ON_STOP; import android.content.Context; -import android.os.Handler; -import android.os.Looper; import android.os.PersistableBundle; -import android.provider.Settings; import android.telephony.CarrierConfigManager; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; @@ -37,7 +34,7 @@ import androidx.preference.Preference; import androidx.preference.PreferenceScreen; import com.android.settings.R; -import com.android.settings.network.PreferredNetworkModeContentObserver; +import com.android.settings.network.AllowedNetworkTypesListener; import com.android.settings.network.telephony.TelephonyConstants.TelephonyManagerConstants; import java.util.ArrayList; @@ -53,7 +50,7 @@ public class EnabledNetworkModePreferenceController extends ListPreference.OnPreferenceChangeListener, LifecycleObserver { private static final String LOG_TAG = "EnabledNetworkMode"; - private PreferredNetworkModeContentObserver mPreferredNetworkModeObserver; + private AllowedNetworkTypesListener mAllowedNetworkTypesListener; private Preference mPreference; private PreferenceScreen mPreferenceScreen; private TelephonyManager mTelephonyManager; @@ -88,18 +85,18 @@ public class EnabledNetworkModePreferenceController extends @OnLifecycleEvent(ON_START) public void onStart() { - if (mPreferredNetworkModeObserver == null) { + if (mAllowedNetworkTypesListener == null) { return; } - mPreferredNetworkModeObserver.register(mContext, mSubId); + mAllowedNetworkTypesListener.register(mContext, mSubId); } @OnLifecycleEvent(ON_STOP) public void onStop() { - if (mPreferredNetworkModeObserver == null) { + if (mAllowedNetworkTypesListener == null) { return; } - mPreferredNetworkModeObserver.unregister(mContext); + mAllowedNetworkTypesListener.unregister(mContext, mSubId); } @Override @@ -145,10 +142,10 @@ public class EnabledNetworkModePreferenceController extends mCarrierConfigManager = mContext.getSystemService(CarrierConfigManager.class); mBuilder = new PreferenceEntriesBuilder(mContext, mSubId); - if (mPreferredNetworkModeObserver == null) { - mPreferredNetworkModeObserver = new PreferredNetworkModeContentObserver( - new Handler(Looper.getMainLooper())); - mPreferredNetworkModeObserver.setPreferredNetworkModeChangedListener( + if (mAllowedNetworkTypesListener == null) { + mAllowedNetworkTypesListener = new AllowedNetworkTypesListener( + mContext.getMainExecutor()); + mAllowedNetworkTypesListener.setAllowedNetworkTypesChangedListener( () -> updatePreference()); } @@ -205,13 +202,12 @@ public class EnabledNetworkModePreferenceController extends .createForSubscriptionId(mSubId); final PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(mSubId); - final boolean isNrEnabledFromCarrierConfig = carrierConfig != null - && carrierConfig.getBoolean(CarrierConfigManager.KEY_NR_ENABLED_BOOL); mAllowed5gNetworkType = checkSupportedRadioBitmask( - mTelephonyManager.getAllowedNetworkTypes(), + mTelephonyManager.getAllowedNetworkTypesForReason( + TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_CARRIER), TelephonyManager.NETWORK_TYPE_BITMASK_NR); - mSupported5gRadioAccessFamily = isNrEnabledFromCarrierConfig - && checkSupportedRadioBitmask(mTelephonyManager.getSupportedRadioAccessFamily(), + mSupported5gRadioAccessFamily = checkSupportedRadioBitmask( + mTelephonyManager.getSupportedRadioAccessFamily(), TelephonyManager.NETWORK_TYPE_BITMASK_NR); mIsGlobalCdma = mTelephonyManager.isLteCdmaEvdoGsmWcdmaEnabled() && carrierConfig != null @@ -370,9 +366,9 @@ public class EnabledNetworkModePreferenceController extends } private int getPreferredNetworkMode() { - int networkMode = Settings.Global.getInt(mContext.getContentResolver(), - Settings.Global.PREFERRED_NETWORK_MODE + mSubId, - TelephonyManager.DEFAULT_PREFERRED_NETWORK_MODE); + int networkMode = MobileNetworkUtils.getNetworkTypeFromRaf( + (int) mTelephonyManager.getAllowedNetworkTypesForReason( + TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER)); if (!showNrList()) { Log.d(LOG_TAG, "Network mode :" + networkMode + " reduce NR"); networkMode = reduceNrToLteNetworkType(networkMode); @@ -452,7 +448,7 @@ public class EnabledNetworkModePreferenceController extends * Sets the display string for the network mode choice and selects the corresponding item * * @param networkMode the current network mode. The current mode might not be an option in - * the choice list. The nearest choice is selected instead + * the choice list. The nearest choice is selected instead */ void setPreferenceValueAndSummary(int networkMode) { setSelectedEntry(networkMode); @@ -781,7 +777,7 @@ public class EnabledNetworkModePreferenceController extends } private String[] getEntryValues() { - final Integer [] intArr = mEntriesValue.toArray(new Integer[0]); + final Integer[] intArr = mEntriesValue.toArray(new Integer[0]); return Arrays.stream(intArr) .map(String::valueOf) .toArray(String[]::new); diff --git a/src/com/android/settings/network/telephony/Enhanced4gBasePreferenceController.java b/src/com/android/settings/network/telephony/Enhanced4gBasePreferenceController.java index ba1214611d6..989cb028455 100644 --- a/src/com/android/settings/network/telephony/Enhanced4gBasePreferenceController.java +++ b/src/com/android/settings/network/telephony/Enhanced4gBasePreferenceController.java @@ -95,8 +95,9 @@ public class Enhanced4gBasePreferenceController extends TelephonyTogglePreferenc mShow5gLimitedDialog = carrierConfig.getBoolean( CarrierConfigManager.KEY_VOLTE_5G_LIMITED_ALERT_DIALOG_BOOL); - mIsNrEnabledFromCarrierConfig = carrierConfig.getBoolean( - CarrierConfigManager.KEY_NR_ENABLED_BOOL); + mIsNrEnabledFromCarrierConfig = carrierConfig.getInt( + CarrierConfigManager.KEY_CARRIER_NR_AVAILABILITY_INT) + != CarrierConfigManager.CARRIER_NR_AVAILABILITY_NONE; return this; } diff --git a/src/com/android/settings/network/telephony/MobileNetworkUtils.java b/src/com/android/settings/network/telephony/MobileNetworkUtils.java index c61c2229c82..2f0695d9f0e 100644 --- a/src/com/android/settings/network/telephony/MobileNetworkUtils.java +++ b/src/com/android/settings/network/telephony/MobileNetworkUtils.java @@ -339,10 +339,10 @@ public class MobileNetworkUtils { } if (isWorldMode(context, subId)) { - final int settingsNetworkMode = android.provider.Settings.Global.getInt( - context.getContentResolver(), - android.provider.Settings.Global.PREFERRED_NETWORK_MODE + subId, - TelephonyManager.DEFAULT_PREFERRED_NETWORK_MODE); + final int settingsNetworkMode = getNetworkTypeFromRaf( + (int) telephonyManager.getAllowedNetworkTypesForReason( + TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER)); + if (settingsNetworkMode == NETWORK_MODE_LTE_GSM_WCDMA || settingsNetworkMode == NETWORK_MODE_LTE_CDMA_EVDO || settingsNetworkMode == NETWORK_MODE_NR_LTE_GSM_WCDMA @@ -368,10 +368,11 @@ public class MobileNetworkUtils { if (isGsmBasicOptions(context, subId)) { return true; } - final int networkMode = android.provider.Settings.Global.getInt( - context.getContentResolver(), - android.provider.Settings.Global.PREFERRED_NETWORK_MODE + subId, - TelephonyManager.DEFAULT_PREFERRED_NETWORK_MODE); + final TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class) + .createForSubscriptionId(subId); + final int networkMode = getNetworkTypeFromRaf( + (int) telephonyManager.getAllowedNetworkTypesForReason( + TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER)); if (isWorldMode(context, subId)) { if (networkMode == NETWORK_MODE_LTE_CDMA_EVDO || networkMode == NETWORK_MODE_LTE_GSM_WCDMA @@ -435,10 +436,9 @@ public class MobileNetworkUtils { return false; } - final int networkMode = android.provider.Settings.Global.getInt( - context.getContentResolver(), - android.provider.Settings.Global.PREFERRED_NETWORK_MODE + subId, - TelephonyManager.DEFAULT_PREFERRED_NETWORK_MODE); + final int networkMode = getNetworkTypeFromRaf( + (int) telephonyManager.getAllowedNetworkTypesForReason( + TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER)); if (networkMode == TelephonyManagerConstants.NETWORK_MODE_LTE_CDMA_EVDO && isWorldMode(context, subId)) { return false; @@ -550,15 +550,17 @@ public class MobileNetworkUtils { */ @VisibleForTesting static boolean shouldSpeciallyUpdateGsmCdma(Context context, int subId) { - final int networkMode = android.provider.Settings.Global.getInt( - context.getContentResolver(), - android.provider.Settings.Global.PREFERRED_NETWORK_MODE + subId, - TelephonyManager.DEFAULT_PREFERRED_NETWORK_MODE); + final TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class) + .createForSubscriptionId(subId); + final int networkMode = getNetworkTypeFromRaf( + (int) telephonyManager.getAllowedNetworkTypesForReason( + TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER)); if (networkMode == TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA_GSM || networkMode == TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA_GSM_WCDMA || networkMode == TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA || networkMode == TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA_WCDMA - || networkMode == TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA + || networkMode + == TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA || networkMode == TelephonyManagerConstants.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA) { if (!isTdscdmaSupported(context, subId) && isWorldMode(context, subId)) { return true; diff --git a/src/com/android/settings/network/telephony/NetworkPreferenceCategoryController.java b/src/com/android/settings/network/telephony/NetworkPreferenceCategoryController.java index 042eb5fc088..25651f5379e 100644 --- a/src/com/android/settings/network/telephony/NetworkPreferenceCategoryController.java +++ b/src/com/android/settings/network/telephony/NetworkPreferenceCategoryController.java @@ -20,8 +20,6 @@ import static androidx.lifecycle.Lifecycle.Event.ON_START; import static androidx.lifecycle.Lifecycle.Event.ON_STOP; import android.content.Context; -import android.os.Handler; -import android.os.Looper; import android.telephony.SubscriptionManager; import androidx.lifecycle.Lifecycle; @@ -29,7 +27,7 @@ import androidx.lifecycle.LifecycleObserver; import androidx.lifecycle.OnLifecycleEvent; import androidx.preference.PreferenceScreen; -import com.android.settings.network.PreferredNetworkModeContentObserver; +import com.android.settings.network.AllowedNetworkTypesListener; import com.android.settings.widget.PreferenceCategoryController; /** @@ -39,15 +37,15 @@ public class NetworkPreferenceCategoryController extends PreferenceCategoryContr implements LifecycleObserver { private PreferenceScreen mPreferenceScreen; - private PreferredNetworkModeContentObserver mPreferredNetworkModeObserver; + private AllowedNetworkTypesListener mAllowedNetworkTypesListener; protected int mSubId; public NetworkPreferenceCategoryController(Context context, String key) { super(context, key); mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; - mPreferredNetworkModeObserver = new PreferredNetworkModeContentObserver( - new Handler(Looper.getMainLooper())); - mPreferredNetworkModeObserver.setPreferredNetworkModeChangedListener( + mAllowedNetworkTypesListener = new AllowedNetworkTypesListener( + context.getMainExecutor()); + mAllowedNetworkTypesListener.setAllowedNetworkTypesChangedListener( () -> updatePreference()); } @@ -57,12 +55,12 @@ public class NetworkPreferenceCategoryController extends PreferenceCategoryContr @OnLifecycleEvent(ON_START) public void onStart() { - mPreferredNetworkModeObserver.register(mContext, mSubId); + mAllowedNetworkTypesListener.register(mContext, mSubId); } @OnLifecycleEvent(ON_STOP) public void onStop() { - mPreferredNetworkModeObserver.unregister(mContext); + mAllowedNetworkTypesListener.unregister(mContext, mSubId); } @Override diff --git a/src/com/android/settings/network/telephony/PreferredNetworkModePreferenceController.java b/src/com/android/settings/network/telephony/PreferredNetworkModePreferenceController.java index ff6ff596fe9..24197795fa2 100644 --- a/src/com/android/settings/network/telephony/PreferredNetworkModePreferenceController.java +++ b/src/com/android/settings/network/telephony/PreferredNetworkModePreferenceController.java @@ -18,7 +18,6 @@ package com.android.settings.network.telephony; import android.content.Context; import android.os.PersistableBundle; -import android.provider.Settings; import android.telephony.CarrierConfigManager; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; @@ -80,17 +79,13 @@ public class PreferredNetworkModePreferenceController extends TelephonyBasePrefe public boolean onPreferenceChange(Preference preference, Object object) { final int newPreferredNetworkMode = Integer.parseInt((String) object); - if (mTelephonyManager.setPreferredNetworkTypeBitmask( - MobileNetworkUtils.getRafFromNetworkType(newPreferredNetworkMode))) { - Settings.Global.putInt(mContext.getContentResolver(), - Settings.Global.PREFERRED_NETWORK_MODE + mSubId, - newPreferredNetworkMode); + mTelephonyManager.setAllowedNetworkTypesForReason( + TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER, + MobileNetworkUtils.getRafFromNetworkType(newPreferredNetworkMode)); + final ListPreference listPreference = (ListPreference) preference; listPreference.setSummary(getPreferredNetworkModeSummaryResId(newPreferredNetworkMode)); return true; - } - - return false; } public void init(int subId) { @@ -104,9 +99,9 @@ public class PreferredNetworkModePreferenceController extends TelephonyBasePrefe } private int getPreferredNetworkMode() { - return Settings.Global.getInt(mContext.getContentResolver(), - Settings.Global.PREFERRED_NETWORK_MODE + mSubId, - TelephonyManager.DEFAULT_PREFERRED_NETWORK_MODE); + return MobileNetworkUtils.getNetworkTypeFromRaf( + (int) mTelephonyManager.getAllowedNetworkTypesForReason( + TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER)); } private int getPreferredNetworkModeSummaryResId(int NetworkMode) { diff --git a/src/com/android/settings/network/telephony/cdma/CdmaBasePreferenceController.java b/src/com/android/settings/network/telephony/cdma/CdmaBasePreferenceController.java index a100d700257..06c3edb8478 100644 --- a/src/com/android/settings/network/telephony/cdma/CdmaBasePreferenceController.java +++ b/src/com/android/settings/network/telephony/cdma/CdmaBasePreferenceController.java @@ -17,11 +17,6 @@ package com.android.settings.network.telephony.cdma; import android.content.Context; -import android.database.ContentObserver; -import android.net.Uri; -import android.os.Handler; -import android.os.Looper; -import android.provider.Settings; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; @@ -29,6 +24,7 @@ import androidx.preference.Preference; import androidx.preference.PreferenceManager; import androidx.preference.PreferenceScreen; +import com.android.settings.network.AllowedNetworkTypesListener; import com.android.settings.network.telephony.MobileNetworkUtils; import com.android.settings.network.telephony.TelephonyBasePreferenceController; import com.android.settingslib.core.lifecycle.LifecycleObserver; @@ -44,22 +40,25 @@ public abstract class CdmaBasePreferenceController extends TelephonyBasePreferen protected Preference mPreference; protected TelephonyManager mTelephonyManager; protected PreferenceManager mPreferenceManager; - private DataContentObserver mDataContentObserver; + private AllowedNetworkTypesListener mAllowedNetworkTypesListener; public CdmaBasePreferenceController(Context context, String key) { super(context, key); mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; - mDataContentObserver = new DataContentObserver(new Handler(Looper.getMainLooper())); } @Override public void onStart() { - mDataContentObserver.register(mContext, mSubId); + if (mAllowedNetworkTypesListener != null) { + mAllowedNetworkTypesListener.register(mContext, mSubId); + } } @Override public void onStop() { - mDataContentObserver.unRegister(mContext); + if (mAllowedNetworkTypesListener != null) { + mAllowedNetworkTypesListener.unregister(mContext, mSubId); + } } @Override @@ -74,12 +73,25 @@ public abstract class CdmaBasePreferenceController extends TelephonyBasePreferen mSubId = subId; mTelephonyManager = mContext.getSystemService(TelephonyManager.class) .createForSubscriptionId(mSubId); + + if (mAllowedNetworkTypesListener == null) { + mAllowedNetworkTypesListener = new AllowedNetworkTypesListener( + mContext.getMainExecutor()); + mAllowedNetworkTypesListener.setAllowedNetworkTypesChangedListener( + () -> updatePreference()); + } } public void init(int subId) { init(null, subId); } + private void updatePreference() { + if (mPreference != null) { + updateState(mPreference); + } + } + @Override public void displayPreference(PreferenceScreen screen) { super.displayPreference(screen); @@ -88,30 +100,4 @@ public abstract class CdmaBasePreferenceController extends TelephonyBasePreferen ((CdmaListPreference) mPreference).setSubId(mSubId); } } - - /** - * Listener that listens to mobile data state change. - */ - public class DataContentObserver extends ContentObserver { - - public DataContentObserver(Handler handler) { - super(handler); - } - - @Override - public void onChange(boolean selfChange) { - super.onChange(selfChange); - updateState(mPreference); - } - - public void register(Context context, int subId) { - final Uri uri = Settings.Global.getUriFor( - Settings.Global.PREFERRED_NETWORK_MODE + subId); - context.getContentResolver().registerContentObserver(uri, false, this); - } - - public void unRegister(Context context) { - context.getContentResolver().unregisterContentObserver(this); - } - } } diff --git a/src/com/android/settings/network/telephony/cdma/CdmaSystemSelectPreferenceController.java b/src/com/android/settings/network/telephony/cdma/CdmaSystemSelectPreferenceController.java index 2b0c2217ec0..5dd445379b8 100644 --- a/src/com/android/settings/network/telephony/cdma/CdmaSystemSelectPreferenceController.java +++ b/src/com/android/settings/network/telephony/cdma/CdmaSystemSelectPreferenceController.java @@ -26,6 +26,8 @@ import android.telephony.TelephonyManager; import androidx.preference.ListPreference; import androidx.preference.Preference; +import com.android.settings.network.telephony.MobileNetworkUtils; + /** * Preference controller for "System Select" */ @@ -50,10 +52,10 @@ public class CdmaSystemSelectPreferenceController extends CdmaBasePreferenceCont resetCdmaRoamingModeToDefault(); } } - final int settingsNetworkMode = Settings.Global.getInt( - mContext.getContentResolver(), - Settings.Global.PREFERRED_NETWORK_MODE + mSubId, - TelephonyManager.DEFAULT_PREFERRED_NETWORK_MODE); + + final int settingsNetworkMode = MobileNetworkUtils.getNetworkTypeFromRaf( + (int) mTelephonyManager.getAllowedNetworkTypesForReason( + TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER)); final boolean enableList = settingsNetworkMode != NETWORK_MODE_LTE_GSM_WCDMA && settingsNetworkMode != NETWORK_MODE_NR_LTE_GSM_WCDMA; listPreference.setEnabled(enableList); diff --git a/src/com/android/settings/network/telephony/gsm/AutoSelectPreferenceController.java b/src/com/android/settings/network/telephony/gsm/AutoSelectPreferenceController.java index d98136290e1..63df1d2165a 100644 --- a/src/com/android/settings/network/telephony/gsm/AutoSelectPreferenceController.java +++ b/src/com/android/settings/network/telephony/gsm/AutoSelectPreferenceController.java @@ -24,6 +24,7 @@ import android.app.settings.SettingsEnums; import android.content.Context; import android.os.Bundle; import android.os.Handler; +import android.os.HandlerExecutor; import android.os.Looper; import android.os.PersistableBundle; import android.os.SystemClock; @@ -43,7 +44,7 @@ import androidx.preference.SwitchPreference; import com.android.settings.R; import com.android.settings.core.SubSettingLauncher; -import com.android.settings.network.PreferredNetworkModeContentObserver; +import com.android.settings.network.AllowedNetworkTypesListener; import com.android.settings.network.telephony.MobileNetworkUtils; import com.android.settings.network.telephony.NetworkSelectSettings; import com.android.settings.network.telephony.TelephonyTogglePreferenceController; @@ -62,7 +63,7 @@ public class AutoSelectPreferenceController extends TelephonyTogglePreferenceCon private final Handler mUiHandler; private PreferenceScreen mPreferenceScreen; - private PreferredNetworkModeContentObserver mPreferredNetworkModeObserver; + private AllowedNetworkTypesListener mAllowedNetworkTypesListener; private TelephonyManager mTelephonyManager; private boolean mOnlyAutoSelectInHome; private List mListeners; @@ -77,8 +78,9 @@ public class AutoSelectPreferenceController extends TelephonyTogglePreferenceCon mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; mListeners = new ArrayList<>(); mUiHandler = new Handler(Looper.getMainLooper()); - mPreferredNetworkModeObserver = new PreferredNetworkModeContentObserver(mUiHandler); - mPreferredNetworkModeObserver.setPreferredNetworkModeChangedListener( + mAllowedNetworkTypesListener = new AllowedNetworkTypesListener( + new HandlerExecutor(mUiHandler)); + mAllowedNetworkTypesListener.setAllowedNetworkTypesChangedListener( () -> updatePreference()); } @@ -93,12 +95,12 @@ public class AutoSelectPreferenceController extends TelephonyTogglePreferenceCon @OnLifecycleEvent(ON_START) public void onStart() { - mPreferredNetworkModeObserver.register(mContext, mSubId); + mAllowedNetworkTypesListener.register(mContext, mSubId); } @OnLifecycleEvent(ON_STOP) public void onStop() { - mPreferredNetworkModeObserver.unregister(mContext); + mAllowedNetworkTypesListener.unregister(mContext, mSubId); } @Override diff --git a/src/com/android/settings/network/telephony/gsm/OpenNetworkSelectPagePreferenceController.java b/src/com/android/settings/network/telephony/gsm/OpenNetworkSelectPagePreferenceController.java index 2cc5bf1bbef..1b77c6dd309 100644 --- a/src/com/android/settings/network/telephony/gsm/OpenNetworkSelectPagePreferenceController.java +++ b/src/com/android/settings/network/telephony/gsm/OpenNetworkSelectPagePreferenceController.java @@ -22,8 +22,6 @@ import static androidx.lifecycle.Lifecycle.Event.ON_STOP; import android.app.settings.SettingsEnums; import android.content.Context; import android.os.Bundle; -import android.os.Handler; -import android.os.Looper; import android.provider.Settings; import android.telephony.ServiceState; import android.telephony.SubscriptionManager; @@ -38,7 +36,7 @@ import androidx.preference.PreferenceScreen; import com.android.settings.R; import com.android.settings.core.SubSettingLauncher; -import com.android.settings.network.PreferredNetworkModeContentObserver; +import com.android.settings.network.AllowedNetworkTypesListener; import com.android.settings.network.telephony.MobileNetworkUtils; import com.android.settings.network.telephony.NetworkSelectSettings; import com.android.settings.network.telephony.TelephonyBasePreferenceController; @@ -54,15 +52,15 @@ public class OpenNetworkSelectPagePreferenceController extends private TelephonyManager mTelephonyManager; private Preference mPreference; private PreferenceScreen mPreferenceScreen; - private PreferredNetworkModeContentObserver mPreferredNetworkModeObserver; + private AllowedNetworkTypesListener mAllowedNetworkTypesListener; public OpenNetworkSelectPagePreferenceController(Context context, String key) { super(context, key); mTelephonyManager = context.getSystemService(TelephonyManager.class); mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; - mPreferredNetworkModeObserver = new PreferredNetworkModeContentObserver( - new Handler(Looper.getMainLooper())); - mPreferredNetworkModeObserver.setPreferredNetworkModeChangedListener( + mAllowedNetworkTypesListener = new AllowedNetworkTypesListener( + context.getMainExecutor()); + mAllowedNetworkTypesListener.setAllowedNetworkTypesChangedListener( () -> updatePreference()); } @@ -85,12 +83,12 @@ public class OpenNetworkSelectPagePreferenceController extends @OnLifecycleEvent(ON_START) public void onStart() { - mPreferredNetworkModeObserver.register(mContext, mSubId); + mAllowedNetworkTypesListener.register(mContext, mSubId); } @OnLifecycleEvent(ON_STOP) public void onStop() { - mPreferredNetworkModeObserver.unregister(mContext); + mAllowedNetworkTypesListener.unregister(mContext, mSubId); } @Override diff --git a/tests/robotests/src/com/android/settings/network/telephony/PreferredNetworkModePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/telephony/PreferredNetworkModePreferenceControllerTest.java index 1feb08b35d2..c64381509ca 100644 --- a/tests/robotests/src/com/android/settings/network/telephony/PreferredNetworkModePreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/network/telephony/PreferredNetworkModePreferenceControllerTest.java @@ -18,17 +18,20 @@ package com.android.settings.network.telephony; import static com.android.settings.core.BasePreferenceController.AVAILABLE; import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE; -import static com.android.settings.network.telephony.MobileNetworkUtils.getRafFromNetworkType; +import static com.android.settings.network.telephony.TelephonyConstants.RadioAccessFamily.GSM; +import static com.android.settings.network.telephony.TelephonyConstants.RadioAccessFamily.RAF_TD_SCDMA; +import static com.android.settings.network.telephony.TelephonyConstants.RadioAccessFamily.WCDMA; import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.content.Context; import android.os.PersistableBundle; -import android.provider.Settings; import android.telephony.CarrierConfigManager; import android.telephony.ServiceState; import android.telephony.SubscriptionManager; @@ -127,9 +130,10 @@ public class PreferredNetworkModePreferenceControllerTest { @Test public void updateState_updateByNetworkMode() { - Settings.Global.putInt(mContext.getContentResolver(), - Settings.Global.PREFERRED_NETWORK_MODE + SUB_ID, - TelephonyManagerConstants.NETWORK_MODE_TDSCDMA_GSM_WCDMA); + // NETWORK_MODE_TDSCDMA_GSM_WCDMA = RAF_TD_SCDMA | GSM | WCDMA + when(mTelephonyManager.getAllowedNetworkTypesForReason( + TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER)).thenReturn( + (long) (RAF_TD_SCDMA | GSM | WCDMA)); mController.updateState(mPreference); @@ -140,28 +144,13 @@ public class PreferredNetworkModePreferenceControllerTest { } @Test - public void onPreferenceChange_updateSuccess() { - doReturn(true).when(mTelephonyManager).setPreferredNetworkTypeBitmask( - getRafFromNetworkType(TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA)); - + public void onPreferenceChange_updateNetworkMode() { mController.onPreferenceChange(mPreference, String.valueOf(TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA)); - assertThat(Settings.Global.getInt(mContext.getContentResolver(), - Settings.Global.PREFERRED_NETWORK_MODE + SUB_ID, 0)).isEqualTo( - TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA); - } - - @Test - public void onPreferenceChange_updateFail() { - doReturn(false).when(mTelephonyManager).setPreferredNetworkTypeBitmask( - getRafFromNetworkType(TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA)); - - mController.onPreferenceChange(mPreference, - String.valueOf(TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA)); - - assertThat(Settings.Global.getInt(mContext.getContentResolver(), - Settings.Global.PREFERRED_NETWORK_MODE + SUB_ID, 0)).isNotEqualTo( - TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA); + verify(mTelephonyManager, times(1)).setAllowedNetworkTypesForReason( + TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER, + MobileNetworkUtils.getRafFromNetworkType( + TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA)); } } diff --git a/tests/unit/src/com/android/settings/network/AllowedNetworkTypesListenerTest.java b/tests/unit/src/com/android/settings/network/AllowedNetworkTypesListenerTest.java new file mode 100644 index 00000000000..3387368e64a --- /dev/null +++ b/tests/unit/src/com/android/settings/network/AllowedNetworkTypesListenerTest.java @@ -0,0 +1,101 @@ +/* + * 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.network; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.os.HandlerExecutor; +import android.telephony.PhoneStateListener; +import android.telephony.RadioAccessFamily; +import android.telephony.TelephonyManager; +import android.test.mock.MockContentResolver; + +import androidx.test.annotation.UiThreadTest; +import androidx.test.core.app.ApplicationProvider; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import java.util.HashMap; +import java.util.Map; + +@RunWith(AndroidJUnit4.class) +public class AllowedNetworkTypesListenerTest { + + private static final int SUB_ID = 1; + + private Context mContext; + private MockContentResolver mResolver; + private AllowedNetworkTypesListener mAllowedNetworkTypesListener; + + @Mock + private AllowedNetworkTypesListener.OnAllowedNetworkTypesChangedListener mListener; + @Mock + private TelephonyManager mTelephonyManager; + + + @Before + @UiThreadTest + public void setUp() { + MockitoAnnotations.initMocks(this); + mContext = spy(ApplicationProvider.getApplicationContext()); + when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager); + doReturn(mTelephonyManager).when(mTelephonyManager).createForSubscriptionId(SUB_ID); + + mAllowedNetworkTypesListener = + spy(new AllowedNetworkTypesListener(mContext.getMainExecutor())); + } + + @Test + public void onChange_shouldCallListener() { + mAllowedNetworkTypesListener.mListener = mListener; + Map allowedNetworkTypesList = new HashMap<>(); + long networkType = (long) RadioAccessFamily.getRafFromNetworkType( + TelephonyManager.NETWORK_MODE_LTE_CDMA_EVDO); + allowedNetworkTypesList.put(TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER, + networkType); + mAllowedNetworkTypesListener.onAllowedNetworkTypesChanged(allowedNetworkTypesList); + + verify(mListener).onAllowedNetworkTypesChanged(); + } + + @Test + public void register_shouldRegisterContentObserver() { + mAllowedNetworkTypesListener.register(mContext, SUB_ID); + + verify(mTelephonyManager, times(1)).registerPhoneStateListener(any(HandlerExecutor.class), + any(PhoneStateListener.class)); + } + + @Test + public void unregister_shouldUnregisterContentObserver() { + mAllowedNetworkTypesListener.unregister(mContext, SUB_ID); + + verify(mTelephonyManager).unregisterPhoneStateListener( + mAllowedNetworkTypesListener); + } +} diff --git a/tests/robotests/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceControllerTest.java b/tests/unit/src/com/android/settings/network/EnabledNetworkModePreferenceControllerTest.java similarity index 68% rename from tests/robotests/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceControllerTest.java rename to tests/unit/src/com/android/settings/network/EnabledNetworkModePreferenceControllerTest.java index ca36f1f83c8..81841b73760 100644 --- a/tests/robotests/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceControllerTest.java +++ b/tests/unit/src/com/android/settings/network/EnabledNetworkModePreferenceControllerTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018 The Android Open Source Project + * 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. @@ -21,21 +21,23 @@ import static androidx.lifecycle.Lifecycle.Event.ON_START; import static com.android.settings.core.BasePreferenceController.AVAILABLE; import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE; import static com.android.settings.network.telephony.MobileNetworkUtils.getRafFromNetworkType; +import static com.android.settings.network.telephony.TelephonyConstants.RadioAccessFamily.CDMA; +import static com.android.settings.network.telephony.TelephonyConstants.RadioAccessFamily.EVDO; +import static com.android.settings.network.telephony.TelephonyConstants.RadioAccessFamily.GSM; +import static com.android.settings.network.telephony.TelephonyConstants.RadioAccessFamily.LTE; +import static com.android.settings.network.telephony.TelephonyConstants.RadioAccessFamily.NR; +import static com.android.settings.network.telephony.TelephonyConstants.RadioAccessFamily.RAF_TD_SCDMA; +import static com.android.settings.network.telephony.TelephonyConstants.RadioAccessFamily.WCDMA; import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertEquals; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; import android.content.Context; -import android.net.Uri; import android.os.PersistableBundle; -import android.provider.Settings; import android.telephony.CarrierConfigManager; import android.telephony.ServiceState; import android.telephony.SubscriptionManager; @@ -43,9 +45,12 @@ import android.telephony.TelephonyManager; import androidx.lifecycle.LifecycleOwner; import androidx.preference.ListPreference; +import androidx.preference.PreferenceManager; import androidx.preference.PreferenceScreen; +import androidx.test.annotation.UiThreadTest; +import androidx.test.core.app.ApplicationProvider; +import androidx.test.ext.junit.runners.AndroidJUnit4; -import com.android.settings.R; import com.android.settings.network.telephony.TelephonyConstants.TelephonyManagerConstants; import com.android.settingslib.core.lifecycle.Lifecycle; @@ -54,10 +59,8 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; -import org.robolectric.RobolectricTestRunner; -import org.robolectric.RuntimeEnvironment; -@RunWith(RobolectricTestRunner.class) +@RunWith(AndroidJUnit4.class) public class EnabledNetworkModePreferenceControllerTest { private static final int SUB_ID = 2; public static final String KEY = "enabled_network"; @@ -81,19 +84,21 @@ public class EnabledNetworkModePreferenceControllerTest { private LifecycleOwner mLifecycleOwner; private Lifecycle mLifecycle; + @UiThreadTest @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); mLifecycleOwner = () -> mLifecycle; mLifecycle = new Lifecycle(mLifecycleOwner); - mContext = spy(RuntimeEnvironment.application); - doReturn(mTelephonyManager).when(mContext).getSystemService(Context.TELEPHONY_SERVICE); - doReturn(mTelephonyManager).when(mContext).getSystemService(TelephonyManager.class); - doReturn(mCarrierConfigManager).when(mContext).getSystemService(CarrierConfigManager.class); + mContext = spy(ApplicationProvider.getApplicationContext()); + + when(mContext.getSystemService(CarrierConfigManager.class)).thenReturn( + mCarrierConfigManager); + when(mContext.getSystemService(Context.TELEPHONY_SERVICE)).thenReturn(mTelephonyManager); + when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager); doReturn(mTelephonyManager).when(mTelephonyManager).createForSubscriptionId(SUB_ID); doReturn(mInvalidTelephonyManager).when(mTelephonyManager).createForSubscriptionId( SubscriptionManager.INVALID_SUBSCRIPTION_ID); - doReturn(mContext).when(mContext).createPackageContext(anyString(), anyInt()); doReturn(mServiceState).when(mTelephonyManager).getServiceState(); mPersistableBundle = new PersistableBundle(); doReturn(mPersistableBundle).when(mCarrierConfigManager).getConfig(); @@ -106,6 +111,7 @@ public class EnabledNetworkModePreferenceControllerTest { mPreference.setKey(mController.getPreferenceKey()); } + @UiThreadTest @Test public void getAvailabilityStatus_hideCarrierNetworkSettings_returnUnavailable() { mPersistableBundle.putBoolean( @@ -115,6 +121,7 @@ public class EnabledNetworkModePreferenceControllerTest { assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE); } + @UiThreadTest @Test public void getAvailabilityStatus_hidePreferredNetworkType_returnUnavailable() { mPersistableBundle.putBoolean(CarrierConfigManager.KEY_HIDE_PREFERRED_NETWORK_TYPE_BOOL, @@ -135,6 +142,7 @@ public class EnabledNetworkModePreferenceControllerTest { assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE); } + @UiThreadTest @Test public void getAvailabilityStatus_notWorldPhone_returnAvailable() { mPersistableBundle.putBoolean(CarrierConfigManager.KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL, @@ -144,6 +152,7 @@ public class EnabledNetworkModePreferenceControllerTest { assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE); } + @UiThreadTest @Test public void updateState_LteWorldPhone_GlobalHasLte() { mPersistableBundle.putBoolean(CarrierConfigManager.KEY_WORLD_MODE_ENABLED_BOOL, true); @@ -155,9 +164,10 @@ public class EnabledNetworkModePreferenceControllerTest { .contains(String.valueOf(TelephonyManager.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA)); } + @UiThreadTest @Test public void updateState_5gWorldPhone_GlobalHasNr() { - mPersistableBundle.putBoolean(CarrierConfigManager.KEY_NR_ENABLED_BOOL, true); + mockAllowedNetworkTypes(ALLOWED_ALL_NETWORK_TYPE); mockAccessFamily(TelephonyManager.NETWORK_MODE_NR_LTE_CDMA_EVDO_GSM_WCDMA); mController.init(mLifecycle, SUB_ID); mPersistableBundle.putBoolean(CarrierConfigManager.KEY_WORLD_MODE_ENABLED_BOOL, true); @@ -169,15 +179,18 @@ public class EnabledNetworkModePreferenceControllerTest { .contains(String.valueOf(TelephonyManager.NETWORK_MODE_NR_LTE_CDMA_EVDO_GSM_WCDMA)); } + @UiThreadTest @Test public void updateState_selectedOn5gItem() { - mPersistableBundle.putBoolean(CarrierConfigManager.KEY_NR_ENABLED_BOOL, true); + mockAllowedNetworkTypes(ALLOWED_ALL_NETWORK_TYPE); mockEnabledNetworkMode(TelephonyManagerConstants.NETWORK_MODE_NR_LTE_TDSCDMA_GSM_WCDMA); mockAccessFamily(TelephonyManager.NETWORK_MODE_NR_LTE_TDSCDMA_GSM_WCDMA); mController.init(mLifecycle, SUB_ID); - Settings.Global.putInt(mContext.getContentResolver(), - Settings.Global.PREFERRED_NETWORK_MODE + SUB_ID, - TelephonyManagerConstants.NETWORK_MODE_NR_LTE_TDSCDMA_GSM_WCDMA); + + // NETWORK_MODE_NR_LTE_TDSCDMA_GSM_WCDMA = NR | LTE | RAF_TD_SCDMA | GSM | WCDMA + when(mTelephonyManager.getAllowedNetworkTypesForReason( + TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER)).thenReturn( + (long) (NR | LTE | RAF_TD_SCDMA | GSM | WCDMA)); mController.updateState(mPreference); @@ -186,16 +199,18 @@ public class EnabledNetworkModePreferenceControllerTest { TelephonyManagerConstants.NETWORK_MODE_NR_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA)); } + @UiThreadTest @Test public void updateState_disAllowed5g_5gOptionHidden() { mockEnabledNetworkMode(TelephonyManagerConstants.NETWORK_MODE_NR_LTE_TDSCDMA_GSM_WCDMA); mockAccessFamily(TelephonyManager.NETWORK_MODE_NR_LTE_TDSCDMA_GSM_WCDMA); mockAllowedNetworkTypes(DISABLED_5G_NETWORK_TYPE); mController.init(mLifecycle, SUB_ID); - Settings.Global.putInt(mContext.getContentResolver(), - Settings.Global.PREFERRED_NETWORK_MODE + SUB_ID, - TelephonyManagerConstants.NETWORK_MODE_NR_LTE_TDSCDMA_GSM_WCDMA); + // NETWORK_MODE_NR_LTE_TDSCDMA_GSM_WCDMA = NR | LTE | RAF_TD_SCDMA | GSM | WCDMA + when(mTelephonyManager.getAllowedNetworkTypesForReason( + TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER)).thenReturn( + (long) (NR | LTE | RAF_TD_SCDMA | GSM | WCDMA)); mController.updateState(mPreference); assertThat(mPreference.getEntryValues()) @@ -204,16 +219,18 @@ public class EnabledNetworkModePreferenceControllerTest { String.valueOf(TelephonyManager.NETWORK_MODE_NR_LTE_CDMA_EVDO_GSM_WCDMA)); } + @UiThreadTest @Test public void updateState_disAllowed5g_selectOn4gOption() { mockEnabledNetworkMode(TelephonyManagerConstants.NETWORK_MODE_NR_LTE_TDSCDMA_GSM_WCDMA); mockAccessFamily(TelephonyManager.NETWORK_MODE_NR_LTE_TDSCDMA_GSM_WCDMA); mockAllowedNetworkTypes(DISABLED_5G_NETWORK_TYPE); mController.init(mLifecycle, SUB_ID); - Settings.Global.putInt(mContext.getContentResolver(), - Settings.Global.PREFERRED_NETWORK_MODE + SUB_ID, - TelephonyManagerConstants.NETWORK_MODE_NR_LTE_TDSCDMA_GSM_WCDMA); + // NETWORK_MODE_NR_LTE_TDSCDMA_GSM_WCDMA = NR | LTE | RAF_TD_SCDMA | GSM | WCDMA + when(mTelephonyManager.getAllowedNetworkTypesForReason( + TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER)).thenReturn( + (long) (NR | LTE | RAF_TD_SCDMA | GSM | WCDMA)); mController.updateState(mPreference); assertThat(mPreference.getValue()).isEqualTo( @@ -221,38 +238,43 @@ public class EnabledNetworkModePreferenceControllerTest { TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA)); } + @UiThreadTest @Test public void updateState_NrEnableBoolFalse_5gOptionHidden() { mockEnabledNetworkMode(TelephonyManagerConstants.NETWORK_MODE_NR_LTE_GSM_WCDMA); mockAccessFamily(TelephonyManager.NETWORK_MODE_NR_LTE_CDMA_EVDO_GSM_WCDMA); - mPersistableBundle.putBoolean(CarrierConfigManager.KEY_NR_ENABLED_BOOL, false); + mockAllowedNetworkTypes(DISABLED_5G_NETWORK_TYPE); mController.init(mLifecycle, SUB_ID); - Settings.Global.putInt(mContext.getContentResolver(), - Settings.Global.PREFERRED_NETWORK_MODE + SUB_ID, - TelephonyManagerConstants.NETWORK_MODE_NR_LTE_GSM_WCDMA); + + // NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA = LTE | CDMA | EVDO | GSM | WCDMA + when(mTelephonyManager.getAllowedNetworkTypesForReason( + TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER)).thenReturn( + (long) (LTE | CDMA | EVDO | GSM | WCDMA)); mController.updateState(mPreference); assertThat(mPreference.getValue()).isEqualTo( String.valueOf( - TelephonyManagerConstants.NETWORK_MODE_LTE_GSM_WCDMA)); + TelephonyManagerConstants.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA)); assertThat(mPreference.getEntryValues()) .asList() .doesNotContain( String.valueOf(TelephonyManager.NETWORK_MODE_NR_LTE_GSM_WCDMA)); } + @UiThreadTest @Test public void updateState_GlobalDisAllowed5g_GlobalWithoutNR() { mockAccessFamily(TelephonyManager.NETWORK_MODE_NR_LTE_CDMA_EVDO_GSM_WCDMA); mockAllowedNetworkTypes(DISABLED_5G_NETWORK_TYPE); mController.init(mLifecycle, SUB_ID); mPersistableBundle.putBoolean(CarrierConfigManager.KEY_WORLD_MODE_ENABLED_BOOL, true); - Settings.Global.putInt(mContext.getContentResolver(), - Settings.Global.PREFERRED_NETWORK_MODE + SUB_ID, - TelephonyManagerConstants.NETWORK_MODE_NR_LTE_CDMA_EVDO_GSM_WCDMA); + // NETWORK_MODE_NR_LTE_CDMA_EVDO_GSM_WCDMA = NR | LTE | CDMA | EVDO | GSM | WCDMA + when(mTelephonyManager.getAllowedNetworkTypesForReason( + TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER)).thenReturn( + (long) (NR | LTE | CDMA | EVDO | GSM | WCDMA)); mController.updateState(mPreference); assertThat(mPreference.getEntryValues()) @@ -261,16 +283,18 @@ public class EnabledNetworkModePreferenceControllerTest { String.valueOf(TelephonyManager.NETWORK_MODE_NR_LTE_CDMA_EVDO_GSM_WCDMA)); } + @UiThreadTest @Test public void updateState_GlobalDisAllowed5g_SelectOnGlobal() { mockAccessFamily(TelephonyManager.NETWORK_MODE_NR_LTE_CDMA_EVDO_GSM_WCDMA); mockAllowedNetworkTypes(DISABLED_5G_NETWORK_TYPE); mController.init(mLifecycle, SUB_ID); mPersistableBundle.putBoolean(CarrierConfigManager.KEY_WORLD_MODE_ENABLED_BOOL, true); - Settings.Global.putInt(mContext.getContentResolver(), - Settings.Global.PREFERRED_NETWORK_MODE + SUB_ID, - TelephonyManagerConstants.NETWORK_MODE_NR_LTE_CDMA_EVDO_GSM_WCDMA); + // NETWORK_MODE_NR_LTE_CDMA_EVDO_GSM_WCDMA = NR | LTE | CDMA | EVDO | GSM | WCDMA + when(mTelephonyManager.getAllowedNetworkTypesForReason( + TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER)).thenReturn( + (long) (NR | LTE | CDMA | EVDO | GSM | WCDMA)); mController.updateState(mPreference); assertThat(mPreference.getValue()).isEqualTo( @@ -278,13 +302,15 @@ public class EnabledNetworkModePreferenceControllerTest { TelephonyManagerConstants.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA)); } + @UiThreadTest @Test public void updateState_updateByNetworkMode() { mockEnabledNetworkMode(TelephonyManagerConstants.NETWORK_MODE_TDSCDMA_GSM_WCDMA); - Settings.Global.putInt(mContext.getContentResolver(), - Settings.Global.PREFERRED_NETWORK_MODE + SUB_ID, - TelephonyManagerConstants.NETWORK_MODE_TDSCDMA_GSM_WCDMA); + // NETWORK_MODE_TDSCDMA_GSM_WCDMA = RAF_TD_SCDMA | GSM | WCDMA + when(mTelephonyManager.getAllowedNetworkTypesForReason( + TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER)).thenReturn( + (long) (RAF_TD_SCDMA | GSM | WCDMA)); mController.updateState(mPreference); assertThat(mPreference.getValue()).isEqualTo( @@ -292,33 +318,38 @@ public class EnabledNetworkModePreferenceControllerTest { assertThat(mPreference.getSummary()).isEqualTo("3G"); } + @UiThreadTest @Test public void updateState_updateByNetworkMode_useDefaultValue() { mockEnabledNetworkMode(TelephonyManagerConstants.NETWORK_MODE_LTE_GSM_WCDMA); - Settings.Global.putInt(mContext.getContentResolver(), - Settings.Global.PREFERRED_NETWORK_MODE + SUB_ID, - TelephonyManagerConstants.NETWORK_MODE_LTE_GSM_WCDMA); + // NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA = LTE | CDMA | EVDO | GSM | WCDMA + when(mTelephonyManager.getAllowedNetworkTypesForReason( + TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER)).thenReturn( + (long) (LTE | CDMA | EVDO | GSM | WCDMA)); mController.updateState(mPreference); assertThat(mPreference.getValue()).isEqualTo( - String.valueOf(TelephonyManagerConstants.NETWORK_MODE_LTE_GSM_WCDMA)); + String.valueOf(TelephonyManagerConstants.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA)); } + @UiThreadTest @Test public void onPreferenceChange_updateSuccess() { mockEnabledNetworkMode(TelephonyManagerConstants.NETWORK_MODE_LTE_GSM_WCDMA); doReturn(true).when(mTelephonyManager).setPreferredNetworkTypeBitmask( - getRafFromNetworkType(TelephonyManagerConstants.NETWORK_MODE_LTE_GSM_WCDMA)); + getRafFromNetworkType( + TelephonyManagerConstants.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA)); mController.updateState(mPreference); mController.onPreferenceChange(mPreference, - String.valueOf(TelephonyManagerConstants.NETWORK_MODE_LTE_GSM_WCDMA)); + String.valueOf(TelephonyManagerConstants.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA)); assertThat(mPreference.getValue()).isEqualTo( - String.valueOf(TelephonyManagerConstants.NETWORK_MODE_LTE_GSM_WCDMA)); + String.valueOf(TelephonyManagerConstants.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA)); } + @UiThreadTest @Test public void onPreferenceChange_updateFail() { mockEnabledNetworkMode(TelephonyManagerConstants.NETWORK_MODE_LTE_GSM_WCDMA); @@ -333,14 +364,21 @@ public class EnabledNetworkModePreferenceControllerTest { String.valueOf(TelephonyManagerConstants.NETWORK_MODE_LTE_GSM_WCDMA)); } + @UiThreadTest @Test public void preferredNetworkModeNotification_preferenceUpdates() { - PreferenceScreen screen = mock(PreferenceScreen.class); + + final PreferenceManager preferenceManager = new PreferenceManager(mContext); + PreferenceScreen screen = preferenceManager.createPreferenceScreen(mContext); + mPreference.setKey(KEY); + screen.addPreference(mPreference); mockEnabledNetworkMode(TelephonyManagerConstants.NETWORK_MODE_TDSCDMA_GSM_WCDMA); - doReturn(mPreference).when(screen).findPreference(KEY); - Settings.Global.putInt(mContext.getContentResolver(), - Settings.Global.PREFERRED_NETWORK_MODE + SUB_ID, - TelephonyManagerConstants.NETWORK_MODE_TDSCDMA_GSM_WCDMA); + + // NETWORK_MODE_TDSCDMA_GSM_WCDMA = RAF_TD_SCDMA | GSM | WCDMA + when(mTelephonyManager.getAllowedNetworkTypesForReason( + TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER)).thenReturn( + (long) (RAF_TD_SCDMA | GSM | WCDMA)); + mController.displayPreference(screen); mController.updateState(mPreference); mLifecycle.handleLifecycleEvent(ON_START); @@ -348,59 +386,59 @@ public class EnabledNetworkModePreferenceControllerTest { assertThat(Integer.parseInt(mPreference.getValue())).isEqualTo( TelephonyManagerConstants.NETWORK_MODE_TDSCDMA_GSM_WCDMA); assertThat(mPreference.getSummary()).isEqualTo("3G"); - - - Settings.Global.putInt(mContext.getContentResolver(), - Settings.Global.PREFERRED_NETWORK_MODE + SUB_ID, - TelephonyManagerConstants.NETWORK_MODE_GSM_ONLY); - final Uri uri = Settings.Global.getUriFor(Settings.Global.PREFERRED_NETWORK_MODE + SUB_ID); - mContext.getContentResolver().notifyChange(uri, null); - - assertThat(Integer.parseInt(mPreference.getValue())).isEqualTo( - TelephonyManagerConstants.NETWORK_MODE_GSM_ONLY); - assertThat(mPreference.getSummary()).isEqualTo("2G"); } + @UiThreadTest @Test public void checkResource_stringArrayLength() { - String[] entryValues = mController.getResourcesForSubId().getStringArray( - R.array.enabled_networks_cdma_values); + int id = mController.getResourcesForSubId().getIdentifier("enabled_networks_cdma_values", + "array", mContext.getPackageName()); + String[] entryValues = mController.getResourcesForSubId().getStringArray(id); assertEquals(4, entryValues.length); - entryValues = mController.getResourcesForSubId().getStringArray( - R.array.enabled_networks_cdma_no_lte_values); + id = mController.getResourcesForSubId().getIdentifier("enabled_networks_cdma_no_lte_values", + "array", mContext.getPackageName()); + entryValues = mController.getResourcesForSubId().getStringArray(id); assertEquals(2, entryValues.length); - entryValues = mController.getResourcesForSubId().getStringArray( - R.array.enabled_networks_cdma_only_lte_values); + id = mController.getResourcesForSubId().getIdentifier( + "enabled_networks_cdma_only_lte_values", "array", mContext.getPackageName()); + entryValues = mController.getResourcesForSubId().getStringArray(id); assertEquals(2, entryValues.length); - entryValues = mController.getResourcesForSubId().getStringArray( - R.array.enabled_networks_tdscdma_values); + id = mController.getResourcesForSubId().getIdentifier("enabled_networks_tdscdma_values", + "array", mContext.getPackageName()); + entryValues = mController.getResourcesForSubId().getStringArray(id); assertEquals(3, entryValues.length); - entryValues = mController.getResourcesForSubId().getStringArray( - R.array.enabled_networks_except_gsm_lte_values); + id = mController.getResourcesForSubId().getIdentifier( + "enabled_networks_except_gsm_lte_values", "array", mContext.getPackageName()); + entryValues = mController.getResourcesForSubId().getStringArray(id); assertEquals(1, entryValues.length); - entryValues = mController.getResourcesForSubId().getStringArray( - R.array.enabled_networks_except_gsm_values); + id = mController.getResourcesForSubId().getIdentifier("enabled_networks_except_gsm_values", + "array", mContext.getPackageName()); + entryValues = mController.getResourcesForSubId().getStringArray(id); assertEquals(2, entryValues.length); - entryValues = mController.getResourcesForSubId().getStringArray( - R.array.enabled_networks_except_lte_values); + id = mController.getResourcesForSubId().getIdentifier("enabled_networks_except_lte_values", + "array", mContext.getPackageName()); + entryValues = mController.getResourcesForSubId().getStringArray(id); assertEquals(2, entryValues.length); - entryValues = mController.getResourcesForSubId().getStringArray( - R.array.enabled_networks_values); + id = mController.getResourcesForSubId().getIdentifier("enabled_networks_values", "array", + mContext.getPackageName()); + entryValues = mController.getResourcesForSubId().getStringArray(id); assertEquals(3, entryValues.length); - entryValues = mController.getResourcesForSubId().getStringArray( - R.array.enabled_networks_values); + id = mController.getResourcesForSubId().getIdentifier("enabled_networks_values", "array", + mContext.getPackageName()); + entryValues = mController.getResourcesForSubId().getStringArray(id); assertEquals(3, entryValues.length); - entryValues = mController.getResourcesForSubId().getStringArray( - R.array.preferred_network_mode_values_world_mode); + id = mController.getResourcesForSubId().getIdentifier( + "preferred_network_mode_values_world_mode", "array", mContext.getPackageName()); + entryValues = mController.getResourcesForSubId().getStringArray(id); assertEquals(3, entryValues.length); } @@ -408,15 +446,17 @@ public class EnabledNetworkModePreferenceControllerTest { if (networkMode == TelephonyManagerConstants.NETWORK_MODE_TDSCDMA_GSM_WCDMA) { mockPhoneType(TelephonyManager.PHONE_TYPE_GSM); mPersistableBundle.putBoolean(CarrierConfigManager.KEY_SUPPORT_TDSCDMA_BOOL, true); - } else if (networkMode == TelephonyManagerConstants.NETWORK_MODE_LTE_GSM_WCDMA) { + } else if (networkMode == TelephonyManagerConstants.NETWORK_MODE_LTE_GSM_WCDMA + || networkMode == TelephonyManagerConstants.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA) { mockPhoneType(TelephonyManager.PHONE_TYPE_GSM); mPersistableBundle.putBoolean(CarrierConfigManager.KEY_PREFER_2G_BOOL, true); mPersistableBundle.putBoolean(CarrierConfigManager.KEY_LTE_ENABLED_BOOL, true); } else if (networkMode == TelephonyManagerConstants.NETWORK_MODE_NR_LTE_TDSCDMA_GSM_WCDMA) { mockPhoneType(TelephonyManager.PHONE_TYPE_GSM); mPersistableBundle.putBoolean(CarrierConfigManager.KEY_SUPPORT_TDSCDMA_BOOL, true); - } else if (networkMode - == TelephonyManagerConstants.NETWORK_MODE_NR_LTE_GSM_WCDMA) { + } else if (networkMode == TelephonyManagerConstants.NETWORK_MODE_NR_LTE_GSM_WCDMA + || networkMode + == TelephonyManagerConstants.NETWORK_MODE_NR_LTE_CDMA_EVDO_GSM_WCDMA) { mockPhoneType(TelephonyManager.PHONE_TYPE_GSM); mPersistableBundle.putBoolean(CarrierConfigManager.KEY_PREFER_2G_BOOL, true); mPersistableBundle.putBoolean(CarrierConfigManager.KEY_LTE_ENABLED_BOOL, true); @@ -424,7 +464,8 @@ public class EnabledNetworkModePreferenceControllerTest { } private void mockAllowedNetworkTypes(long allowedNetworkType) { - doReturn(allowedNetworkType).when(mTelephonyManager).getAllowedNetworkTypes(); + doReturn(allowedNetworkType).when(mTelephonyManager).getAllowedNetworkTypesForReason( + TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_CARRIER); } private void mockAccessFamily(int networkMode) { diff --git a/tests/unit/src/com/android/settings/network/PreferredNetworkModeContentObserverTest.java b/tests/unit/src/com/android/settings/network/PreferredNetworkModeContentObserverTest.java deleted file mode 100644 index e07a8f140e0..00000000000 --- a/tests/unit/src/com/android/settings/network/PreferredNetworkModeContentObserverTest.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * 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.network; - -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.content.Context; -import android.provider.Settings; -import android.test.mock.MockContentResolver; - -import androidx.test.core.app.ApplicationProvider; -import androidx.test.ext.junit.runners.AndroidJUnit4; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -@RunWith(AndroidJUnit4.class) -public class PreferredNetworkModeContentObserverTest { - - private static final int SUB_ID = 1; - - private Context mContext; - private MockContentResolver mResolver; - private PreferredNetworkModeContentObserver mPreferredNetworkModeContentObserver; - - @Mock - private PreferredNetworkModeContentObserver.OnPreferredNetworkModeChangedListener mListener; - - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - mContext = spy(ApplicationProvider.getApplicationContext()); - - mResolver = spy(new MockContentResolver(mContext)); - when(mContext.getContentResolver()).thenReturn(mResolver); - mPreferredNetworkModeContentObserver = - spy(new PreferredNetworkModeContentObserver(null)); - } - - @Test - public void onChange_shouldCallListener() { - mPreferredNetworkModeContentObserver.mListener = mListener; - mPreferredNetworkModeContentObserver.onChange(true); - - verify(mListener).onPreferredNetworkModeChanged(); - } - - @Test - public void register_shouldRegisterContentObserver() { - mPreferredNetworkModeContentObserver.register(mContext, SUB_ID); - - verify(mResolver).registerContentObserver( - Settings.Global.getUriFor(Settings.Global.PREFERRED_NETWORK_MODE + SUB_ID), false, - mPreferredNetworkModeContentObserver); - } - - @Test - public void unregister_shouldUnregisterContentObserver() { - mPreferredNetworkModeContentObserver.unregister(mContext); - - verify(mResolver).unregisterContentObserver(mPreferredNetworkModeContentObserver); - } -} diff --git a/tests/unit/src/com/android/settings/network/telephony/MobileNetworkUtilsTest.java b/tests/unit/src/com/android/settings/network/telephony/MobileNetworkUtilsTest.java index ee8157d6c60..b84af2c00f4 100644 --- a/tests/unit/src/com/android/settings/network/telephony/MobileNetworkUtilsTest.java +++ b/tests/unit/src/com/android/settings/network/telephony/MobileNetworkUtilsTest.java @@ -16,6 +16,13 @@ package com.android.settings.network.telephony; +import static com.android.settings.network.telephony.TelephonyConstants.RadioAccessFamily.CDMA; +import static com.android.settings.network.telephony.TelephonyConstants.RadioAccessFamily.EVDO; +import static com.android.settings.network.telephony.TelephonyConstants.RadioAccessFamily.GSM; +import static com.android.settings.network.telephony.TelephonyConstants.RadioAccessFamily.LTE; +import static com.android.settings.network.telephony.TelephonyConstants.RadioAccessFamily.RAF_TD_SCDMA; +import static com.android.settings.network.telephony.TelephonyConstants.RadioAccessFamily.WCDMA; + import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.anyBoolean; @@ -32,7 +39,6 @@ import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.os.PersistableBundle; -import android.provider.Settings; import android.telecom.PhoneAccountHandle; import android.telephony.CarrierConfigManager; import android.telephony.SubscriptionInfo; @@ -42,8 +48,6 @@ import android.telephony.TelephonyManager; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; -import com.android.settings.network.telephony.TelephonyConstants.TelephonyManagerConstants; - import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -177,10 +181,10 @@ public class MobileNetworkUtilsTest { public void isCdmaOptions_worldModeWithGsmWcdma_returnTrue() { when(mTelephonyManager.getPhoneType()).thenReturn(TelephonyManager.PHONE_TYPE_GSM); mCarrierConfig.putBoolean(CarrierConfigManager.KEY_WORLD_MODE_ENABLED_BOOL, true); - - Settings.Global.putInt(mContext.getContentResolver(), - android.provider.Settings.Global.PREFERRED_NETWORK_MODE + SUB_ID_1, - TelephonyManagerConstants.NETWORK_MODE_LTE_GSM_WCDMA); + // NETWORK_MODE_LTE_GSM_WCDMA = LTE | GSM | WCDMA + when(mTelephonyManager.getAllowedNetworkTypesForReason( + TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER)).thenReturn( + (long) (LTE | GSM | WCDMA)); assertThat(MobileNetworkUtils.isCdmaOptions(mContext, SUB_ID_1)).isTrue(); } @@ -252,9 +256,10 @@ public class MobileNetworkUtilsTest { public void shouldSpeciallyUpdateGsmCdma_ModeLteTdscdmaGsm_returnTrue() { mCarrierConfig.putBoolean(CarrierConfigManager.KEY_WORLD_MODE_ENABLED_BOOL, true); mCarrierConfig.putBoolean(CarrierConfigManager.KEY_SUPPORT_TDSCDMA_BOOL, false); - Settings.Global.putInt(mContext.getContentResolver(), - android.provider.Settings.Global.PREFERRED_NETWORK_MODE + SUB_ID_1, - TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA_GSM); + // NETWORK_MODE_LTE_TDSCDMA_GSM = LTE | RAF_TD_SCDMA | GSM + when(mTelephonyManager.getAllowedNetworkTypesForReason( + TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER)).thenReturn( + (long) (LTE | RAF_TD_SCDMA | GSM)); assertThat(MobileNetworkUtils.shouldSpeciallyUpdateGsmCdma(mContext, SUB_ID_1)).isTrue(); } @@ -263,9 +268,10 @@ public class MobileNetworkUtilsTest { public void shouldSpeciallyUpdateGsmCdma_ModeLteTdscdmaGsmWcdma_returnTrue() { mCarrierConfig.putBoolean(CarrierConfigManager.KEY_WORLD_MODE_ENABLED_BOOL, true); mCarrierConfig.putBoolean(CarrierConfigManager.KEY_SUPPORT_TDSCDMA_BOOL, false); - Settings.Global.putInt(mContext.getContentResolver(), - android.provider.Settings.Global.PREFERRED_NETWORK_MODE + SUB_ID_1, - TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA_GSM_WCDMA); + // NETWORK_MODE_LTE_TDSCDMA_GSM_WCDMA = LTE | RAF_TD_SCDMA | GSM | WCDMA + when(mTelephonyManager.getAllowedNetworkTypesForReason( + TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER)).thenReturn( + (long) (LTE | RAF_TD_SCDMA | GSM | WCDMA)); assertThat(MobileNetworkUtils.shouldSpeciallyUpdateGsmCdma(mContext, SUB_ID_1)).isTrue(); } @@ -274,9 +280,10 @@ public class MobileNetworkUtilsTest { public void shouldSpeciallyUpdateGsmCdma_ModeLteTdscdma_returnTrue() { mCarrierConfig.putBoolean(CarrierConfigManager.KEY_WORLD_MODE_ENABLED_BOOL, true); mCarrierConfig.putBoolean(CarrierConfigManager.KEY_SUPPORT_TDSCDMA_BOOL, false); - Settings.Global.putInt(mContext.getContentResolver(), - android.provider.Settings.Global.PREFERRED_NETWORK_MODE + SUB_ID_1, - TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA); + // NETWORK_MODE_LTE_TDSCDMA = LTE | RAF_TD_SCDMA + when(mTelephonyManager.getAllowedNetworkTypesForReason( + TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER)).thenReturn( + (long) (LTE | RAF_TD_SCDMA)); assertThat(MobileNetworkUtils.shouldSpeciallyUpdateGsmCdma(mContext, SUB_ID_1)).isTrue(); } @@ -285,9 +292,10 @@ public class MobileNetworkUtilsTest { public void shouldSpeciallyUpdateGsmCdma_ModeLteTdscdmaWcdma_returnTrue() { mCarrierConfig.putBoolean(CarrierConfigManager.KEY_WORLD_MODE_ENABLED_BOOL, true); mCarrierConfig.putBoolean(CarrierConfigManager.KEY_SUPPORT_TDSCDMA_BOOL, false); - Settings.Global.putInt(mContext.getContentResolver(), - android.provider.Settings.Global.PREFERRED_NETWORK_MODE + SUB_ID_1, - TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA_WCDMA); + // NETWORK_MODE_LTE_TDSCDMA_WCDMA = LTE | RAF_TD_SCDMA | WCDMA + when(mTelephonyManager.getAllowedNetworkTypesForReason( + TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER)).thenReturn( + (long) (LTE | RAF_TD_SCDMA | WCDMA)); assertThat(MobileNetworkUtils.shouldSpeciallyUpdateGsmCdma(mContext, SUB_ID_1)).isTrue(); } @@ -296,9 +304,11 @@ public class MobileNetworkUtilsTest { public void shouldSpeciallyUpdateGsmCdma_ModeLteTdscdmaCdmaEvdoGsmWcdma_returnTrue() { mCarrierConfig.putBoolean(CarrierConfigManager.KEY_WORLD_MODE_ENABLED_BOOL, true); mCarrierConfig.putBoolean(CarrierConfigManager.KEY_SUPPORT_TDSCDMA_BOOL, false); - Settings.Global.putInt(mContext.getContentResolver(), - android.provider.Settings.Global.PREFERRED_NETWORK_MODE + SUB_ID_1, - TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA); + // NETWORK_MODE_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA + // = LTE | RAF_TD_SCDMA | CDMA | EVDO | GSM | WCDMA + when(mTelephonyManager.getAllowedNetworkTypesForReason( + TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER)).thenReturn( + (long) (LTE | RAF_TD_SCDMA | CDMA | EVDO | GSM | WCDMA)); assertThat(MobileNetworkUtils.shouldSpeciallyUpdateGsmCdma(mContext, SUB_ID_1)).isTrue(); } @@ -307,9 +317,10 @@ public class MobileNetworkUtilsTest { public void shouldSpeciallyUpdateGsmCdma_ModeLteCdmaEvdoGsmWcdma_returnTrue() { mCarrierConfig.putBoolean(CarrierConfigManager.KEY_WORLD_MODE_ENABLED_BOOL, true); mCarrierConfig.putBoolean(CarrierConfigManager.KEY_SUPPORT_TDSCDMA_BOOL, false); - Settings.Global.putInt(mContext.getContentResolver(), - android.provider.Settings.Global.PREFERRED_NETWORK_MODE + SUB_ID_1, - TelephonyManagerConstants.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA); + // NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA = LTE | CDMA | EVDO | GSM | WCDMA + when(mTelephonyManager.getAllowedNetworkTypesForReason( + TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER)).thenReturn( + (long) (LTE | CDMA | EVDO | GSM | WCDMA)); assertThat(MobileNetworkUtils.shouldSpeciallyUpdateGsmCdma(mContext, SUB_ID_1)).isTrue(); } diff --git a/tests/unit/src/com/android/settings/network/telephony/cdma/CdmaSystemSelectPreferenceControllerTest.java b/tests/unit/src/com/android/settings/network/telephony/cdma/CdmaSystemSelectPreferenceControllerTest.java index 4f44a29aae3..c8133168f40 100644 --- a/tests/unit/src/com/android/settings/network/telephony/cdma/CdmaSystemSelectPreferenceControllerTest.java +++ b/tests/unit/src/com/android/settings/network/telephony/cdma/CdmaSystemSelectPreferenceControllerTest.java @@ -16,6 +16,10 @@ package com.android.settings.network.telephony.cdma; +import static com.android.settings.network.telephony.TelephonyConstants.RadioAccessFamily.GSM; +import static com.android.settings.network.telephony.TelephonyConstants.RadioAccessFamily.LTE; +import static com.android.settings.network.telephony.TelephonyConstants.RadioAccessFamily.WCDMA; + import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.anyInt; @@ -29,11 +33,10 @@ import android.telephony.TelephonyManager; import androidx.preference.ListPreference; import androidx.preference.PreferenceManager; +import androidx.test.annotation.UiThreadTest; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; -import com.android.settings.network.telephony.TelephonyConstants.TelephonyManagerConstants; - import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -54,8 +57,8 @@ public class CdmaSystemSelectPreferenceControllerTest { private ListPreference mPreference; private Context mContext; private int mCdmaRoamingMode; - private int mSettingsNetworkMode; + @UiThreadTest @Before public void setUp() { MockitoAnnotations.initMocks(this); @@ -73,20 +76,12 @@ public class CdmaSystemSelectPreferenceControllerTest { mCdmaRoamingMode = Settings.Global.getInt(mContext.getContentResolver(), Settings.Global.CDMA_ROAMING_MODE, TelephonyManager.CDMA_ROAMING_MODE_ANY); - - mSettingsNetworkMode = Settings.Global.getInt( - mContext.getContentResolver(), - Settings.Global.PREFERRED_NETWORK_MODE + SUB_ID, - TelephonyManager.DEFAULT_PREFERRED_NETWORK_MODE); } @After public void tearDown() { Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.CDMA_ROAMING_MODE, mCdmaRoamingMode); - - Settings.Global.putInt(mContext.getContentResolver(), - Settings.Global.PREFERRED_NETWORK_MODE + SUB_ID, mSettingsNetworkMode); } @Test @@ -120,9 +115,9 @@ public class CdmaSystemSelectPreferenceControllerTest { public void updateState_LteGSMWcdma_disabled() { doReturn(TelephonyManager.CDMA_ROAMING_MODE_HOME).when( mTelephonyManager).getCdmaRoamingMode(); - Settings.Global.putInt(mContext.getContentResolver(), - Settings.Global.PREFERRED_NETWORK_MODE + SUB_ID, - TelephonyManagerConstants.NETWORK_MODE_LTE_GSM_WCDMA); + when(mTelephonyManager.getAllowedNetworkTypesForReason( + TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER)).thenReturn( + (long) (LTE | GSM | WCDMA)); mController.updateState(mPreference); From edaeb41ff796a0c49f5187c6b2ec530ffb5c8455 Mon Sep 17 00:00:00 2001 From: tom hsu Date: Thu, 4 Mar 2021 20:45:55 +0800 Subject: [PATCH 12/23] [Provider Model] Fix preference summary not update. - When activity enter onPause, the status will not update, then sub id of TelephonyManager keep same value after activity go back. - Solution: Everytime update the UI, and always get new TelephonyManager with the latest sub id. Bug: 181196545 Test: atest passed. Test: Manual test passed. Change-Id: I1d65bbc06af66b97b6c85f40bed394da03213d06 --- .../settings/network/SubscriptionsPreferenceController.java | 3 ++- .../network/SubscriptionsPreferenceControllerTest.java | 5 ++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/com/android/settings/network/SubscriptionsPreferenceController.java b/src/com/android/settings/network/SubscriptionsPreferenceController.java index 392ccc6aba5..f89ccfdde80 100644 --- a/src/com/android/settings/network/SubscriptionsPreferenceController.java +++ b/src/com/android/settings/network/SubscriptionsPreferenceController.java @@ -257,9 +257,10 @@ public class SubscriptionsPreferenceController extends AbstractPreferenceControl } private CharSequence getMobilePreferenceSummary(int subId) { + TelephonyManager tm = mTelephonyManager.createForSubscriptionId(subId); String result = mSubsPrefCtrlInjector.getNetworkType( mContext, mConfig, mTelephonyDisplayInfo, subId); - if (!mTelephonyManager.isDataEnabled()) { + if (!tm.isDataEnabled()) { return mContext.getString(R.string.mobile_data_off_summary); } if (!result.isEmpty() && mSubsPrefCtrlInjector.isActiveCellularNetwork(mContext)) { diff --git a/tests/unit/src/com/android/settings/network/SubscriptionsPreferenceControllerTest.java b/tests/unit/src/com/android/settings/network/SubscriptionsPreferenceControllerTest.java index 6b31342d31e..699760741e8 100644 --- a/tests/unit/src/com/android/settings/network/SubscriptionsPreferenceControllerTest.java +++ b/tests/unit/src/com/android/settings/network/SubscriptionsPreferenceControllerTest.java @@ -97,6 +97,7 @@ public class SubscriptionsPreferenceControllerTest { private LifecycleOwner mLifecycleOwner; @Mock private WifiPickerTrackerHelper mWifiPickerTrackerHelper; + private LifecycleRegistry mLifecycleRegistry; private int mOnChildUpdatedCount; private Context mContext; @@ -428,7 +429,6 @@ public class SubscriptionsPreferenceControllerTest { doReturn(mock(MobileMappings.Config.class)).when(sInjector).getConfig(mContext); doReturn(networkType) .when(sInjector).getNetworkType(any(), any(), any(), anyInt()); - when(mTelephonyManager.isDataEnabled()).thenReturn(true); mController.onResume(); mController.displayPreference(mPreferenceScreen); @@ -447,7 +447,7 @@ public class SubscriptionsPreferenceControllerTest { final List sub = setupMockSubscriptions(2); doReturn(true).when(sInjector).isProviderModelEnabled(mContext); doReturn(sub.get(0)).when(mSubscriptionManager).getDefaultDataSubscriptionInfo(); - setupGetIconConditions(sub.get(0).getSubscriptionId(), false, true, + setupGetIconConditions(sub.get(0).getSubscriptionId(), false, false, TelephonyManager.DATA_CONNECTED, ServiceState.STATE_IN_SERVICE); doReturn(networkType) .when(sInjector).getNetworkType(any(), any(), any(), anyInt()); @@ -534,7 +534,6 @@ public class SubscriptionsPreferenceControllerTest { doReturn(mock(MobileMappings.Config.class)).when(sInjector).getConfig(mContext); doReturn(networkType) .when(sInjector).getNetworkType(any(), any(), any(), anyInt()); - when(mTelephonyManager.isDataEnabled()).thenReturn(true); mController.onResume(); mController.displayPreference(mPreferenceScreen); From 84d83e292323fd093dc8725c5822e1a2a329b0f0 Mon Sep 17 00:00:00 2001 From: Julia Reynolds Date: Fri, 26 Feb 2021 14:41:40 -0500 Subject: [PATCH 13/23] Add icons to NLS mgmt page Test: manual Fixes: 181125169 Change-Id: Id8340db5f2901947c4e63e459aad1fee52437a9f --- res/drawable/ic_notification_silence.xml | 33 +++++-------------- res/drawable/ic_ongoing_notification.xml | 25 ++++++++++++++ ...notification_access_permission_details.xml | 4 +++ 3 files changed, 38 insertions(+), 24 deletions(-) create mode 100644 res/drawable/ic_ongoing_notification.xml diff --git a/res/drawable/ic_notification_silence.xml b/res/drawable/ic_notification_silence.xml index 9da56dd0bbf..4b71d65dcc6 100644 --- a/res/drawable/ic_notification_silence.xml +++ b/res/drawable/ic_notification_silence.xml @@ -14,28 +14,13 @@ Copyright (C) 2019 The Android Open Source Project See the License for the specific language governing permissions and limitations under the License. --> - - - - - - - - - - - - - + android:viewportHeight="24" + android:tint="?android:attr/colorControlNormal"> + + diff --git a/res/drawable/ic_ongoing_notification.xml b/res/drawable/ic_ongoing_notification.xml new file mode 100644 index 00000000000..238b5170a48 --- /dev/null +++ b/res/drawable/ic_ongoing_notification.xml @@ -0,0 +1,25 @@ + + + + diff --git a/res/xml/notification_access_permission_details.xml b/res/xml/notification_access_permission_details.xml index 55a47f5361a..bf61882d0bc 100644 --- a/res/xml/notification_access_permission_details.xml +++ b/res/xml/notification_access_permission_details.xml @@ -34,18 +34,22 @@ /> /> /> /> Date: Wed, 3 Mar 2021 17:36:35 -0500 Subject: [PATCH 14/23] Add device list to NLS pages If a notification listener has access via the companion device manager api, list the name(s) of the associated devices to give the user more context about why the app has notification listener access. Test: settings unit Bug: 181125174 Change-Id: I01771b2c4e136fe16d23e89f33f85f63803e3f7c --- ...notification_access_permission_details.xml | 8 +- .../HeaderPreferenceController.java | 64 +++++++++ .../NotificationAccessDetails.java | 13 +- .../HeaderPreferenceControllerTest.java | 135 ++++++++++++++++++ 4 files changed, 212 insertions(+), 8 deletions(-) create mode 100644 tests/unit/src/com/android/settings/applications/specialaccess/notificationaccess/HeaderPreferenceControllerTest.java diff --git a/res/xml/notification_access_permission_details.xml b/res/xml/notification_access_permission_details.xml index bf61882d0bc..0b764301153 100644 --- a/res/xml/notification_access_permission_details.xml +++ b/res/xml/notification_access_permission_details.xml @@ -35,22 +35,22 @@ android:key="type_filter_ongoing" android:title="@string/notif_type_ongoing" android:icon="@drawable/ic_ongoing_notification" - settings:controller="com.android.settings.applications.specialaccess.notificationaccess.OngoingTypeFilterPreferenceController"/>/> + settings:controller="com.android.settings.applications.specialaccess.notificationaccess.OngoingTypeFilterPreferenceController"/> /> + settings:controller="com.android.settings.applications.specialaccess.notificationaccess.ConversationTypeFilterPreferenceController"/> /> + settings:controller="com.android.settings.applications.specialaccess.notificationaccess.AlertingTypeFilterPreferenceController"/> /> + settings:controller="com.android.settings.applications.specialaccess.notificationaccess.SilentTypeFilterPreferenceController"/> associatedMacAddrs = + mCdm.getAssociations(mCn.getPackageName(), mUserId); + if (associatedMacAddrs != null) { + for (String assocMac : associatedMacAddrs) { + final Collection cachedDevices = + mBm.getCachedDeviceManager().getCachedDevicesCopy(); + for (CachedBluetoothDevice cachedBluetoothDevice : cachedDevices) { + if (Objects.equals(assocMac, cachedBluetoothDevice.getAddress())) { + if (multiple) { + sb.append(", "); + } else { + multiple = true; + } + sb.append(cachedBluetoothDevice.getName()); + } + } + } + } + } catch (RemoteException e) { + Log.w(TAG, "Error calling CDM", e); + } + return sb.toString(); + } } diff --git a/src/com/android/settings/applications/specialaccess/notificationaccess/NotificationAccessDetails.java b/src/com/android/settings/applications/specialaccess/notificationaccess/NotificationAccessDetails.java index a205b57433b..16aa07883e6 100644 --- a/src/com/android/settings/applications/specialaccess/notificationaccess/NotificationAccessDetails.java +++ b/src/com/android/settings/applications/specialaccess/notificationaccess/NotificationAccessDetails.java @@ -21,7 +21,7 @@ import static com.android.settings.applications.AppInfoBase.ARG_PACKAGE_NAME; import android.app.Activity; import android.app.NotificationManager; import android.app.settings.SettingsEnums; -import android.bluetooth.BluetoothAdapter; +import android.companion.ICompanionDeviceManager; import android.content.ComponentName; import android.content.Context; import android.content.Intent; @@ -30,6 +30,7 @@ import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; import android.os.Bundle; +import android.os.ServiceManager; import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; @@ -45,14 +46,13 @@ import com.android.settings.R; import com.android.settings.SettingsActivity; import com.android.settings.applications.AppInfoBase; import com.android.settings.applications.manageapplications.ManageApplications; +import com.android.settings.bluetooth.Utils; import com.android.settings.core.SubSettingLauncher; import com.android.settings.dashboard.DashboardFragment; import com.android.settings.notification.NotificationBackend; import com.android.settingslib.RestrictedLockUtils; import com.android.settingslib.RestrictedLockUtilsInternal; -import com.android.settingslib.bluetooth.CachedBluetoothDevice; -import java.util.Collection; import java.util.List; import java.util.Objects; @@ -99,7 +99,12 @@ public class NotificationAccessDetails extends DashboardFragment { .setFragment(this) .setPackageInfo(mPackageInfo) .setPm(context.getPackageManager()) - .setServiceName(mServiceName); + .setServiceName(mServiceName) + .setBluetoothManager(Utils.getLocalBtManager(context)) + .setCdm(ICompanionDeviceManager.Stub.asInterface( + ServiceManager.getService(Context.COMPANION_DEVICE_SERVICE))) + .setCn(mComponentName) + .setUserId(mUserId); getPreferenceControllers().forEach(controllers -> { controllers.forEach(controller -> { if (controller instanceof TypeFilterPreferenceController) { diff --git a/tests/unit/src/com/android/settings/applications/specialaccess/notificationaccess/HeaderPreferenceControllerTest.java b/tests/unit/src/com/android/settings/applications/specialaccess/notificationaccess/HeaderPreferenceControllerTest.java new file mode 100644 index 00000000000..40ad1e08b17 --- /dev/null +++ b/tests/unit/src/com/android/settings/applications/specialaccess/notificationaccess/HeaderPreferenceControllerTest.java @@ -0,0 +1,135 @@ +/* + * 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.applications.specialaccess.notificationaccess; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import android.bluetooth.BluetoothAdapter; +import android.companion.ICompanionDeviceManager; +import android.content.ComponentName; +import android.content.Context; + +import androidx.test.core.app.ApplicationProvider; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import com.android.settingslib.bluetooth.CachedBluetoothDevice; +import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager; +import com.android.settingslib.bluetooth.LocalBluetoothManager; + +import com.google.common.collect.ImmutableList; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +@RunWith(AndroidJUnit4.class) +public class HeaderPreferenceControllerTest { + + private Context mContext; + private HeaderPreferenceController mController; + @Mock + LocalBluetoothManager mBm; + @Mock + ICompanionDeviceManager mCdm; + @Mock + CachedBluetoothDeviceManager mCbm; + ComponentName mCn = new ComponentName("a", "b"); + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mContext = ApplicationProvider.getApplicationContext(); + + when(mBm.getCachedDeviceManager()).thenReturn(mCbm); + + mController = new HeaderPreferenceController(mContext, "key"); + mController.setCn(mCn); + mController.setUserId(0); + mController.setBluetoothManager(mBm); + mController.setCdm(mCdm); + } + + @Test + public void getDeviceList_noAssociations() throws Exception { + when(mCdm.getAssociations(mCn.getPackageName(), 0)).thenReturn(null); + + Collection cachedDevices = new ArrayList<>(); + CachedBluetoothDevice cbd1 = mock(CachedBluetoothDevice.class); + when(cbd1.getAddress()).thenReturn("00:00:00:00:00:10"); + when(cbd1.getName()).thenReturn("Device 1"); + cachedDevices.add(cbd1); + when(mCbm.getCachedDevicesCopy()).thenReturn(cachedDevices); + + BluetoothAdapter.getDefaultAdapter().enable(); + + assertThat(mController.getDeviceList().toString()).isEmpty(); + } + + @Test + public void getDeviceList_associationsButNoDevice() throws Exception { + List macs = ImmutableList.of("00:00:00:00:00:10", "00:00:00:00:00:20"); + when(mCdm.getAssociations(mCn.getPackageName(), 0)).thenReturn(macs); + + when(mCbm.getCachedDevicesCopy()).thenReturn(new ArrayList<>()); + + assertThat(mController.getDeviceList().toString()).isEmpty(); + } + + @Test + public void getDeviceList_singleDevice() throws Exception { + List macs = ImmutableList.of("00:00:00:00:00:10", "00:00:00:00:00:20"); + when(mCdm.getAssociations(mCn.getPackageName(), 0)).thenReturn(macs); + + Collection cachedDevices = new ArrayList<>(); + CachedBluetoothDevice cbd1 = mock(CachedBluetoothDevice.class); + when(cbd1.getAddress()).thenReturn(macs.get(0)); + when(cbd1.getName()).thenReturn("Device 1"); + cachedDevices.add(cbd1); + when(mCbm.getCachedDevicesCopy()).thenReturn(cachedDevices); + + assertThat(mController.getDeviceList().toString()).isEqualTo("Device 1"); + } + + @Test + public void getDeviceList_multipleDevices() throws Exception { + List macs = ImmutableList.of("00:00:00:00:00:10", "00:00:00:00:00:20"); + when(mCdm.getAssociations(mCn.getPackageName(), 0)).thenReturn(macs); + + Collection cachedDevices = new ArrayList<>(); + CachedBluetoothDevice cbd1 = mock(CachedBluetoothDevice.class); + when(cbd1.getAddress()).thenReturn(macs.get(0)); + when(cbd1.getName()).thenReturn("Device 1"); + cachedDevices.add(cbd1); + + CachedBluetoothDevice cbd2 = mock(CachedBluetoothDevice.class); + when(cbd2.getAddress()).thenReturn(macs.get(1)); + when(cbd2.getName()).thenReturn("Device 2"); + cachedDevices.add(cbd2); + when(mCbm.getCachedDevicesCopy()).thenReturn(cachedDevices); + + assertThat(mController.getDeviceList().toString()).isEqualTo("Device 1, Device 2"); + } +} From e82e80450c5835fa0976fbe6d0d9f1c121016b8b Mon Sep 17 00:00:00 2001 From: Jimmy Chen Date: Thu, 4 Mar 2021 02:50:43 +0800 Subject: [PATCH 15/23] wifi: add WPA3 Enterprise entry in "Add network" Bug: 174569407 Test: checked UI manually and stored configurations. Change-Id: I8a05bbb11e4a363c39a71d26513caf727d228b36 --- .../settings/wifi/WifiConfigController.java | 22 ++++++++++++++----- .../settings/wifi/WifiConfigController2.java | 15 +++++++++++-- 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/src/com/android/settings/wifi/WifiConfigController.java b/src/com/android/settings/wifi/WifiConfigController.java index b2eca781a8a..ee2abf83966 100644 --- a/src/com/android/settings/wifi/WifiConfigController.java +++ b/src/com/android/settings/wifi/WifiConfigController.java @@ -536,8 +536,9 @@ public class WifiConfigController implements TextWatcher, } else { enabled = ipAndProxyFieldsAreValid(); } - if ((mAccessPointSecurity == AccessPoint.SECURITY_EAP || - mAccessPointSecurity == AccessPoint.SECURITY_EAP_SUITE_B) + if ((mAccessPointSecurity == AccessPoint.SECURITY_EAP + || mAccessPointSecurity == AccessPoint.SECURITY_EAP_WPA3_ENTERPRISE + || mAccessPointSecurity == AccessPoint.SECURITY_EAP_SUITE_B) && mEapCaCertSpinner != null && mView.findViewById(R.id.l_ca_cert).getVisibility() != View.GONE) { String caCertSelection = (String) mEapCaCertSpinner.getSelectedItem(); @@ -553,8 +554,9 @@ public class WifiConfigController implements TextWatcher, enabled = false; } } - if ((mAccessPointSecurity == AccessPoint.SECURITY_EAP || - mAccessPointSecurity == AccessPoint.SECURITY_EAP_SUITE_B) + if ((mAccessPointSecurity == AccessPoint.SECURITY_EAP + || mAccessPointSecurity == AccessPoint.SECURITY_EAP_WPA3_ENTERPRISE + || mAccessPointSecurity == AccessPoint.SECURITY_EAP_SUITE_B) && mEapUserCertSpinner != null && mView.findViewById(R.id.l_user_cert).getVisibility() != View.GONE && mEapUserCertSpinner.getSelectedItem().equals(mUnspecifiedCertString)) { @@ -651,10 +653,13 @@ public class WifiConfigController implements TextWatcher, break; case AccessPoint.SECURITY_EAP: + case AccessPoint.SECURITY_EAP_WPA3_ENTERPRISE: case AccessPoint.SECURITY_EAP_SUITE_B: if (mAccessPointSecurity == AccessPoint.SECURITY_EAP_SUITE_B) { // allowedSuiteBCiphers will be set according to certificate type config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP_SUITE_B); + } else if (mAccessPointSecurity == AccessPoint.SECURITY_EAP_WPA3_ENTERPRISE) { + config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE); } else { config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP); } @@ -1693,9 +1698,14 @@ public class WifiConfigController implements TextWatcher, if (mWifiManager.isWpa3SaeSupported()) { spinnerAdapter.add(mContext.getString(R.string.wifi_security_sae)); mSecurityInPosition[idx++] = AccessPoint.SECURITY_SAE; + spinnerAdapter.add(mContext.getString(R.string.wifi_security_eap_wpa_wpa2)); + mSecurityInPosition[idx++] = AccessPoint.SECURITY_EAP; + spinnerAdapter.add(mContext.getString(R.string.wifi_security_eap_wpa3)); + mSecurityInPosition[idx++] = AccessPoint.SECURITY_EAP_WPA3_ENTERPRISE; + } else { + spinnerAdapter.add(mContext.getString(R.string.wifi_security_eap)); + mSecurityInPosition[idx++] = AccessPoint.SECURITY_EAP; } - spinnerAdapter.add(mContext.getString(R.string.wifi_security_eap)); - mSecurityInPosition[idx++] = AccessPoint.SECURITY_EAP; if (mWifiManager.isWpa3SuiteBSupported()) { spinnerAdapter.add(mContext.getString(R.string.wifi_security_eap_suiteb)); mSecurityInPosition[idx++] = AccessPoint.SECURITY_EAP_SUITE_B; diff --git a/src/com/android/settings/wifi/WifiConfigController2.java b/src/com/android/settings/wifi/WifiConfigController2.java index b4e26a6ab94..32152de70ab 100644 --- a/src/com/android/settings/wifi/WifiConfigController2.java +++ b/src/com/android/settings/wifi/WifiConfigController2.java @@ -500,6 +500,7 @@ public class WifiConfigController2 implements TextWatcher, enabled = ipAndProxyFieldsAreValid(); } if ((mWifiEntrySecurity == WifiEntry.SECURITY_EAP + || mWifiEntrySecurity == WifiEntry.SECURITY_EAP_WPA3_ENTERPRISE || mWifiEntrySecurity == WifiEntry.SECURITY_EAP_SUITE_B) && mEapCaCertSpinner != null && mView.findViewById(R.id.l_ca_cert).getVisibility() != View.GONE) { @@ -517,6 +518,7 @@ public class WifiConfigController2 implements TextWatcher, } } if ((mWifiEntrySecurity == WifiEntry.SECURITY_EAP + || mWifiEntrySecurity == WifiEntry.SECURITY_EAP_WPA3_ENTERPRISE || mWifiEntrySecurity == WifiEntry.SECURITY_EAP_SUITE_B) && mEapUserCertSpinner != null && mView.findViewById(R.id.l_user_cert).getVisibility() != View.GONE @@ -615,10 +617,13 @@ public class WifiConfigController2 implements TextWatcher, break; case WifiEntry.SECURITY_EAP: + case WifiEntry.SECURITY_EAP_WPA3_ENTERPRISE: case WifiEntry.SECURITY_EAP_SUITE_B: if (mWifiEntrySecurity == WifiEntry.SECURITY_EAP_SUITE_B) { // allowedSuiteBCiphers will be set according to certificate type config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP_SUITE_B); + } else if (mWifiEntrySecurity == WifiEntry.SECURITY_EAP_WPA3_ENTERPRISE) { + config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE); } else { config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP); } @@ -942,6 +947,7 @@ public class WifiConfigController2 implements TextWatcher, } if (mWifiEntrySecurity != WifiEntry.SECURITY_EAP + && mWifiEntrySecurity != WifiEntry.SECURITY_EAP_WPA3_ENTERPRISE && mWifiEntrySecurity != WifiEntry.SECURITY_EAP_SUITE_B) { mView.findViewById(R.id.eap).setVisibility(View.GONE); return; @@ -1660,9 +1666,14 @@ public class WifiConfigController2 implements TextWatcher, if (mWifiManager.isWpa3SaeSupported()) { spinnerAdapter.add(mContext.getString(R.string.wifi_security_sae)); mSecurityInPosition[idx++] = WifiEntry.SECURITY_SAE; + spinnerAdapter.add(mContext.getString(R.string.wifi_security_eap_wpa_wpa2)); + mSecurityInPosition[idx++] = WifiEntry.SECURITY_EAP; + spinnerAdapter.add(mContext.getString(R.string.wifi_security_eap_wpa3)); + mSecurityInPosition[idx++] = WifiEntry.SECURITY_EAP_WPA3_ENTERPRISE; + } else { + spinnerAdapter.add(mContext.getString(R.string.wifi_security_eap)); + mSecurityInPosition[idx++] = WifiEntry.SECURITY_EAP; } - spinnerAdapter.add(mContext.getString(R.string.wifi_security_eap)); - mSecurityInPosition[idx++] = WifiEntry.SECURITY_EAP; if (mWifiManager.isWpa3SuiteBSupported()) { spinnerAdapter.add(mContext.getString(R.string.wifi_security_eap_suiteb)); mSecurityInPosition[idx++] = WifiEntry.SECURITY_EAP_SUITE_B; From 9481334a6aa535556ff06104877bd29091d4ce5a Mon Sep 17 00:00:00 2001 From: Abel Tesfaye Date: Thu, 4 Mar 2021 20:01:30 +0000 Subject: [PATCH 16/23] Instrument metrics for smart-auto-rotate and screen timeout Test: locally with flame Bug: 172974834 Change-Id: Id6927e749049c88e4efea2d69f93b9d397acc1c1 --- .../display/AdaptiveSleepPreferenceController.java | 7 +++++++ .../settings/display/AutoRotateSwitchBarController.java | 3 ++- .../android/settings/display/ScreenTimeoutSettings.java | 6 ++++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/com/android/settings/display/AdaptiveSleepPreferenceController.java b/src/com/android/settings/display/AdaptiveSleepPreferenceController.java index c0c5e63bfa4..e0527f9d32b 100644 --- a/src/com/android/settings/display/AdaptiveSleepPreferenceController.java +++ b/src/com/android/settings/display/AdaptiveSleepPreferenceController.java @@ -20,6 +20,7 @@ import static com.android.settings.core.BasePreferenceController.AVAILABLE_UNSEA import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE; import android.Manifest; +import android.app.settings.SettingsEnums; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; @@ -33,8 +34,10 @@ import androidx.preference.PreferenceScreen; import com.android.settings.R; import com.android.settings.bluetooth.RestrictionUtils; +import com.android.settings.overlay.FeatureFactory; import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin; import com.android.settingslib.RestrictedSwitchPreference; +import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; import com.google.common.annotations.VisibleForTesting; @@ -45,6 +48,7 @@ public class AdaptiveSleepPreferenceController { private RestrictionUtils mRestrictionUtils; private PackageManager mPackageManager; private Context mContext; + private MetricsFeatureProvider mMetricsFeatureProvider; @VisibleForTesting RestrictedSwitchPreference mPreference; @@ -52,6 +56,7 @@ public class AdaptiveSleepPreferenceController { public AdaptiveSleepPreferenceController(Context context, RestrictionUtils restrictionUtils) { mContext = context; mRestrictionUtils = restrictionUtils; + mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider(); mPreference = new RestrictedSwitchPreference(context); mPreference.setTitle(R.string.adaptive_sleep_title); mPreference.setSummary(R.string.adaptive_sleep_description); @@ -60,6 +65,8 @@ public class AdaptiveSleepPreferenceController { mPreference.setKey(PREFERENCE_KEY); mPreference.setOnPreferenceClickListener(preference -> { final boolean isChecked = ((RestrictedSwitchPreference) preference).isChecked(); + mMetricsFeatureProvider.action(context, SettingsEnums.ACTION_SCREEN_ATTENTION_CHANGED, + isChecked); Settings.Secure.putInt(context.getContentResolver(), Settings.Secure.ADAPTIVE_SLEEP, isChecked ? 1 : DEFAULT_VALUE); return true; diff --git a/src/com/android/settings/display/AutoRotateSwitchBarController.java b/src/com/android/settings/display/AutoRotateSwitchBarController.java index 0931a10840c..e149ccb6c76 100644 --- a/src/com/android/settings/display/AutoRotateSwitchBarController.java +++ b/src/com/android/settings/display/AutoRotateSwitchBarController.java @@ -93,7 +93,8 @@ public class AutoRotateSwitchBarController implements OnMainSwitchChangeListener private boolean setRotationLock(boolean isChecked) { final boolean isLocked = !isChecked; - mMetricsFeatureProvider.action(mContext, SettingsEnums.ACTION_ROTATION_LOCK, isLocked); + mMetricsFeatureProvider.action(mContext, SettingsEnums.ACTION_ROTATE_ROTATE_MASTER_TOGGLE, + isChecked); RotationPolicy.setRotationLock(mContext, isLocked); return true; } diff --git a/src/com/android/settings/display/ScreenTimeoutSettings.java b/src/com/android/settings/display/ScreenTimeoutSettings.java index b187c876ac8..15b5466ff06 100644 --- a/src/com/android/settings/display/ScreenTimeoutSettings.java +++ b/src/com/android/settings/display/ScreenTimeoutSettings.java @@ -37,6 +37,7 @@ import androidx.preference.Preference; import androidx.preference.PreferenceScreen; import com.android.settings.R; +import com.android.settings.overlay.FeatureFactory; import com.android.settings.search.BaseSearchIndexProvider; import com.android.settings.search.actionbar.SearchMenuController; import com.android.settings.support.actionbar.HelpMenuController; @@ -44,6 +45,7 @@ import com.android.settings.support.actionbar.HelpResourceProvider; import com.android.settings.widget.RadioButtonPickerFragment; import com.android.settingslib.RestrictedLockUtils; import com.android.settingslib.RestrictedLockUtilsInternal; +import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; import com.android.settingslib.search.SearchIndexable; import com.android.settingslib.search.SearchIndexableRaw; import com.android.settingslib.widget.CandidateInfo; @@ -70,6 +72,7 @@ public class ScreenTimeoutSettings extends RadioButtonPickerFragment implements private CharSequence[] mInitialEntries; private CharSequence[] mInitialValues; private FooterPreference mPrivacyPreference; + private MetricsFeatureProvider mMetricsFeatureProvider; @VisibleForTesting RestrictedLockUtils.EnforcedAdmin mAdmin; @@ -102,6 +105,7 @@ public class ScreenTimeoutSettings extends RadioButtonPickerFragment implements mPrivacyPreference.setTitle(R.string.adaptive_sleep_privacy); mPrivacyPreference.setSelectable(false); mPrivacyPreference.setLayoutResource(R.layout.preference_footer); + mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider(); } @Override @@ -244,6 +248,8 @@ public class ScreenTimeoutSettings extends RadioButtonPickerFragment implements try { if (context != null) { final long value = Long.parseLong(key); + mMetricsFeatureProvider.action(context, SettingsEnums.ACTION_SCREEN_TIMEOUT_CHANGED, + (int) value); Settings.System.putLong(context.getContentResolver(), SCREEN_OFF_TIMEOUT, value); } } catch (NumberFormatException e) { From ddf1958bdcd4f2e57e2709b3aad410f77d06e3d4 Mon Sep 17 00:00:00 2001 From: Julia Reynolds Date: Thu, 4 Mar 2021 10:26:42 -0500 Subject: [PATCH 17/23] Update NLS listing page - Organized by allowed/not allowed - Include paired devices if there are any Test: settings robotests Fixes: 181125174 Change-Id: Id64ee0ebd9b40a92d54a03d92fec3ff0bb3b926d --- res/xml/notification_access_settings.xml | 11 +- .../HeaderPreferenceController.java | 40 +----- .../NotificationAccessSettings.java | 28 +++- .../notification/NotificationBackend.java | 34 +++++ .../notification/NotificationBackendTest.java | 91 ++++++++++++ .../HeaderPreferenceControllerTest.java | 135 ------------------ 6 files changed, 160 insertions(+), 179 deletions(-) delete mode 100644 tests/unit/src/com/android/settings/applications/specialaccess/notificationaccess/HeaderPreferenceControllerTest.java diff --git a/res/xml/notification_access_settings.xml b/res/xml/notification_access_settings.xml index 43f7c492b37..b523d7de691 100644 --- a/res/xml/notification_access_settings.xml +++ b/res/xml/notification_access_settings.xml @@ -21,4 +21,13 @@ android:key="notification_access_screen" android:title="@string/manage_notification_access_title" settings:searchable="false" - settings:controller="com.android.settings.applications.specialaccess.notificationaccess.NotificationAccessScreenPreferenceController" /> + settings:controller="com.android.settings.applications.specialaccess.notificationaccess.NotificationAccessScreenPreferenceController"> + + + + + diff --git a/src/com/android/settings/applications/specialaccess/notificationaccess/HeaderPreferenceController.java b/src/com/android/settings/applications/specialaccess/notificationaccess/HeaderPreferenceController.java index 36f884ffe6b..1144f12132d 100644 --- a/src/com/android/settings/applications/specialaccess/notificationaccess/HeaderPreferenceController.java +++ b/src/com/android/settings/applications/specialaccess/notificationaccess/HeaderPreferenceController.java @@ -21,9 +21,7 @@ import android.content.ComponentName; import android.content.Context; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; -import android.os.RemoteException; import android.util.IconDrawableFactory; -import android.util.Log; import android.view.View; import androidx.lifecycle.LifecycleObserver; @@ -34,17 +32,13 @@ import com.android.settings.R; import com.android.settings.core.BasePreferenceController; import com.android.settings.core.PreferenceControllerMixin; import com.android.settings.dashboard.DashboardFragment; +import com.android.settings.notification.NotificationBackend; import com.android.settings.widget.EntityHeaderController; import com.android.settingslib.applications.AppUtils; -import com.android.settingslib.bluetooth.CachedBluetoothDevice; import com.android.settingslib.bluetooth.LocalBluetoothManager; import com.android.settingslib.core.lifecycle.Lifecycle; import com.android.settingslib.widget.LayoutPreference; -import java.util.Collection; -import java.util.List; -import java.util.Objects; - public class HeaderPreferenceController extends BasePreferenceController implements PreferenceControllerMixin, LifecycleObserver { @@ -122,7 +116,8 @@ public class HeaderPreferenceController extends BasePreferenceController .getBadgedIcon(mPackageInfo.applicationInfo)) .setLabel(mPackageInfo.applicationInfo.loadLabel(mPm)) .setSummary(mServiceName) - .setSecondSummary(getDeviceList()) + .setSecondSummary(new NotificationBackend().getDeviceList( + mCdm, mBm, mCn.getPackageName(), mUserId)) .setIsInstantApp(AppUtils.isInstant(mPackageInfo.applicationInfo)) .setPackageName(mPackageInfo.packageName) .setUid(mPackageInfo.applicationInfo.uid) @@ -139,33 +134,4 @@ public class HeaderPreferenceController extends BasePreferenceController mHeaderController.styleActionBar(mFragment.getActivity()); } } - - protected CharSequence getDeviceList() { - boolean multiple = false; - StringBuilder sb = new StringBuilder(); - - try { - List associatedMacAddrs = - mCdm.getAssociations(mCn.getPackageName(), mUserId); - if (associatedMacAddrs != null) { - for (String assocMac : associatedMacAddrs) { - final Collection cachedDevices = - mBm.getCachedDeviceManager().getCachedDevicesCopy(); - for (CachedBluetoothDevice cachedBluetoothDevice : cachedDevices) { - if (Objects.equals(assocMac, cachedBluetoothDevice.getAddress())) { - if (multiple) { - sb.append(", "); - } else { - multiple = true; - } - sb.append(cachedBluetoothDevice.getName()); - } - } - } - } - } catch (RemoteException e) { - Log.w(TAG, "Error calling CDM", e); - } - return sb.toString(); - } } diff --git a/src/com/android/settings/notification/NotificationAccessSettings.java b/src/com/android/settings/notification/NotificationAccessSettings.java index 12d6295ef90..a642d9c5b33 100644 --- a/src/com/android/settings/notification/NotificationAccessSettings.java +++ b/src/com/android/settings/notification/NotificationAccessSettings.java @@ -20,12 +20,14 @@ import android.annotation.Nullable; import android.app.NotificationManager; import android.app.admin.DevicePolicyManager; import android.app.settings.SettingsEnums; +import android.companion.ICompanionDeviceManager; import android.content.ComponentName; import android.content.Context; import android.content.pm.PackageItemInfo; import android.content.pm.PackageManager; import android.content.pm.ServiceInfo; import android.os.Bundle; +import android.os.ServiceManager; import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; @@ -35,6 +37,7 @@ import android.util.Log; import android.view.View; import android.widget.Toast; +import androidx.preference.PreferenceCategory; import androidx.preference.PreferenceScreen; import com.android.settings.R; @@ -57,6 +60,9 @@ import java.util.List; @SearchIndexable public class NotificationAccessSettings extends EmptyTextSettings { private static final String TAG = "NotifAccessSettings"; + private static final String ALLOWED_KEY = "allowed"; + private static final String NOT_ALLOWED_KEY = "not_allowed"; + private static final ManagedServiceSettings.Config CONFIG = new ManagedServiceSettings.Config.Builder() .setTag(TAG) @@ -76,6 +82,7 @@ public class NotificationAccessSettings extends EmptyTextSettings { private DevicePolicyManager mDpm; private ServiceListing mServiceListing; private IconDrawableFactory mIconDrawableFactory; + private NotificationBackend mBackend = new NotificationBackend(); @Override public void onCreate(Bundle icicle) { @@ -93,7 +100,6 @@ public class NotificationAccessSettings extends EmptyTextSettings { .setTag(CONFIG.tag) .build(); mServiceListing.addCallback(this::updateList); - setPreferenceScreen(getPreferenceManager().createPreferenceScreen(mContext)); if (UserManager.get(mContext).isManagedProfile()) { // Apps in the work profile do not support notification listeners. @@ -127,7 +133,11 @@ public class NotificationAccessSettings extends EmptyTextSettings { final int managedProfileId = Utils.getManagedProfileId(um, UserHandle.myUserId()); final PreferenceScreen screen = getPreferenceScreen(); - screen.removeAll(); + final PreferenceCategory allowedCategory = screen.findPreference(ALLOWED_KEY); + allowedCategory.removeAll(); + final PreferenceCategory notAllowedCategory = screen.findPreference(NOT_ALLOWED_KEY); + notAllowedCategory.removeAll(); + services.sort(new PackageItemInfo.DisplayNameComparator(mPm)); for (ServiceInfo service : services) { final ComponentName cn = new ComponentName(service.packageName, service.name); @@ -145,9 +155,11 @@ public class NotificationAccessSettings extends EmptyTextSettings { pref.setIcon(mIconDrawableFactory.getBadgedIcon(service, service.applicationInfo, UserHandle.getUserId(service.applicationInfo.uid))); pref.setKey(cn.flattenToString()); - pref.setSummary(mNm.isNotificationListenerAccessGranted(cn) - ? R.string.app_permission_summary_allowed - : R.string.app_permission_summary_not_allowed); + pref.setSummary(mBackend.getDeviceList(ICompanionDeviceManager.Stub.asInterface( + ServiceManager.getService(Context.COMPANION_DEVICE_SERVICE)), + com.android.settings.bluetooth.Utils.getLocalBtManager(mContext), + service.packageName, + UserHandle.myUserId())); if (managedProfileId != UserHandle.USER_NULL && !mDpm.isNotificationListenerServicePermitted( service.packageName, managedProfileId)) { @@ -173,7 +185,11 @@ public class NotificationAccessSettings extends EmptyTextSettings { return true; }); pref.setKey(cn.flattenToString()); - screen.addPreference(pref); + if (mNm.isNotificationListenerAccessGranted(cn)) { + allowedCategory.addPreference(pref); + } else { + notAllowedCategory.addPreference(pref); + } } highlightPreferenceIfNeeded(); } diff --git a/src/com/android/settings/notification/NotificationBackend.java b/src/com/android/settings/notification/NotificationBackend.java index 8a7e737dbb8..4347ca55104 100644 --- a/src/com/android/settings/notification/NotificationBackend.java +++ b/src/com/android/settings/notification/NotificationBackend.java @@ -30,6 +30,7 @@ import android.app.NotificationManager; import android.app.role.RoleManager; import android.app.usage.IUsageStatsManager; import android.app.usage.UsageEvents; +import android.companion.ICompanionDeviceManager; import android.content.ComponentName; import android.content.Context; import android.content.Intent; @@ -55,14 +56,18 @@ import androidx.annotation.VisibleForTesting; import com.android.settingslib.R; import com.android.settingslib.Utils; +import com.android.settingslib.bluetooth.CachedBluetoothDevice; +import com.android.settingslib.bluetooth.LocalBluetoothManager; import com.android.settingslib.notification.ConversationIconFactory; import com.android.settingslib.utils.StringUtil; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Objects; public class NotificationBackend { private static final String TAG = "NotificationBackend"; @@ -138,6 +143,35 @@ public class NotificationBackend { } } + static public CharSequence getDeviceList(ICompanionDeviceManager cdm, LocalBluetoothManager lbm, + String pkg, int userId) { + boolean multiple = false; + StringBuilder sb = new StringBuilder(); + + try { + List associatedMacAddrs = cdm.getAssociations(pkg, userId); + if (associatedMacAddrs != null) { + for (String assocMac : associatedMacAddrs) { + final Collection cachedDevices = + lbm.getCachedDeviceManager().getCachedDevicesCopy(); + for (CachedBluetoothDevice cachedBluetoothDevice : cachedDevices) { + if (Objects.equals(assocMac, cachedBluetoothDevice.getAddress())) { + if (multiple) { + sb.append(", "); + } else { + multiple = true; + } + sb.append(cachedBluetoothDevice.getName()); + } + } + } + } + } catch (RemoteException e) { + Log.w(TAG, "Error calling CDM", e); + } + return sb.toString(); + } + public boolean isSystemApp(Context context, ApplicationInfo app) { try { PackageInfo info = context.getPackageManager().getPackageInfo( diff --git a/tests/robotests/src/com/android/settings/notification/NotificationBackendTest.java b/tests/robotests/src/com/android/settings/notification/NotificationBackendTest.java index cb5060914b8..17471b5d90c 100644 --- a/tests/robotests/src/com/android/settings/notification/NotificationBackendTest.java +++ b/tests/robotests/src/com/android/settings/notification/NotificationBackendTest.java @@ -26,24 +26,50 @@ import static org.mockito.Mockito.when; import android.app.role.RoleManager; import android.app.usage.UsageEvents; +import android.bluetooth.BluetoothAdapter; +import android.companion.ICompanionDeviceManager; +import android.content.ComponentName; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.os.Parcel; import com.android.settings.notification.NotificationBackend.AppRow; +import com.android.settingslib.bluetooth.CachedBluetoothDevice; +import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager; +import com.android.settingslib.bluetooth.LocalBluetoothManager; +import com.google.common.collect.ImmutableList; + +import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; import java.util.ArrayList; +import java.util.Collection; import java.util.List; @RunWith(RobolectricTestRunner.class) public class NotificationBackendTest { + @Mock + LocalBluetoothManager mBm; + @Mock + ICompanionDeviceManager mCdm; + @Mock + CachedBluetoothDeviceManager mCbm; + ComponentName mCn = new ComponentName("a", "b"); + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + when(mBm.getCachedDeviceManager()).thenReturn(mCbm); + } + @Test public void testMarkAppRow_unblockablePackage() { AppRow appRow = new AppRow(); @@ -138,4 +164,69 @@ public class NotificationBackendTest { parcel.setDataPosition(0); return UsageEvents.CREATOR.createFromParcel(parcel); } + + @Test + public void getDeviceList_noAssociations() throws Exception { + when(mCdm.getAssociations(mCn.getPackageName(), 0)).thenReturn(null); + + Collection cachedDevices = new ArrayList<>(); + CachedBluetoothDevice cbd1 = mock(CachedBluetoothDevice.class); + when(cbd1.getAddress()).thenReturn("00:00:00:00:00:10"); + when(cbd1.getName()).thenReturn("Device 1"); + cachedDevices.add(cbd1); + when(mCbm.getCachedDevicesCopy()).thenReturn(cachedDevices); + + BluetoothAdapter.getDefaultAdapter().enable(); + + assertThat(new NotificationBackend().getDeviceList( + mCdm, mBm, mCn.getPackageName(), 0).toString()).isEmpty(); + } + + @Test + public void getDeviceList_associationsButNoDevice() throws Exception { + List macs = ImmutableList.of("00:00:00:00:00:10", "00:00:00:00:00:20"); + when(mCdm.getAssociations(mCn.getPackageName(), 0)).thenReturn(macs); + + when(mCbm.getCachedDevicesCopy()).thenReturn(new ArrayList<>()); + + assertThat(new NotificationBackend().getDeviceList( + mCdm, mBm, mCn.getPackageName(), 0).toString()).isEmpty(); + } + + @Test + public void getDeviceList_singleDevice() throws Exception { + List macs = ImmutableList.of("00:00:00:00:00:10", "00:00:00:00:00:20"); + when(mCdm.getAssociations(mCn.getPackageName(), 0)).thenReturn(macs); + + Collection cachedDevices = new ArrayList<>(); + CachedBluetoothDevice cbd1 = mock(CachedBluetoothDevice.class); + when(cbd1.getAddress()).thenReturn(macs.get(0)); + when(cbd1.getName()).thenReturn("Device 1"); + cachedDevices.add(cbd1); + when(mCbm.getCachedDevicesCopy()).thenReturn(cachedDevices); + + assertThat(new NotificationBackend().getDeviceList( + mCdm, mBm, mCn.getPackageName(), 0).toString()).isEqualTo("Device 1"); + } + + @Test + public void getDeviceList_multipleDevices() throws Exception { + List macs = ImmutableList.of("00:00:00:00:00:10", "00:00:00:00:00:20"); + when(mCdm.getAssociations(mCn.getPackageName(), 0)).thenReturn(macs); + + Collection cachedDevices = new ArrayList<>(); + CachedBluetoothDevice cbd1 = mock(CachedBluetoothDevice.class); + when(cbd1.getAddress()).thenReturn(macs.get(0)); + when(cbd1.getName()).thenReturn("Device 1"); + cachedDevices.add(cbd1); + + CachedBluetoothDevice cbd2 = mock(CachedBluetoothDevice.class); + when(cbd2.getAddress()).thenReturn(macs.get(1)); + when(cbd2.getName()).thenReturn("Device 2"); + cachedDevices.add(cbd2); + when(mCbm.getCachedDevicesCopy()).thenReturn(cachedDevices); + + assertThat(new NotificationBackend().getDeviceList( + mCdm, mBm, mCn.getPackageName(), 0).toString()).isEqualTo("Device 1, Device 2"); + } } diff --git a/tests/unit/src/com/android/settings/applications/specialaccess/notificationaccess/HeaderPreferenceControllerTest.java b/tests/unit/src/com/android/settings/applications/specialaccess/notificationaccess/HeaderPreferenceControllerTest.java deleted file mode 100644 index 40ad1e08b17..00000000000 --- a/tests/unit/src/com/android/settings/applications/specialaccess/notificationaccess/HeaderPreferenceControllerTest.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * 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.applications.specialaccess.notificationaccess; - -import static com.google.common.truth.Truth.assertThat; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import android.bluetooth.BluetoothAdapter; -import android.companion.ICompanionDeviceManager; -import android.content.ComponentName; -import android.content.Context; - -import androidx.test.core.app.ApplicationProvider; -import androidx.test.ext.junit.runners.AndroidJUnit4; - -import com.android.settingslib.bluetooth.CachedBluetoothDevice; -import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager; -import com.android.settingslib.bluetooth.LocalBluetoothManager; - -import com.google.common.collect.ImmutableList; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -@RunWith(AndroidJUnit4.class) -public class HeaderPreferenceControllerTest { - - private Context mContext; - private HeaderPreferenceController mController; - @Mock - LocalBluetoothManager mBm; - @Mock - ICompanionDeviceManager mCdm; - @Mock - CachedBluetoothDeviceManager mCbm; - ComponentName mCn = new ComponentName("a", "b"); - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - mContext = ApplicationProvider.getApplicationContext(); - - when(mBm.getCachedDeviceManager()).thenReturn(mCbm); - - mController = new HeaderPreferenceController(mContext, "key"); - mController.setCn(mCn); - mController.setUserId(0); - mController.setBluetoothManager(mBm); - mController.setCdm(mCdm); - } - - @Test - public void getDeviceList_noAssociations() throws Exception { - when(mCdm.getAssociations(mCn.getPackageName(), 0)).thenReturn(null); - - Collection cachedDevices = new ArrayList<>(); - CachedBluetoothDevice cbd1 = mock(CachedBluetoothDevice.class); - when(cbd1.getAddress()).thenReturn("00:00:00:00:00:10"); - when(cbd1.getName()).thenReturn("Device 1"); - cachedDevices.add(cbd1); - when(mCbm.getCachedDevicesCopy()).thenReturn(cachedDevices); - - BluetoothAdapter.getDefaultAdapter().enable(); - - assertThat(mController.getDeviceList().toString()).isEmpty(); - } - - @Test - public void getDeviceList_associationsButNoDevice() throws Exception { - List macs = ImmutableList.of("00:00:00:00:00:10", "00:00:00:00:00:20"); - when(mCdm.getAssociations(mCn.getPackageName(), 0)).thenReturn(macs); - - when(mCbm.getCachedDevicesCopy()).thenReturn(new ArrayList<>()); - - assertThat(mController.getDeviceList().toString()).isEmpty(); - } - - @Test - public void getDeviceList_singleDevice() throws Exception { - List macs = ImmutableList.of("00:00:00:00:00:10", "00:00:00:00:00:20"); - when(mCdm.getAssociations(mCn.getPackageName(), 0)).thenReturn(macs); - - Collection cachedDevices = new ArrayList<>(); - CachedBluetoothDevice cbd1 = mock(CachedBluetoothDevice.class); - when(cbd1.getAddress()).thenReturn(macs.get(0)); - when(cbd1.getName()).thenReturn("Device 1"); - cachedDevices.add(cbd1); - when(mCbm.getCachedDevicesCopy()).thenReturn(cachedDevices); - - assertThat(mController.getDeviceList().toString()).isEqualTo("Device 1"); - } - - @Test - public void getDeviceList_multipleDevices() throws Exception { - List macs = ImmutableList.of("00:00:00:00:00:10", "00:00:00:00:00:20"); - when(mCdm.getAssociations(mCn.getPackageName(), 0)).thenReturn(macs); - - Collection cachedDevices = new ArrayList<>(); - CachedBluetoothDevice cbd1 = mock(CachedBluetoothDevice.class); - when(cbd1.getAddress()).thenReturn(macs.get(0)); - when(cbd1.getName()).thenReturn("Device 1"); - cachedDevices.add(cbd1); - - CachedBluetoothDevice cbd2 = mock(CachedBluetoothDevice.class); - when(cbd2.getAddress()).thenReturn(macs.get(1)); - when(cbd2.getName()).thenReturn("Device 2"); - cachedDevices.add(cbd2); - when(mCbm.getCachedDevicesCopy()).thenReturn(cachedDevices); - - assertThat(mController.getDeviceList().toString()).isEqualTo("Device 1, Device 2"); - } -} From 6adc5ab33497f093bf0dbc850888393b308e8e11 Mon Sep 17 00:00:00 2001 From: Yomna Nasser Date: Tue, 2 Mar 2021 22:09:17 +0000 Subject: [PATCH 18/23] Add metrics to Enable2gPreferenceController. Test: m & atest -c Enable2gPreferenceControllerTest & statsd_testdrive 97 Bug: b/181699391 Change-Id: I1ad860937cec7594c482706cadd853b115436594 --- .../network/telephony/Enable2gPreferenceController.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/com/android/settings/network/telephony/Enable2gPreferenceController.java b/src/com/android/settings/network/telephony/Enable2gPreferenceController.java index c7802341ce0..cf08d107528 100644 --- a/src/com/android/settings/network/telephony/Enable2gPreferenceController.java +++ b/src/com/android/settings/network/telephony/Enable2gPreferenceController.java @@ -15,6 +15,7 @@ */ package com.android.settings.network.telephony; +import android.app.settings.SettingsEnums; import android.content.Context; import android.os.PersistableBundle; import android.telephony.CarrierConfigManager; @@ -22,6 +23,9 @@ import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.util.Log; +import com.android.settings.overlay.FeatureFactory; +import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; + /** * Preference controller for "Enable 2G" */ @@ -34,6 +38,8 @@ public class Enable2gPreferenceController extends TelephonyTogglePreferenceContr | TelephonyManager.NETWORK_TYPE_BITMASK_CDMA | TelephonyManager.NETWORK_TYPE_BITMASK_1xRTT; + private final MetricsFeatureProvider mMetricsFeatureProvider; + private CarrierConfigManager mCarrierConfigManager; private TelephonyManager mTelephonyManager; @@ -46,6 +52,7 @@ public class Enable2gPreferenceController extends TelephonyTogglePreferenceContr public Enable2gPreferenceController(Context context, String key) { super(context, key); mCarrierConfigManager = context.getSystemService(CarrierConfigManager.class); + mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider(); } /** @@ -98,6 +105,8 @@ public class Enable2gPreferenceController extends TelephonyTogglePreferenceContr } mTelephonyManager.setAllowedNetworkTypesForReason( mTelephonyManager.ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G, newAllowedNetworkTypes); + mMetricsFeatureProvider.action( + mContext, SettingsEnums.ACTION_2G_ENABLED, isChecked); return true; } } From 8bd543fce45daf77f6719493a8205c5fac082c9c Mon Sep 17 00:00:00 2001 From: Sunny Shao Date: Thu, 4 Mar 2021 16:42:10 +0800 Subject: [PATCH 19/23] Add strings for new Intent Picker bug: 177923646 Test: compilation Change-Id: Icbd17a2979d0bb135e03103f27a205590cb843b9 --- res/values/strings.xml | 41 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/res/values/strings.xml b/res/values/strings.xml index 75884fade5e..ed8e2302e6e 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -4482,13 +4482,13 @@ Uninstall updates - You\u2019ve chosen to launch this app by default for some actions. + Some activities you\u2019ve selected open in this app by default. You\u2019ve chosen to allow this app to create widgets and access their data. No defaults set. - Clear defaults + Clear default preferences This app may not be designed for your screen. You can control how it adjusts to your screen here. @@ -9668,9 +9668,44 @@ Opening links Open supported links + + Supported links open in this app + + Links to open in this app + Open without asking Supported links - Other defaults + + Other default preferences + + Add link + + An app can verify links to automatically open in the app. Learn more + + + + %d verified link + %d verified links + + + This link is verified and automatically opens in this app. + These links are verified and automatically open in this app. + + + OK + + + Checking for other supported links\u2026 + + Cancel + + + + %d supported link + %d supported links + + + Add %1$s used in %2$s From a5571da12bef0dd1b1d38c06de72710b1379a83c Mon Sep 17 00:00:00 2001 From: Ahaan Ugale Date: Sun, 28 Feb 2021 22:10:51 -0800 Subject: [PATCH 20/23] AF: Show passwords settings for available autofill service. Separates autofill preferences into 2 categories - one for the passwords settings and one for the existing default service preference. The passwords preference controller dynamically creates preferences for each autofill service. Bug: 169455298 Test: manual Test: TODO new test for controller Change-Id: I369b5db00be75957c869df4d960595e9e1d9772c --- res/values/strings.xml | 4 +- res/xml/default_autofill_picker_settings.xml | 29 ++++-- .../PasswordsPreferenceController.java | 94 +++++++++++++++++++ 3 files changed, 118 insertions(+), 9 deletions(-) create mode 100644 src/com/android/settings/applications/autofill/PasswordsPreferenceController.java diff --git a/res/values/strings.xml b/res/values/strings.xml index 75884fade5e..9724b021ffd 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -11481,8 +11481,10 @@ Autofill service + + Passwords - auto, fill, autofill + auto, fill, autofill, password diff --git a/res/xml/default_autofill_picker_settings.xml b/res/xml/default_autofill_picker_settings.xml index bfc285bf5ee..392f733ba56 100644 --- a/res/xml/default_autofill_picker_settings.xml +++ b/res/xml/default_autofill_picker_settings.xml @@ -22,14 +22,27 @@ android:title="@string/autofill_app" settings:keywords="@string/autofill_keywords"> - - - + + + + + + + + + + mServices; + + public PasswordsPreferenceController(Context context, String preferenceKey) { + super(context, preferenceKey); + mPm = context.getPackageManager(); + mIconFactory = IconDrawableFactory.newInstance(mContext); + mServices = AutofillServiceInfo.getAvailableServices(mContext, UserHandle.myUserId()); + for (int i = mServices.size() - 1; i >= 0; i--) { + final String passwordsActivity = mServices.get(i).getPasswordsActivity(); + if (TextUtils.isEmpty(passwordsActivity)) { + mServices.remove(i); + } + } + } + + @Override + public int getAvailabilityStatus() { + return mServices.isEmpty() ? CONDITIONALLY_UNAVAILABLE : AVAILABLE; + } + + @Override + public void displayPreference(PreferenceScreen screen) { + super.displayPreference(screen); + final PreferenceGroup group = screen.findPreference(getPreferenceKey()); + // TODO(b/169455298): Show work profile passwords too. + addPasswordPreferences(screen.getContext(), UserHandle.myUserId(), group); + } + + private void addPasswordPreferences( + Context prefContext, @UserIdInt int user, PreferenceGroup group) { + for (int i = 0; i < mServices.size(); i++) { + final AutofillServiceInfo service = mServices.get(i); + final Preference pref = new Preference(prefContext); + final ServiceInfo serviceInfo = service.getServiceInfo(); + pref.setTitle(serviceInfo.loadLabel(mPm)); + final Drawable icon = + mIconFactory.getBadgedIcon( + serviceInfo, + serviceInfo.applicationInfo, + user); + Utils.setSafeIcon(pref, icon); + pref.setIntent( + new Intent(Intent.ACTION_MAIN) + .setClassName(serviceInfo.packageName, service.getPasswordsActivity())); + group.addPreference(pref); + } + } +} From 280e3639cd3bbed3f2a5ce11bc42c7118a2b46b7 Mon Sep 17 00:00:00 2001 From: "Wesley.CW Wang" Date: Thu, 25 Feb 2021 18:13:46 +0800 Subject: [PATCH 21/23] Update Battery Settings main page (1/2) - Rollback ag/13413813 to meet the design change - Regrouping the index Screenshots: https://screenshot.googleplex.com/85aPq9ArJMWjJV2.png https://screenshot.googleplex.com/8uiZ9KLKAHoJyrP.png Bug: 177407113 Test: make RunSettingsRoboTests -j40 Change-Id: Ic3c16d985b7c5e98e6d1bbe4481c48eadd3e4078 --- res/xml/power_usage_summary.xml | 36 +++--- .../fuelgauge/BatterySaverController.java | 78 ++++++++----- .../fuelgauge/BatterySaverControllerTest.java | 103 +++++++----------- 3 files changed, 111 insertions(+), 106 deletions(-) diff --git a/res/xml/power_usage_summary.xml b/res/xml/power_usage_summary.xml index b5e414b487c..75bbca048e9 100644 --- a/res/xml/power_usage_summary.xml +++ b/res/xml/power_usage_summary.xml @@ -17,6 +17,7 @@ @@ -31,6 +32,7 @@ android:fragment="com.android.settings.fuelgauge.PowerUsageAdvanced" android:key="battery_usage_summary" android:title="@string/advanced_battery_preference_title" + app:iconSpaceReserved="false" settings:searchable="false" /> - + + + - + + - + + Date: Fri, 5 Mar 2021 03:30:11 +0800 Subject: [PATCH 22/23] Update new consent screen for fingerprint - Move top description into subtitle for landscape mode - Update the button text Bug: 177591560 Test: robotest and visual verified 1) Settings -> Security -> Fingerprint 2) Rotate the device and check if the description is on the right side Change-Id: Ie20597fce48f73aa83c5d637682db1860c384a7a --- ...c_fingerprint_introduction_shield_24dp.xml | 45 +++++++++ .../fingerprint_enroll_introduction.xml | 95 +++++++++++++++---- res/values/strings.xml | 18 +++- .../biometrics/BiometricEnrollBase.java | 4 + .../BiometricEnrollIntroduction.java | 3 +- .../FingerprintEnrollIntroduction.java | 6 +- 6 files changed, 145 insertions(+), 26 deletions(-) create mode 100644 res/drawable/ic_fingerprint_introduction_shield_24dp.xml diff --git a/res/drawable/ic_fingerprint_introduction_shield_24dp.xml b/res/drawable/ic_fingerprint_introduction_shield_24dp.xml new file mode 100644 index 00000000000..28c998471e9 --- /dev/null +++ b/res/drawable/ic_fingerprint_introduction_shield_24dp.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/res/layout/fingerprint_enroll_introduction.xml b/res/layout/fingerprint_enroll_introduction.xml index 0aa18fbc89f..8555f1ab13a 100644 --- a/res/layout/fingerprint_enroll_introduction.xml +++ b/res/layout/fingerprint_enroll_introduction.xml @@ -30,23 +30,16 @@ android:clipToPadding="false" android:orientation="vertical"> - - - + android:layout_marginVertical="12dp"> - + - - + android:orientation="vertical"> + android:textAlignment="viewStart" + android:paddingTop="12dp" + android:text="@string/security_settings_fingerprint_enroll_introduction_footer_title_1" /> + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/res/values/strings.xml b/res/values/strings.xml index 75884fade5e..41a8e0a4518 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -884,13 +884,21 @@ - Unlock with fingerprint - + Set up your fingerprint + Use your fingerprint Just touch the fingerprint sensor to unlock your phone, authorize purchases, or sign in to apps. Be careful whose fingerprints you add. Even one added print can do any of these things. + + You\u2019re in control + + Keep in mind - Your fingerprint may be less secure than a strong pattern or PIN. + The data recorded by Fingerprint is stored securely and never leaves your phone. You can delete your data anytime in Settings. + + Your fingerprint may be less secure than a strong pattern or PIN. + + Your phone will occasionally use your recent fingerprint images to create improved fingerprint models. Use your fingerprint to unlock your phone or approve purchases.\n\nNote: You can\u2019t use your fingerprint to unlock this device. For more information, contact your organization\u2019s admin. @@ -899,8 +907,12 @@ Cancel No thanks + + Skip Continue + + Agree Skip diff --git a/src/com/android/settings/biometrics/BiometricEnrollBase.java b/src/com/android/settings/biometrics/BiometricEnrollBase.java index 7936f66a726..3fb89411190 100644 --- a/src/com/android/settings/biometrics/BiometricEnrollBase.java +++ b/src/com/android/settings/biometrics/BiometricEnrollBase.java @@ -173,6 +173,10 @@ public abstract class BiometricEnrollBase extends InstrumentedActivity { setHeaderText(resId, false /* force */); } + protected void setDescriptionText(int resId) { + getLayout().setDescriptionText(resId); + } + protected FooterButton getNextButton() { if (mFooterBarMixin != null) { return mFooterBarMixin.getPrimaryButton(); diff --git a/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java b/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java index 26df474aa55..09344b0d0dd 100644 --- a/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java +++ b/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java @@ -309,9 +309,8 @@ public abstract class BiometricEnrollIntroduction extends BiometricEnrollBase protected void initViews() { super.initViews(); - TextView description = (TextView) findViewById(R.id.sud_layout_description); if (mBiometricUnlockDisabledByAdmin) { - description.setText(getDescriptionResDisabledByAdmin()); + setDescriptionText(getDescriptionResDisabledByAdmin()); } } } diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroduction.java b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroduction.java index 23a11339525..0996a582d44 100644 --- a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroduction.java +++ b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroduction.java @@ -57,6 +57,8 @@ public class FingerprintEnrollIntroduction extends BiometricEnrollIntroduction { super.onCreate(savedInstanceState); + setDescriptionText(R.string.security_settings_fingerprint_enroll_introduction_message); + mFooterBarMixin = getLayout().getMixin(FooterBarMixin.class); mFooterBarMixin.setSecondaryButton( new FooterButton.Builder(this) @@ -69,7 +71,7 @@ public class FingerprintEnrollIntroduction extends BiometricEnrollIntroduction { mFooterBarMixin.setPrimaryButton( new FooterButton.Builder(this) - .setText(R.string.wizard_next) + .setText(R.string.security_settings_fingerprint_enroll_introduction_agree) .setListener(this::onNextButtonClick) .setButtonType(FooterButton.ButtonType.NEXT) .setTheme(R.style.SudGlifButton_Primary) @@ -78,7 +80,7 @@ public class FingerprintEnrollIntroduction extends BiometricEnrollIntroduction { } int getNegativeButtonTextId() { - return R.string.security_settings_fingerprint_enroll_introduction_no_thanks; + return R.string.security_settings_fingerprint_enroll_introduction_skip; } @Override From 8aaa9b1b246b2326663f8aa09cba76e936fc131f Mon Sep 17 00:00:00 2001 From: Julia Reynolds Date: Thu, 4 Mar 2021 14:53:26 -0500 Subject: [PATCH 23/23] NLS settings polish - Update strings - Link to NLS page from notifications - And fix an ordering issue on that page Test: manual Fixes: 181855978 Fixes: 181125178 Change-Id: I93d975763326d1e6d0cd02887abc515ad55329d0 --- res/values/strings.xml | 35 ++++++++----------- .../configure_notification_settings_v2.xml | 21 +++++++++++ ...ification_access_bridged_apps_settings.xml | 2 +- ...notification_access_permission_details.xml | 5 +++ .../NotificationAccessDetails.java | 10 +----- 5 files changed, 43 insertions(+), 30 deletions(-) diff --git a/res/values/strings.xml b/res/values/strings.xml index 75884fade5e..137a86bbd3e 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -8773,8 +8773,10 @@ Never - - Notification access + + Device & app notifications + + Control which notifications show on your apps and devices @@ -8833,26 +8835,19 @@ Turn off Cancel Allowed notification types - Important ongoing notifications - Conversation notifications - Alerting notifications - Silent notifications - - - Apps that are not bridged to this listener - - - All apps are bridged - - - - %d app is not bridged - %d apps are not bridged - + Real-time + Real-time communication from apps in use, navigation, phone calls, and more + Conversations + SMS and other communications + Default + Notifications that may ring or vibrate based on settings + Silent + Notifications that never make sound or vibrations - Bridged apps + See all apps + Change notification settings for each app that can send notifications + Apps shown on device VR helper services diff --git a/res/xml/configure_notification_settings_v2.xml b/res/xml/configure_notification_settings_v2.xml index 902922087c6..b7cc2c86a0d 100644 --- a/res/xml/configure_notification_settings_v2.xml +++ b/res/xml/configure_notification_settings_v2.xml @@ -23,12 +23,14 @@ android:title="@string/conversation_notifs_category"> @@ -58,6 +61,7 @@ android:title="@string/lock_screen_notifications_title"> + diff --git a/res/xml/notification_access_bridged_apps_settings.xml b/res/xml/notification_access_bridged_apps_settings.xml index 590a468f07f..535a0401da6 100644 --- a/res/xml/notification_access_bridged_apps_settings.xml +++ b/res/xml/notification_access_bridged_apps_settings.xml @@ -19,7 +19,7 @@ xmlns:android="http://schemas.android.com/apk/res/android" xmlns:settings="http://schemas.android.com/apk/res-auto" android:key="nonbridged_apps" - android:title="@string/notif_listener_excluded_app_title" + android:title="@string/notif_listener_excluded_app_screen_title" settings:controller="com.android.settings.applications.specialaccess.notificationaccess.BridgedAppsPreferenceController" settings:searchable="false"> diff --git a/res/xml/notification_access_permission_details.xml b/res/xml/notification_access_permission_details.xml index 0b764301153..c4bb7f069a5 100644 --- a/res/xml/notification_access_permission_details.xml +++ b/res/xml/notification_access_permission_details.xml @@ -34,27 +34,32 @@ diff --git a/src/com/android/settings/applications/specialaccess/notificationaccess/NotificationAccessDetails.java b/src/com/android/settings/applications/specialaccess/notificationaccess/NotificationAccessDetails.java index 16aa07883e6..1ac578d8e3c 100644 --- a/src/com/android/settings/applications/specialaccess/notificationaccess/NotificationAccessDetails.java +++ b/src/com/android/settings/applications/specialaccess/notificationaccess/NotificationAccessDetails.java @@ -60,7 +60,6 @@ public class NotificationAccessDetails extends DashboardFragment { private static final String TAG = "NotifAccessDetails"; private NotificationBackend mNm = new NotificationBackend(); - private NotificationListenerFilter mNlf; private ComponentName mComponentName; private CharSequence mServiceName; protected ServiceInfo mServiceInfo; @@ -157,13 +156,6 @@ public class NotificationAccessDetails extends DashboardFragment { Preference apps = getPreferenceScreen().findPreference( use(BridgedAppsPreferenceController.class).getPreferenceKey()); if (apps != null) { - mNlf = mNm.getListenerFilter(mComponentName, mUserId); - int nonBridgedCount = mNlf.getDisallowedPackages().size(); - apps.setSummary(nonBridgedCount == 0 ? - getString(R.string.notif_listener_excluded_summary_zero) - : getResources().getQuantityString( - R.plurals.notif_listener_excluded_summary_nonzero, - nonBridgedCount, nonBridgedCount)); apps.setOnPreferenceClickListener(preference -> { final Bundle args = new Bundle(); @@ -174,7 +166,7 @@ public class NotificationAccessDetails extends DashboardFragment { new SubSettingLauncher(getContext()) .setDestination(BridgedAppsSettings.class.getName()) .setSourceMetricsCategory(getMetricsCategory()) - .setTitleRes(R.string.notif_listener_excluded_app_title) + .setTitleRes(R.string.notif_listener_excluded_app_screen_title) .setArguments(args) .setUserHandle(UserHandle.of(mUserId)) .launch();