From e4f785c773bd6b4aca64558451836c6c18e13f0a Mon Sep 17 00:00:00 2001 From: Mill Chen Date: Wed, 24 Apr 2024 08:38:14 +0000 Subject: [PATCH 01/14] Redirect Volume Panel to settings page Flag: com.android.settings.flags.slices_retirement Bug: 328529042 Bug: 202262476 Test: manual test adb shell am start -a android.settings.panel.action.VOLUME Change-Id: I54f30d18eb10db864dcf5ee745b168b03e388b14 --- .../settings/panel/PanelFeatureProviderImpl.java | 13 ++++++++++++- .../panel/PanelFeatureProviderImplTest.java | 4 ++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/com/android/settings/panel/PanelFeatureProviderImpl.java b/src/com/android/settings/panel/PanelFeatureProviderImpl.java index 71711f9228e..d73edfca42e 100644 --- a/src/com/android/settings/panel/PanelFeatureProviderImpl.java +++ b/src/com/android/settings/panel/PanelFeatureProviderImpl.java @@ -22,11 +22,15 @@ import android.os.Bundle; import android.provider.Settings; import android.util.FeatureFlagUtils; +import androidx.annotation.Nullable; + import com.android.settings.Utils; +import com.android.settings.flags.Flags; public class PanelFeatureProviderImpl implements PanelFeatureProvider { @Override + @Nullable public PanelContent getPanel(Context context, Bundle bundle) { if (context == null) { return null; @@ -59,7 +63,14 @@ public class PanelFeatureProviderImpl implements PanelFeatureProvider { context.sendBroadcast(volumeIntent); return null; } else { - return VolumePanel.create(context); + if (Flags.slicesRetirement()) { + Intent volIntent = new Intent(Settings.ACTION_SOUND_SETTINGS); + volIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + context.startActivity(volIntent); + return null; + } else { + return VolumePanel.create(context); + } } } diff --git a/tests/unit/src/com/android/settings/panel/PanelFeatureProviderImplTest.java b/tests/unit/src/com/android/settings/panel/PanelFeatureProviderImplTest.java index 4b08ef8bfa8..d2f53f948e3 100644 --- a/tests/unit/src/com/android/settings/panel/PanelFeatureProviderImplTest.java +++ b/tests/unit/src/com/android/settings/panel/PanelFeatureProviderImplTest.java @@ -27,12 +27,15 @@ import static org.mockito.Mockito.verify; import android.content.Context; import android.content.Intent; import android.os.Bundle; +import android.platform.test.annotations.DisableFlags; import android.provider.Settings; import android.util.FeatureFlagUtils; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; +import com.android.settings.flags.Flags; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -68,6 +71,7 @@ public class PanelFeatureProviderImplTest { } @Test + @DisableFlags(Flags.FLAG_SLICES_RETIREMENT) public void getPanel_volumePanel_returnsCorrectPanel() { FeatureFlagUtils.setEnabled(mContext, FeatureFlagUtils.SETTINGS_VOLUME_PANEL_IN_SYSTEMUI, false); From 4c061771b77dadad403924bf9b4cb88e8ba42183 Mon Sep 17 00:00:00 2001 From: Mill Chen Date: Mon, 6 May 2024 22:12:23 +0000 Subject: [PATCH 02/14] Deprecated Wifi panel and relevant objects Bug: 328529085 Test: robotest Change-Id: I960718acbdf1d2be6c3b6b396cf2ac69d4aa3046 --- src/com/android/settings/panel/WifiPanel.java | 3 +++ src/com/android/settings/wifi/slice/ConnectToWifiHandler.java | 3 +++ src/com/android/settings/wifi/slice/WifiScanWorker.java | 3 +++ src/com/android/settings/wifi/slice/WifiSlice.java | 3 +++ src/com/android/settings/wifi/slice/WifiSliceItem.java | 3 +++ .../com/android/settings/wifi/slice/WifiScanWorkerTest.java | 1 + .../src/com/android/settings/wifi/slice/WifiSliceTest.java | 1 + tests/unit/src/com/android/settings/panel/WifiPanelTest.java | 1 + 8 files changed, 18 insertions(+) diff --git a/src/com/android/settings/panel/WifiPanel.java b/src/com/android/settings/panel/WifiPanel.java index 3e713bcf7f4..2e97b413346 100644 --- a/src/com/android/settings/panel/WifiPanel.java +++ b/src/com/android/settings/panel/WifiPanel.java @@ -32,7 +32,10 @@ import java.util.List; /** * Panel data class for Wifi settings. + * + * @deprecated this is not used after V and will be removed. */ +@Deprecated(forRemoval = true) public class WifiPanel implements PanelContent { private final Context mContext; diff --git a/src/com/android/settings/wifi/slice/ConnectToWifiHandler.java b/src/com/android/settings/wifi/slice/ConnectToWifiHandler.java index 779a57e40f3..e2fa2db6962 100644 --- a/src/com/android/settings/wifi/slice/ConnectToWifiHandler.java +++ b/src/com/android/settings/wifi/slice/ConnectToWifiHandler.java @@ -32,7 +32,10 @@ import com.android.wifitrackerlib.WifiEntry.ConnectCallback; /** * This receiver helps connect to Wi-Fi network + * + * @deprecated this is not used after V and will be removed. */ +@Deprecated(forRemoval = true) public class ConnectToWifiHandler extends BroadcastReceiver { static final String KEY_CHOSEN_WIFIENTRY_KEY = "key_chosen_wifientry_key"; diff --git a/src/com/android/settings/wifi/slice/WifiScanWorker.java b/src/com/android/settings/wifi/slice/WifiScanWorker.java index 4f1f64dd060..1161af02853 100644 --- a/src/com/android/settings/wifi/slice/WifiScanWorker.java +++ b/src/com/android/settings/wifi/slice/WifiScanWorker.java @@ -39,7 +39,10 @@ import java.util.List; /** * {@link SliceBackgroundWorker} for Wi-Fi, used by {@link WifiSlice}. + * + * @deprecated this is not used after V and will be removed. */ +@Deprecated(forRemoval = true) public class WifiScanWorker extends SliceBackgroundWorker implements WifiPickerTracker.WifiPickerTrackerCallback, LifecycleOwner, WifiEntryCallback { diff --git a/src/com/android/settings/wifi/slice/WifiSlice.java b/src/com/android/settings/wifi/slice/WifiSlice.java index f75fe11953d..a849c41328b 100644 --- a/src/com/android/settings/wifi/slice/WifiSlice.java +++ b/src/com/android/settings/wifi/slice/WifiSlice.java @@ -70,7 +70,10 @@ import java.util.stream.Collectors; /** * {@link CustomSliceable} for Wi-Fi, used by generic clients. + * + * @deprecated This is not used after V and will be removed. */ +@Deprecated(forRemoval = true) public class WifiSlice implements CustomSliceable { @VisibleForTesting diff --git a/src/com/android/settings/wifi/slice/WifiSliceItem.java b/src/com/android/settings/wifi/slice/WifiSliceItem.java index c6f85e52a03..7a9cda20cde 100644 --- a/src/com/android/settings/wifi/slice/WifiSliceItem.java +++ b/src/com/android/settings/wifi/slice/WifiSliceItem.java @@ -26,7 +26,10 @@ import com.android.wifitrackerlib.WifiEntry; /** * The data set which is needed by a Wi-Fi Slice, it collects necessary data from {@link WifiEntry} * and provides similar getter methods for corresponding data. + * + * @deprecated this is not used after V and will be removed. */ +@Deprecated(forRemoval = true) public class WifiSliceItem { private final Context mContext; diff --git a/tests/robotests/src/com/android/settings/wifi/slice/WifiScanWorkerTest.java b/tests/robotests/src/com/android/settings/wifi/slice/WifiScanWorkerTest.java index 54a546a83e0..4262b8dc987 100644 --- a/tests/robotests/src/com/android/settings/wifi/slice/WifiScanWorkerTest.java +++ b/tests/robotests/src/com/android/settings/wifi/slice/WifiScanWorkerTest.java @@ -48,6 +48,7 @@ import org.robolectric.RobolectricTestRunner; import java.util.Arrays; +@Deprecated(forRemoval = true) @RunWith(RobolectricTestRunner.class) public class WifiScanWorkerTest { diff --git a/tests/robotests/src/com/android/settings/wifi/slice/WifiSliceTest.java b/tests/robotests/src/com/android/settings/wifi/slice/WifiSliceTest.java index 5c3f920dd54..c9cf5a2a852 100644 --- a/tests/robotests/src/com/android/settings/wifi/slice/WifiSliceTest.java +++ b/tests/robotests/src/com/android/settings/wifi/slice/WifiSliceTest.java @@ -72,6 +72,7 @@ import org.robolectric.shadows.ShadowBinder; import java.util.ArrayList; import java.util.List; +@Deprecated(forRemoval = true) @RunWith(RobolectricTestRunner.class) @Config(shadows = { WifiSliceTest.ShadowSliceBackgroundWorker.class, diff --git a/tests/unit/src/com/android/settings/panel/WifiPanelTest.java b/tests/unit/src/com/android/settings/panel/WifiPanelTest.java index b03075e69f0..29265f40ffe 100644 --- a/tests/unit/src/com/android/settings/panel/WifiPanelTest.java +++ b/tests/unit/src/com/android/settings/panel/WifiPanelTest.java @@ -31,6 +31,7 @@ import org.junit.runner.RunWith; import java.util.List; +@Deprecated(forRemoval = true) @RunWith(AndroidJUnit4.class) public class WifiPanelTest { From 840aa5e40b0bb732516899d7059c16221f450730 Mon Sep 17 00:00:00 2001 From: Mill Chen Date: Mon, 6 May 2024 22:27:02 +0000 Subject: [PATCH 03/14] Deprecate Nfc panel and relevant objects Bug: 328528962 Test: robotest Change-Id: Ia2acf4268e9a444d8b4cfe36c6eb2bd198f4be64 --- src/com/android/settings/panel/NfcPanel.java | 1 + tests/unit/src/com/android/settings/panel/NfcPanelTest.java | 1 + 2 files changed, 2 insertions(+) diff --git a/src/com/android/settings/panel/NfcPanel.java b/src/com/android/settings/panel/NfcPanel.java index 6b1e43525b4..ce4a719162f 100644 --- a/src/com/android/settings/panel/NfcPanel.java +++ b/src/com/android/settings/panel/NfcPanel.java @@ -30,6 +30,7 @@ import com.android.settings.slices.SliceBuilderUtils; import java.util.ArrayList; import java.util.List; +@Deprecated(forRemoval = true) public class NfcPanel implements PanelContent { private final Context mContext; diff --git a/tests/unit/src/com/android/settings/panel/NfcPanelTest.java b/tests/unit/src/com/android/settings/panel/NfcPanelTest.java index 60adfdd1bcb..c7b31bd9443 100644 --- a/tests/unit/src/com/android/settings/panel/NfcPanelTest.java +++ b/tests/unit/src/com/android/settings/panel/NfcPanelTest.java @@ -31,6 +31,7 @@ import org.junit.runner.RunWith; import java.util.List; +@Deprecated(forRemoval = true) @RunWith(AndroidJUnit4.class) public class NfcPanelTest { From f4d7fe308287195923a9d61404a49070a7b8ea83 Mon Sep 17 00:00:00 2001 From: Mill Chen Date: Mon, 6 May 2024 22:31:17 +0000 Subject: [PATCH 04/14] Deprecate Volume panel and relevant objects Bug: 328529042 Test: robotest Change-Id: I462ddb72b2f764a016d957cc4195fc8298c5f21d --- src/com/android/settings/panel/VolumePanel.java | 3 +++ .../src/com/android/settings/panel/VolumePanelTest.java | 1 + 2 files changed, 4 insertions(+) diff --git a/src/com/android/settings/panel/VolumePanel.java b/src/com/android/settings/panel/VolumePanel.java index 4f38504d5e6..16b0cd1c894 100644 --- a/src/com/android/settings/panel/VolumePanel.java +++ b/src/com/android/settings/panel/VolumePanel.java @@ -57,7 +57,10 @@ import java.util.concurrent.FutureTask; /** * Panel data class for Volume settings. + * + * @deprecated this is no longer used after V and will be removed. */ +@Deprecated(forRemoval = true) public class VolumePanel implements PanelContent, LifecycleObserver { private static final String TAG = "VolumePanel"; diff --git a/tests/robotests/src/com/android/settings/panel/VolumePanelTest.java b/tests/robotests/src/com/android/settings/panel/VolumePanelTest.java index d30ef3eb3e9..91b3a4a9aad 100644 --- a/tests/robotests/src/com/android/settings/panel/VolumePanelTest.java +++ b/tests/robotests/src/com/android/settings/panel/VolumePanelTest.java @@ -35,6 +35,7 @@ import org.robolectric.RuntimeEnvironment; import java.util.List; +@Deprecated(forRemoval = true) @RunWith(RobolectricTestRunner.class) public class VolumePanelTest { From 1df242994a0b2e66872863821f65909ae93d0fba Mon Sep 17 00:00:00 2001 From: mxyyiyi Date: Mon, 6 May 2024 19:30:32 +0800 Subject: [PATCH 05/14] Add new action to log battery optimizaition mode updated by Turbo. Bug: 338965652 Test: atest SettingsRoboTests:com.android.settings.fuelgauge.BatteryOptimizeUtilsTest Change-Id: I80a53d327fee4b0442784e9b20617029f0e63f46 --- protos/fuelgauge_log.proto | 1 + 1 file changed, 1 insertion(+) diff --git a/protos/fuelgauge_log.proto b/protos/fuelgauge_log.proto index 36126a5b52d..4bee75ca058 100644 --- a/protos/fuelgauge_log.proto +++ b/protos/fuelgauge_log.proto @@ -20,6 +20,7 @@ message BatteryOptimizeHistoricalLogEntry { RESTORE = 4; BACKUP = 5; FORCE_RESET = 6; + EXTERNAL_UPDATE = 7; } optional string package_name = 1; From 137b5e503c73b42a1035b8cac1f1c2d607b6cf22 Mon Sep 17 00:00:00 2001 From: songferngwang Date: Tue, 7 May 2024 08:32:25 +0000 Subject: [PATCH 06/14] Avoid to show sim onboarding during the SUW Bug: 339154888 Test: build pass Change-Id: Ic0c5b22284a046d76cb1d07e5f6928d1e4c71d2d --- .../android/settings/sim/receivers/SimSlotChangeHandler.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/com/android/settings/sim/receivers/SimSlotChangeHandler.java b/src/com/android/settings/sim/receivers/SimSlotChangeHandler.java index 61d91114119..be40f2961a6 100644 --- a/src/com/android/settings/sim/receivers/SimSlotChangeHandler.java +++ b/src/com/android/settings/sim/receivers/SimSlotChangeHandler.java @@ -385,6 +385,10 @@ public class SimSlotChangeHandler { } private void startSimConfirmDialogActivity(int subId) { + if (!isSuwFinished(mContext)) { + Log.d(TAG, "Still in SUW. Do nothing"); + return; + } if (!SubscriptionManager.isUsableSubscriptionId(subId)) { Log.i(TAG, "Unable to enable subscription due to invalid subscription ID."); return; From 0a9e7046cc2b7f630285aeb5a3d6aa6d32e8e857 Mon Sep 17 00:00:00 2001 From: Mengjun Leng Date: Thu, 25 Apr 2024 12:53:47 +0530 Subject: [PATCH 07/14] Refacotr mobile data observer for repository In current design, the mobile data observer might be removed due to SIM absence after registered so that mobile data network info can't be updated to clients. To fix it, migrate it to use API TelephonyCallback.onUserMobileDataStateChanged Change-Id: I26c8f946823abb7505f0227c8dd8ab0700d0c5f2 Merged-In: I26c8f946823abb7505f0227c8dd8ab0700d0c5f2 --- .../network/MobileNetworkRepository.java | 46 +++++++++---------- .../DefaultSubscriptionController.java | 3 -- 2 files changed, 21 insertions(+), 28 deletions(-) diff --git a/src/com/android/settings/network/MobileNetworkRepository.java b/src/com/android/settings/network/MobileNetworkRepository.java index b0c85fcfdfc..0796dee4f8a 100644 --- a/src/com/android/settings/network/MobileNetworkRepository.java +++ b/src/com/android/settings/network/MobileNetworkRepository.java @@ -91,7 +91,6 @@ public class MobileNetworkRepository extends SubscriptionManager.OnSubscriptions private AirplaneModeObserver mAirplaneModeObserver; private DataRoamingObserver mDataRoamingObserver; private MetricsFeatureProvider mMetricsFeatureProvider; - private Map mDataContentObserverMap = new HashMap<>(); private int mPhysicalSlotIndex = SubscriptionManager.INVALID_SIM_SLOT_INDEX; private int mLogicalSlotIndex = SubscriptionManager.INVALID_SIM_SLOT_INDEX; private int mCardState = UiccSlotInfo.CARD_STATE_INFO_ABSENT; @@ -209,6 +208,9 @@ public class MobileNetworkRepository extends SubscriptionManager.OnSubscriptions */ public void addRegister(LifecycleOwner lifecycleOwner, MobileNetworkCallback mobileNetworkCallback, int subId) { + if (DEBUG) { + Log.d(TAG, "addRegister by SUB ID " + subId); + } if (sCallbacks.isEmpty()) { mSubscriptionManager.addOnSubscriptionsChangedListener(mContext.getMainExecutor(), this); @@ -222,7 +224,6 @@ public class MobileNetworkRepository extends SubscriptionManager.OnSubscriptions observeAllUiccInfo(lifecycleOwner); observeAllMobileNetworkInfo(lifecycleOwner); if (subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) { - addRegisterBySubId(subId); createTelephonyManagerBySubId(subId); mDataRoamingObserver.register(mContext, subId); } @@ -231,25 +232,12 @@ public class MobileNetworkRepository extends SubscriptionManager.OnSubscriptions sendAvailableSubInfoCache(mobileNetworkCallback); } - public void addRegisterBySubId(int subId) { - MobileDataContentObserver dataContentObserver = new MobileDataContentObserver( - new Handler(Looper.getMainLooper())); - dataContentObserver.setOnMobileDataChangedListener(() -> { - sExecutor.execute(() -> { - insertMobileNetworkInfo(mContext, subId, - getTelephonyManagerBySubId(mContext, subId)); - }); - }); - dataContentObserver.register(mContext, subId); - mDataContentObserverMap.put(subId, dataContentObserver); - } - private void createTelephonyManagerBySubId(int subId) { if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) { return; } PhoneCallStateTelephonyCallback - telephonyCallback = new PhoneCallStateTelephonyCallback(); + telephonyCallback = new PhoneCallStateTelephonyCallback(subId); TelephonyManager telephonyManager = mContext.getSystemService( TelephonyManager.class).createForSubscriptionId(subId); telephonyManager.registerTelephonyCallback(mContext.getMainExecutor(), @@ -288,10 +276,6 @@ public class MobileNetworkRepository extends SubscriptionManager.OnSubscriptions } } } - if (mDataContentObserverMap.containsKey(subId)) { - mDataContentObserverMap.get(subId).unRegister(mContext); - mDataContentObserverMap.remove(subId); - } } public void removeRegister(MobileNetworkCallback mobileNetworkCallback) { @@ -300,10 +284,6 @@ public class MobileNetworkRepository extends SubscriptionManager.OnSubscriptions mSubscriptionManager.removeOnSubscriptionsChangedListener(this); mAirplaneModeObserver.unRegister(mContext); mDataRoamingObserver.unRegister(mContext); - mDataContentObserverMap.forEach((id, observer) -> { - observer.unRegister(mContext); - }); - mDataContentObserverMap.clear(); mTelephonyManagerMap.forEach((id, manager) -> { TelephonyCallback callback = mTelephonyCallbackMap.get(id); @@ -764,7 +744,14 @@ public class MobileNetworkRepository extends SubscriptionManager.OnSubscriptions } private class PhoneCallStateTelephonyCallback extends TelephonyCallback implements - TelephonyCallback.CallStateListener { + TelephonyCallback.CallStateListener, + TelephonyCallback.UserMobileDataStateListener { + + private int mSubId; + + public PhoneCallStateTelephonyCallback(int subId) { + mSubId = subId; + } @Override public void onCallStateChanged(int state) { @@ -772,6 +759,15 @@ public class MobileNetworkRepository extends SubscriptionManager.OnSubscriptions callback.onCallStateChanged(state); } } + + @Override + public void onUserMobileDataStateChanged(boolean enabled) { + Log.d(TAG, "onUserMobileDataStateChanged enabled " + enabled + " on SUB " + mSubId); + sExecutor.execute(() -> { + insertMobileNetworkInfo(mContext, mSubId, + getTelephonyManagerBySubId(mContext, mSubId)); + }); + } } /** diff --git a/src/com/android/settings/network/telephony/DefaultSubscriptionController.java b/src/com/android/settings/network/telephony/DefaultSubscriptionController.java index 03ce7f66dc8..96c39f27df6 100644 --- a/src/com/android/settings/network/telephony/DefaultSubscriptionController.java +++ b/src/com/android/settings/network/telephony/DefaultSubscriptionController.java @@ -100,9 +100,6 @@ public abstract class DefaultSubscriptionController extends TelephonyBasePrefere mMobileNetworkRepository.addRegister(mLifecycleOwner, this, SubscriptionManager.INVALID_SUBSCRIPTION_ID); mMobileNetworkRepository.updateEntity(); - // Can not get default subId from database until get the callback, add register by subId - // later. - mMobileNetworkRepository.addRegisterBySubId(getDefaultSubscriptionId()); mDataSubscriptionChangedReceiver.registerReceiver(); } From 120adb234997ca9585cc9128361e3c8f9fc9f6a8 Mon Sep 17 00:00:00 2001 From: Mengjun Leng Date: Thu, 25 Apr 2024 12:53:47 +0530 Subject: [PATCH 08/14] Refacotr mobile data observer for repository In current design, the mobile data observer might be removed due to SIM absence after registered so that mobile data network info can't be updated to clients. To fix it, migrate it to use API TelephonyCallback.onUserMobileDataStateChanged Bug: 327696232 Change-Id: I26c8f946823abb7505f0227c8dd8ab0700d0c5f2 --- .../network/MobileNetworkRepository.java | 48 ++++++++----------- .../DefaultSubscriptionController.java | 3 -- 2 files changed, 21 insertions(+), 30 deletions(-) diff --git a/src/com/android/settings/network/MobileNetworkRepository.java b/src/com/android/settings/network/MobileNetworkRepository.java index 6820f10cebf..8ee5389bfca 100644 --- a/src/com/android/settings/network/MobileNetworkRepository.java +++ b/src/com/android/settings/network/MobileNetworkRepository.java @@ -91,7 +91,6 @@ public class MobileNetworkRepository extends SubscriptionManager.OnSubscriptions private AirplaneModeObserver mAirplaneModeObserver; private DataRoamingObserver mDataRoamingObserver; private MetricsFeatureProvider mMetricsFeatureProvider; - private Map mDataContentObserverMap = new HashMap<>(); private int mPhysicalSlotIndex = SubscriptionManager.INVALID_SIM_SLOT_INDEX; private int mLogicalSlotIndex = SubscriptionManager.INVALID_SIM_SLOT_INDEX; private int mCardState = UiccSlotInfo.CARD_STATE_INFO_ABSENT; @@ -210,6 +209,9 @@ public class MobileNetworkRepository extends SubscriptionManager.OnSubscriptions */ public void addRegister(LifecycleOwner lifecycleOwner, MobileNetworkCallback mobileNetworkCallback, int subId) { + if (DEBUG) { + Log.d(TAG, "addRegister by SUB ID " + subId); + } if (sCallbacks.isEmpty()) { mSubscriptionManager.addOnSubscriptionsChangedListener(mContext.getMainExecutor(), this); @@ -221,7 +223,6 @@ public class MobileNetworkRepository extends SubscriptionManager.OnSubscriptions observeAllUiccInfo(lifecycleOwner); observeAllMobileNetworkInfo(lifecycleOwner); if (subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) { - addRegisterBySubId(subId); createTelephonyManagerBySubId(subId); mDataRoamingObserver.register(mContext, subId); } @@ -230,21 +231,6 @@ public class MobileNetworkRepository extends SubscriptionManager.OnSubscriptions sendAvailableSubInfoCache(mobileNetworkCallback); } - public void addRegisterBySubId(int subId) { - Log.d(TAG, "MobileDataContentObserver addRegisterBySubId: " + subId); - MobileDataContentObserver dataContentObserver = new MobileDataContentObserver( - new Handler(Looper.getMainLooper())); - dataContentObserver.setOnMobileDataChangedListener(() -> { - sExecutor.execute(() -> { - Log.d(TAG, "MobileDataContentObserver changed"); - insertMobileNetworkInfo(mContext, subId, - getTelephonyManagerBySubId(mContext, subId)); - }); - }); - dataContentObserver.register(mContext, subId); - mDataContentObserverMap.put(subId, dataContentObserver); - } - private void createTelephonyManagerBySubId(int subId) { if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID || mTelephonyCallbackMap.containsKey(subId)) { @@ -254,7 +240,7 @@ public class MobileNetworkRepository extends SubscriptionManager.OnSubscriptions return; } PhoneCallStateTelephonyCallback - telephonyCallback = new PhoneCallStateTelephonyCallback(); + telephonyCallback = new PhoneCallStateTelephonyCallback(subId); TelephonyManager telephonyManager = mContext.getSystemService( TelephonyManager.class).createForSubscriptionId(subId); telephonyManager.registerTelephonyCallback(mContext.getMainExecutor(), @@ -293,10 +279,6 @@ public class MobileNetworkRepository extends SubscriptionManager.OnSubscriptions } } } - if (mDataContentObserverMap.containsKey(subId)) { - mDataContentObserverMap.get(subId).unRegister(mContext); - mDataContentObserverMap.remove(subId); - } } public void removeRegister(MobileNetworkCallback mobileNetworkCallback) { @@ -307,10 +289,6 @@ public class MobileNetworkRepository extends SubscriptionManager.OnSubscriptions mSubscriptionManager.removeOnSubscriptionsChangedListener(this); mAirplaneModeObserver.unRegister(mContext); mDataRoamingObserver.unRegister(mContext); - mDataContentObserverMap.forEach((id, observer) -> { - observer.unRegister(mContext); - }); - mDataContentObserverMap.clear(); mTelephonyManagerMap.forEach((id, manager) -> { TelephonyCallback callback = mTelephonyCallbackMap.get(id); @@ -763,7 +741,14 @@ public class MobileNetworkRepository extends SubscriptionManager.OnSubscriptions } private class PhoneCallStateTelephonyCallback extends TelephonyCallback implements - TelephonyCallback.CallStateListener { + TelephonyCallback.CallStateListener, + TelephonyCallback.UserMobileDataStateListener { + + private int mSubId; + + public PhoneCallStateTelephonyCallback(int subId) { + mSubId = subId; + } @Override public void onCallStateChanged(int state) { @@ -771,6 +756,15 @@ public class MobileNetworkRepository extends SubscriptionManager.OnSubscriptions callback.onCallStateChanged(state); } } + + @Override + public void onUserMobileDataStateChanged(boolean enabled) { + Log.d(TAG, "onUserMobileDataStateChanged enabled " + enabled + " on SUB " + mSubId); + sExecutor.execute(() -> { + insertMobileNetworkInfo(mContext, mSubId, + getTelephonyManagerBySubId(mContext, mSubId)); + }); + } } /** diff --git a/src/com/android/settings/network/telephony/DefaultSubscriptionController.java b/src/com/android/settings/network/telephony/DefaultSubscriptionController.java index 024fb834968..fa8760c2205 100644 --- a/src/com/android/settings/network/telephony/DefaultSubscriptionController.java +++ b/src/com/android/settings/network/telephony/DefaultSubscriptionController.java @@ -100,9 +100,6 @@ public abstract class DefaultSubscriptionController extends TelephonyBasePrefere mMobileNetworkRepository.addRegister(mLifecycleOwner, this, SubscriptionManager.INVALID_SUBSCRIPTION_ID); mMobileNetworkRepository.updateEntity(); - // Can not get default subId from database until get the callback, add register by subId - // later. - mMobileNetworkRepository.addRegisterBySubId(getDefaultSubscriptionId()); mDataSubscriptionChangedReceiver.registerReceiver(); } From 8443ce8f9a29391cd29ba1d39b5e31da40191ec7 Mon Sep 17 00:00:00 2001 From: Fiona Campbell Date: Fri, 3 May 2024 14:50:11 +0000 Subject: [PATCH 09/14] Set EvenDimmer to true by default - Read from setting with true as fallback Bug: 336476693 Test: atest DisplayServiceTests Test: manual up/downgrade with settings / off Change-Id: I5279db2b35af9e84057d8f89bbbe9f26c62237c6 --- .../settings/display/EvenDimmerPreferenceController.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/com/android/settings/display/EvenDimmerPreferenceController.java b/src/com/android/settings/display/EvenDimmerPreferenceController.java index 9f239b2e1ad..2a0f16d2987 100644 --- a/src/com/android/settings/display/EvenDimmerPreferenceController.java +++ b/src/com/android/settings/display/EvenDimmerPreferenceController.java @@ -18,6 +18,7 @@ package com.android.settings.display; import android.content.Context; import android.content.res.Resources; +import android.os.UserHandle; import android.provider.Settings; import android.util.Log; @@ -79,7 +80,8 @@ public class EvenDimmerPreferenceController extends TogglePreferenceController { } private boolean getEvenDimmerActivated() { - return Settings.Secure.getFloat(mContext.getContentResolver(), - Settings.Secure.EVEN_DIMMER_ACTIVATED, 0) == 1; + return Settings.Secure.getFloatForUser(mContext.getContentResolver(), + Settings.Secure.EVEN_DIMMER_ACTIVATED, + /* def= */ 1.0f, UserHandle.USER_CURRENT) == 1.0f; } } From 107cca7a776ef539437f53950692e905f9eada28 Mon Sep 17 00:00:00 2001 From: Chaohui Wang Date: Tue, 7 May 2024 17:36:34 +0800 Subject: [PATCH 10/14] Fix data usage when policy has no cycle Fallback to four weeks, as the same as no policy. Fix: 336108815 Test: manual - on DataUsageList Test: unit test Change-Id: I63140a13ea3f3ee790cc911432fbdfd6247f7318 --- .../lib/NetworkCycleBucketRepository.kt | 16 ++--- .../lib/NetworkCycleDataRepository.kt | 22 +++---- .../lib/NetworkCycleBucketRepositoryTest.kt | 60 ++++++++++++++----- .../lib/NetworkCycleDataRepositoryTest.kt | 24 +++++++- 4 files changed, 84 insertions(+), 38 deletions(-) diff --git a/src/com/android/settings/datausage/lib/NetworkCycleBucketRepository.kt b/src/com/android/settings/datausage/lib/NetworkCycleBucketRepository.kt index 7e3e1832592..01f19651164 100644 --- a/src/com/android/settings/datausage/lib/NetworkCycleBucketRepository.kt +++ b/src/com/android/settings/datausage/lib/NetworkCycleBucketRepository.kt @@ -18,11 +18,10 @@ package com.android.settings.datausage.lib import android.content.Context import android.net.NetworkTemplate -import android.text.format.DateUtils import android.util.Range +import com.android.settings.datausage.lib.NetworkCycleDataRepository.Companion.asFourWeeks import com.android.settings.datausage.lib.NetworkCycleDataRepository.Companion.bucketRange import com.android.settings.datausage.lib.NetworkCycleDataRepository.Companion.getCycles -import com.android.settings.datausage.lib.NetworkCycleDataRepository.Companion.reverseBucketRange import com.android.settings.datausage.lib.NetworkStatsRepository.Companion.Bucket import com.android.settings.datausage.lib.NetworkStatsRepository.Companion.aggregate import com.android.settings.datausage.lib.NetworkStatsRepository.Companion.filterTime @@ -39,16 +38,11 @@ class NetworkCycleBucketRepository( getCycles().map { aggregateUsage(it) }.filter { it.usage > 0 } private fun getCycles(): List> = - networkCycleDataRepository.getPolicy()?.getCycles() ?: queryCyclesAsFourWeeks() + networkCycleDataRepository.getPolicy()?.getCycles().orEmpty() + .ifEmpty { queryCyclesAsFourWeeks() } - private fun queryCyclesAsFourWeeks(): List> { - val timeRange = buckets.aggregate()?.timeRange ?: return emptyList() - return reverseBucketRange( - startTime = timeRange.lower, - endTime = timeRange.upper, - step = DateUtils.WEEK_IN_MILLIS * 4, - ) - } + private fun queryCyclesAsFourWeeks(): List> = + buckets.aggregate()?.timeRange.asFourWeeks() fun queryChartData(usageData: NetworkUsageData) = NetworkCycleChartData( total = usageData, diff --git a/src/com/android/settings/datausage/lib/NetworkCycleDataRepository.kt b/src/com/android/settings/datausage/lib/NetworkCycleDataRepository.kt index 31052ef8763..d55524c7db3 100644 --- a/src/com/android/settings/datausage/lib/NetworkCycleDataRepository.kt +++ b/src/com/android/settings/datausage/lib/NetworkCycleDataRepository.kt @@ -42,16 +42,10 @@ class NetworkCycleDataRepository( fun loadFirstCycle(): NetworkUsageData? = getCycles().firstOrNull()?.let { queryUsage(it) } override fun getCycles(): List> = - getPolicy()?.getCycles() ?: queryCyclesAsFourWeeks() + getPolicy()?.getCycles().orEmpty().ifEmpty { queryCyclesAsFourWeeks() } - private fun queryCyclesAsFourWeeks(): List> { - val timeRange = networkStatsRepository.getTimeRange() ?: return emptyList() - return reverseBucketRange( - startTime = timeRange.lower, - endTime = timeRange.upper, - step = DateUtils.WEEK_IN_MILLIS * 4, - ) - } + private fun queryCyclesAsFourWeeks(): List> = + networkStatsRepository.getTimeRange().asFourWeeks() override fun getPolicy(): NetworkPolicy? = with(NetworkPolicyEditor(policyManager)) { @@ -59,7 +53,6 @@ class NetworkCycleDataRepository( getPolicy(networkTemplate) } - override fun queryUsage(range: Range) = NetworkUsageData( startTime = range.lower, endTime = range.upper, @@ -71,6 +64,15 @@ class NetworkCycleDataRepository( Range(it.lower.toInstant().toEpochMilli(), it.upper.toInstant().toEpochMilli()) }.toList() + fun Range?.asFourWeeks(): List> { + val timeRange = this ?: return emptyList() + return reverseBucketRange( + startTime = timeRange.lower, + endTime = timeRange.upper, + step = DateUtils.WEEK_IN_MILLIS * 4, + ) + } + fun bucketRange(startTime: Long, endTime: Long, step: Long): List> = (startTime..endTime step step).zipWithNext(::Range) diff --git a/tests/spa_unit/src/com/android/settings/datausage/lib/NetworkCycleBucketRepositoryTest.kt b/tests/spa_unit/src/com/android/settings/datausage/lib/NetworkCycleBucketRepositoryTest.kt index f83b85fd40d..81b57c995d5 100644 --- a/tests/spa_unit/src/com/android/settings/datausage/lib/NetworkCycleBucketRepositoryTest.kt +++ b/tests/spa_unit/src/com/android/settings/datausage/lib/NetworkCycleBucketRepositoryTest.kt @@ -42,6 +42,13 @@ class NetworkCycleBucketRepositoryTest { private val mockNetworkCycleDataRepository = mock() + private fun createRepository(buckets: List) = NetworkCycleBucketRepository( + context = context, + networkTemplate = template, + buckets = buckets, + networkCycleDataRepository = mockNetworkCycleDataRepository, + ) + @Test fun loadCycles_byPolicy() { val policy = mock { @@ -52,9 +59,7 @@ class NetworkCycleBucketRepositoryTest { mockNetworkCycleDataRepository.stub { on { getPolicy() } doReturn policy } - val repository = NetworkCycleBucketRepository( - context = context, - networkTemplate = template, + val repository = createRepository( buckets = listOf( Bucket( uid = 0, @@ -62,8 +67,7 @@ class NetworkCycleBucketRepositoryTest { startTimeStamp = CYCLE1_START_TIME, endTimeStamp = CYCLE1_END_TIME, ) - ), - networkCycleDataRepository = mockNetworkCycleDataRepository, + ) ) val cycles = repository.loadCycles() @@ -78,13 +82,14 @@ class NetworkCycleBucketRepositoryTest { } @Test - fun loadCycles_asFourWeeks() { - mockNetworkCycleDataRepository.stub { - on { getPolicy() } doReturn null + fun loadCycles_policyHasNoCycle_asFourWeeks() { + val policy = mock { + on { cycleIterator() } doReturn emptyList>().iterator() } - val repository = NetworkCycleBucketRepository( - context = context, - networkTemplate = template, + mockNetworkCycleDataRepository.stub { + on { getPolicy() } doReturn policy + } + val repository = createRepository( buckets = listOf( Bucket( uid = 0, @@ -92,8 +97,34 @@ class NetworkCycleBucketRepositoryTest { startTimeStamp = CYCLE2_START_TIME, endTimeStamp = CYCLE2_END_TIME, ) + ) + ) + + val cycles = repository.loadCycles() + + assertThat(cycles).containsExactly( + NetworkUsageData( + startTime = CYCLE2_END_TIME - DateUtils.WEEK_IN_MILLIS * 4, + endTime = CYCLE2_END_TIME, + usage = CYCLE2_BYTES, ), - networkCycleDataRepository = mockNetworkCycleDataRepository, + ) + } + + @Test + fun loadCycles_noPolicy_asFourWeeks() { + mockNetworkCycleDataRepository.stub { + on { getPolicy() } doReturn null + } + val repository = createRepository( + buckets = listOf( + Bucket( + uid = 0, + bytes = CYCLE2_BYTES, + startTimeStamp = CYCLE2_START_TIME, + endTimeStamp = CYCLE2_END_TIME, + ) + ) ) val cycles = repository.loadCycles() @@ -114,9 +145,7 @@ class NetworkCycleBucketRepositoryTest { endTime = CYCLE4_END_TIME, usage = CYCLE3_BYTES + CYCLE4_BYTES, ) - val repository = NetworkCycleBucketRepository( - context = context, - networkTemplate = template, + val repository = createRepository( buckets = listOf( Bucket( uid = 0, @@ -131,7 +160,6 @@ class NetworkCycleBucketRepositoryTest { endTimeStamp = CYCLE4_END_TIME, ), ), - networkCycleDataRepository = mockNetworkCycleDataRepository, ) val summary = repository.queryChartData(cycle) diff --git a/tests/spa_unit/src/com/android/settings/datausage/lib/NetworkCycleDataRepositoryTest.kt b/tests/spa_unit/src/com/android/settings/datausage/lib/NetworkCycleDataRepositoryTest.kt index 77fe843d8b3..c011af23851 100644 --- a/tests/spa_unit/src/com/android/settings/datausage/lib/NetworkCycleDataRepositoryTest.kt +++ b/tests/spa_unit/src/com/android/settings/datausage/lib/NetworkCycleDataRepositoryTest.kt @@ -25,6 +25,7 @@ import androidx.test.core.app.ApplicationProvider import androidx.test.ext.junit.runners.AndroidJUnit4 import com.android.settings.testutils.zonedDateTime import com.google.common.truth.Truth.assertThat +import java.time.ZonedDateTime import kotlinx.coroutines.test.runTest import org.junit.Test import org.junit.runner.RunWith @@ -77,7 +78,28 @@ class NetworkCycleDataRepositoryTest { } @Test - fun loadFirstCycle_asFourWeeks() = runTest { + fun loadFirstCycle_policyHasNoCycle_asFourWeeks() = runTest { + val policy = mock { + on { cycleIterator() } doReturn emptyList>().iterator() + } + doReturn(policy).whenever(repository).getPolicy() + mockNetworkStatsRepository.stub { + on { getTimeRange() } doReturn Range(CYCLE2_START_TIME, CYCLE2_END_TIME) + } + + val firstCycle = repository.loadFirstCycle() + + assertThat(firstCycle).isEqualTo( + NetworkUsageData( + startTime = CYCLE2_END_TIME - DateUtils.WEEK_IN_MILLIS * 4, + endTime = CYCLE2_END_TIME, + usage = CYCLE2_BYTES, + ), + ) + } + + @Test + fun loadFirstCycle_noPolicy_asFourWeeks() = runTest { doReturn(null).whenever(repository).getPolicy() mockNetworkStatsRepository.stub { on { getTimeRange() } doReturn Range(CYCLE2_START_TIME, CYCLE2_END_TIME) From 294e0db163971adaffcf5388d9cd9b9c151f8dc8 Mon Sep 17 00:00:00 2001 From: Mengjun Leng Date: Tue, 7 May 2024 14:11:54 +0530 Subject: [PATCH 11/14] Refacotr mobile data observer for repository In current design, the mobile data observer might be removed due to SIM absence after registered so that mobile data network info can't be updated to clients. To fix it, migrate it to use API TelephonyCallback.onUserMobileDataStateChanged Bug: 327696232 Test: manual + unit tests Change-Id: I26c8f946823abb7505f0227c8dd8ab0700d0c5f2 Merged-In: I26c8f946823abb7505f0227c8dd8ab0700d0c5f2 --- .../network/MobileNetworkRepository.java | 46 +++++++++---------- .../DefaultSubscriptionController.java | 3 -- 2 files changed, 21 insertions(+), 28 deletions(-) diff --git a/src/com/android/settings/network/MobileNetworkRepository.java b/src/com/android/settings/network/MobileNetworkRepository.java index 7bc61a49438..324b4b79a0b 100644 --- a/src/com/android/settings/network/MobileNetworkRepository.java +++ b/src/com/android/settings/network/MobileNetworkRepository.java @@ -91,7 +91,6 @@ public class MobileNetworkRepository extends SubscriptionManager.OnSubscriptions private AirplaneModeObserver mAirplaneModeObserver; private DataRoamingObserver mDataRoamingObserver; private MetricsFeatureProvider mMetricsFeatureProvider; - private Map mDataContentObserverMap = new HashMap<>(); private int mPhysicalSlotIndex = SubscriptionManager.INVALID_SIM_SLOT_INDEX; private int mLogicalSlotIndex = SubscriptionManager.INVALID_SIM_SLOT_INDEX; private int mCardState = UiccSlotInfo.CARD_STATE_INFO_ABSENT; @@ -209,6 +208,9 @@ public class MobileNetworkRepository extends SubscriptionManager.OnSubscriptions */ public void addRegister(LifecycleOwner lifecycleOwner, MobileNetworkCallback mobileNetworkCallback, int subId) { + if (DEBUG) { + Log.d(TAG, "addRegister by SUB ID " + subId); + } if (sCallbacks.isEmpty()) { mSubscriptionManager.addOnSubscriptionsChangedListener(mContext.getMainExecutor(), this); @@ -222,7 +224,6 @@ public class MobileNetworkRepository extends SubscriptionManager.OnSubscriptions observeAllUiccInfo(lifecycleOwner); observeAllMobileNetworkInfo(lifecycleOwner); if (subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) { - addRegisterBySubId(subId); createTelephonyManagerBySubId(subId); mDataRoamingObserver.register(mContext, subId); } @@ -231,19 +232,6 @@ public class MobileNetworkRepository extends SubscriptionManager.OnSubscriptions sendAvailableSubInfoCache(mobileNetworkCallback); } - public void addRegisterBySubId(int subId) { - MobileDataContentObserver dataContentObserver = new MobileDataContentObserver( - new Handler(Looper.getMainLooper())); - dataContentObserver.setOnMobileDataChangedListener(() -> { - sExecutor.execute(() -> { - insertMobileNetworkInfo(mContext, subId, - getTelephonyManagerBySubId(mContext, subId)); - }); - }); - dataContentObserver.register(mContext, subId); - mDataContentObserverMap.put(subId, dataContentObserver); - } - private void createTelephonyManagerBySubId(int subId) { if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID || mTelephonyCallbackMap.containsKey(subId)) { @@ -253,7 +241,7 @@ public class MobileNetworkRepository extends SubscriptionManager.OnSubscriptions return; } PhoneCallStateTelephonyCallback - telephonyCallback = new PhoneCallStateTelephonyCallback(); + telephonyCallback = new PhoneCallStateTelephonyCallback(subId); TelephonyManager telephonyManager = mContext.getSystemService( TelephonyManager.class).createForSubscriptionId(subId); telephonyManager.registerTelephonyCallback(mContext.getMainExecutor(), @@ -292,10 +280,6 @@ public class MobileNetworkRepository extends SubscriptionManager.OnSubscriptions } } } - if (mDataContentObserverMap.containsKey(subId)) { - mDataContentObserverMap.get(subId).unRegister(mContext); - mDataContentObserverMap.remove(subId); - } } public void removeRegister(MobileNetworkCallback mobileNetworkCallback) { @@ -304,10 +288,6 @@ public class MobileNetworkRepository extends SubscriptionManager.OnSubscriptions mSubscriptionManager.removeOnSubscriptionsChangedListener(this); mAirplaneModeObserver.unRegister(mContext); mDataRoamingObserver.unRegister(mContext); - mDataContentObserverMap.forEach((id, observer) -> { - observer.unRegister(mContext); - }); - mDataContentObserverMap.clear(); mTelephonyManagerMap.forEach((id, manager) -> { TelephonyCallback callback = mTelephonyCallbackMap.get(id); @@ -768,7 +748,14 @@ public class MobileNetworkRepository extends SubscriptionManager.OnSubscriptions } private class PhoneCallStateTelephonyCallback extends TelephonyCallback implements - TelephonyCallback.CallStateListener { + TelephonyCallback.CallStateListener, + TelephonyCallback.UserMobileDataStateListener { + + private int mSubId; + + public PhoneCallStateTelephonyCallback(int subId) { + mSubId = subId; + } @Override public void onCallStateChanged(int state) { @@ -776,6 +763,15 @@ public class MobileNetworkRepository extends SubscriptionManager.OnSubscriptions callback.onCallStateChanged(state); } } + + @Override + public void onUserMobileDataStateChanged(boolean enabled) { + Log.d(TAG, "onUserMobileDataStateChanged enabled " + enabled + " on SUB " + mSubId); + sExecutor.execute(() -> { + insertMobileNetworkInfo(mContext, mSubId, + getTelephonyManagerBySubId(mContext, mSubId)); + }); + } } /** diff --git a/src/com/android/settings/network/telephony/DefaultSubscriptionController.java b/src/com/android/settings/network/telephony/DefaultSubscriptionController.java index 84263821e50..84cd874318a 100644 --- a/src/com/android/settings/network/telephony/DefaultSubscriptionController.java +++ b/src/com/android/settings/network/telephony/DefaultSubscriptionController.java @@ -96,9 +96,6 @@ public abstract class DefaultSubscriptionController extends TelephonyBasePrefere mMobileNetworkRepository.addRegister(mLifecycleOwner, this, SubscriptionManager.INVALID_SUBSCRIPTION_ID); mMobileNetworkRepository.updateEntity(); - // Can not get default subId from database until get the callback, add register by subId - // later. - mMobileNetworkRepository.addRegisterBySubId(getDefaultSubscriptionId()); mDataSubscriptionChangedReceiver.registerReceiver(); } From 29b2f16edf4a3af2e0dc849dbba4a83ab92e33ae Mon Sep 17 00:00:00 2001 From: tomhsu Date: Mon, 6 May 2024 11:37:46 +0000 Subject: [PATCH 12/14] Show dialog on Wifi, and APM' entries in Settings - When satellite mode is switched on Wifi, and APM entry shall show the warning dialog and avoid user uses these functions. Bug: 337154438 Test: Manual test. Test: atest pass Change-Id: I45cd92a8688e7a619613361ea4a8d58a0984d99f --- .../AirplaneModePreferenceController.java | 63 ++++++++++++++----- .../network/SatelliteWarningDialogActivity.kt | 2 +- .../android/settings/wifi/WifiEnabler.java | 38 ++++++++++- .../settings/wifi/slice/WifiSlice.java | 21 ++++++- .../settings/wifi/WifiEnablerTest.java | 16 +++++ .../AirplaneModePreferenceControllerTest.java | 23 ++++++- 6 files changed, 142 insertions(+), 21 deletions(-) diff --git a/src/com/android/settings/network/AirplaneModePreferenceController.java b/src/com/android/settings/network/AirplaneModePreferenceController.java index b52779b3f3e..b1f6e5052ff 100644 --- a/src/com/android/settings/network/AirplaneModePreferenceController.java +++ b/src/com/android/settings/network/AirplaneModePreferenceController.java @@ -17,6 +17,9 @@ package com.android.settings.network; import static android.provider.SettingsSlicesContract.KEY_AIRPLANE_MODE; +import static com.android.settings.network.SatelliteWarningDialogActivity.EXTRA_TYPE_OF_SATELLITE_WARNING_DIALOG; +import static com.android.settings.network.SatelliteWarningDialogActivity.TYPE_IS_AIRPLANE_MODE; + import android.app.Activity; import android.content.ContentResolver; import android.content.Context; @@ -25,6 +28,7 @@ import android.content.pm.PackageManager; import android.net.Uri; import android.provider.SettingsSlicesContract; import android.telephony.TelephonyManager; +import android.util.Log; import androidx.annotation.VisibleForTesting; import androidx.fragment.app.Fragment; @@ -38,13 +42,20 @@ import com.android.settings.Utils; import com.android.settings.core.TogglePreferenceController; import com.android.settingslib.core.lifecycle.LifecycleObserver; import com.android.settingslib.core.lifecycle.events.OnDestroy; +import com.android.settingslib.core.lifecycle.events.OnResume; import com.android.settingslib.core.lifecycle.events.OnStart; import com.android.settingslib.core.lifecycle.events.OnStop; -public class AirplaneModePreferenceController extends TogglePreferenceController - implements LifecycleObserver, OnStart, OnStop, OnDestroy, - AirplaneModeEnabler.OnAirplaneModeChangedListener { +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.AtomicBoolean; +public class AirplaneModePreferenceController extends TogglePreferenceController + implements LifecycleObserver, OnStart, OnResume, OnStop, OnDestroy, + AirplaneModeEnabler.OnAirplaneModeChangedListener { + private static final String TAG = AirplaneModePreferenceController.class.getSimpleName(); public static final int REQUEST_CODE_EXIT_ECM = 1; /** @@ -60,12 +71,15 @@ public class AirplaneModePreferenceController extends TogglePreferenceController private Fragment mFragment; private AirplaneModeEnabler mAirplaneModeEnabler; private TwoStatePreference mAirplaneModePreference; + private SatelliteRepository mSatelliteRepository; + @VisibleForTesting + AtomicBoolean mIsSatelliteOn = new AtomicBoolean(false); public AirplaneModePreferenceController(Context context, String key) { super(context, key); - if (isAvailable(mContext)) { mAirplaneModeEnabler = new AirplaneModeEnabler(mContext, this); + mSatelliteRepository = new SatelliteRepository(mContext); } } @@ -80,18 +94,28 @@ public class AirplaneModePreferenceController extends TogglePreferenceController @Override public boolean handlePreferenceTreeClick(Preference preference) { - if (KEY_AIRPLANE_MODE.equals(preference.getKey()) && isAvailable() - && mAirplaneModeEnabler.isInEcmMode()) { + if (KEY_AIRPLANE_MODE.equals(preference.getKey()) && isAvailable()) { // In ECM mode launch ECM app dialog - if (mFragment != null) { - mFragment.startActivityForResult( - new Intent(TelephonyManager.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS, null) - .setPackage(Utils.PHONE_PACKAGE_NAME), - REQUEST_CODE_EXIT_ECM); + if (mAirplaneModeEnabler.isInEcmMode()) { + if (mFragment != null) { + mFragment.startActivityForResult( + new Intent(TelephonyManager.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS, null) + .setPackage(Utils.PHONE_PACKAGE_NAME), + REQUEST_CODE_EXIT_ECM); + } + return true; } - return true; - } + if (mIsSatelliteOn.get()) { + mContext.startActivity( + new Intent(mContext, SatelliteWarningDialogActivity.class) + .putExtra( + EXTRA_TYPE_OF_SATELLITE_WARNING_DIALOG, + TYPE_IS_AIRPLANE_MODE) + ); + return true; + } + } return false; } @@ -134,6 +158,17 @@ public class AirplaneModePreferenceController extends TogglePreferenceController } } + @Override + public void onResume() { + try { + mIsSatelliteOn.set( + mSatelliteRepository.requestIsEnabled(Executors.newSingleThreadExecutor()) + .get(2000, TimeUnit.MILLISECONDS)); + } catch (ExecutionException | TimeoutException | InterruptedException e) { + Log.e(TAG, "Error to get satellite status : " + e); + } + } + @Override public void onStop() { if (isAvailable()) { @@ -165,7 +200,7 @@ public class AirplaneModePreferenceController extends TogglePreferenceController @Override public boolean setChecked(boolean isChecked) { - if (isChecked() == isChecked) { + if (isChecked() == isChecked || mIsSatelliteOn.get()) { return false; } if (isAvailable()) { diff --git a/src/com/android/settings/network/SatelliteWarningDialogActivity.kt b/src/com/android/settings/network/SatelliteWarningDialogActivity.kt index a0d494cdef6..0702e4fbc66 100644 --- a/src/com/android/settings/network/SatelliteWarningDialogActivity.kt +++ b/src/com/android/settings/network/SatelliteWarningDialogActivity.kt @@ -41,7 +41,7 @@ class SatelliteWarningDialogActivity : SpaDialogWindowTypeActivity() { } override fun getDialogWindowType(): Int { - return WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW + return WindowManager.LayoutParams.LAST_APPLICATION_WINDOW } @Composable diff --git a/src/com/android/settings/wifi/WifiEnabler.java b/src/com/android/settings/wifi/WifiEnabler.java index 794587de626..d1cf7d679cd 100644 --- a/src/com/android/settings/wifi/WifiEnabler.java +++ b/src/com/android/settings/wifi/WifiEnabler.java @@ -16,6 +16,9 @@ package com.android.settings.wifi; +import static com.android.settings.network.SatelliteWarningDialogActivity.EXTRA_TYPE_OF_SATELLITE_WARNING_DIALOG; +import static com.android.settings.network.SatelliteWarningDialogActivity.TYPE_IS_WIFI; + import android.app.settings.SettingsEnums; import android.content.BroadcastReceiver; import android.content.Context; @@ -27,19 +30,26 @@ import android.net.wifi.SupplicantState; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.provider.Settings; +import android.util.Log; import android.widget.Toast; import androidx.annotation.VisibleForTesting; import com.android.settings.R; +import com.android.settings.network.SatelliteRepository; +import com.android.settings.network.SatelliteWarningDialogActivity; import com.android.settings.widget.SwitchWidgetController; import com.android.settingslib.WirelessUtils; import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicBoolean; public class WifiEnabler implements SwitchWidgetController.OnSwitchChangeListener { - + private static final String TAG = WifiEnabler.class.getSimpleName(); private final SwitchWidgetController mSwitchWidget; private final WifiManager mWifiManager; private final ConnectivityManager mConnectivityManager; @@ -48,7 +58,9 @@ public class WifiEnabler implements SwitchWidgetController.OnSwitchChangeListene private Context mContext; private boolean mListeningToOnSwitchChange = false; private AtomicBoolean mConnected = new AtomicBoolean(false); - + private SatelliteRepository mSatelliteRepository; + @VisibleForTesting + AtomicBoolean mIsSatelliteOn = new AtomicBoolean(false); private boolean mStateMachineEvent; private final IntentFilter mIntentFilter; @@ -93,7 +105,7 @@ public class WifiEnabler implements SwitchWidgetController.OnSwitchChangeListene // The order matters! We really should not depend on this. :( mIntentFilter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION); mIntentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION); - + mSatelliteRepository = new SatelliteRepository(context); setupSwitchController(); } @@ -124,6 +136,14 @@ public class WifiEnabler implements SwitchWidgetController.OnSwitchChangeListene mSwitchWidget.startListening(); mListeningToOnSwitchChange = true; } + // Refresh satellite mode status. + try { + mIsSatelliteOn.set( + mSatelliteRepository.requestIsEnabled(Executors.newSingleThreadExecutor()) + .get(2000, TimeUnit.MILLISECONDS)); + } catch (ExecutionException | TimeoutException | InterruptedException e) { + Log.e(TAG, "Error to get satellite status : " + e); + } } public void pause() { @@ -185,6 +205,18 @@ public class WifiEnabler implements SwitchWidgetController.OnSwitchChangeListene if (mStateMachineEvent) { return true; } + + // Show dialog and do nothing under satellite mode. + if (mIsSatelliteOn.get()) { + mContext.startActivity( + new Intent(mContext, SatelliteWarningDialogActivity.class) + .putExtra( + EXTRA_TYPE_OF_SATELLITE_WARNING_DIALOG, + TYPE_IS_WIFI) + ); + return false; + } + // Show toast message if Wi-Fi is not allowed in airplane mode if (isChecked && !WirelessUtils.isRadioAllowed(mContext, Settings.Global.RADIO_WIFI)) { Toast.makeText(mContext, R.string.wifi_in_airplane_mode, Toast.LENGTH_SHORT).show(); diff --git a/src/com/android/settings/wifi/slice/WifiSlice.java b/src/com/android/settings/wifi/slice/WifiSlice.java index f75fe11953d..599bf6b6d91 100644 --- a/src/com/android/settings/wifi/slice/WifiSlice.java +++ b/src/com/android/settings/wifi/slice/WifiSlice.java @@ -52,6 +52,7 @@ import com.android.settings.SubSettings; import com.android.settings.Utils; import com.android.settings.core.SubSettingLauncher; import com.android.settings.network.NetworkProviderSettings; +import com.android.settings.network.SatelliteRepository; import com.android.settings.network.WifiSwitchPreferenceController; import com.android.settings.slices.CustomSliceable; import com.android.settings.slices.SliceBackgroundWorker; @@ -66,6 +67,10 @@ import com.android.wifitrackerlib.WifiEntry; import java.util.Arrays; import java.util.List; import java.util.Set; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; import java.util.stream.Collectors; /** @@ -225,7 +230,8 @@ public class WifiSlice implements CustomSliceable { .setAccentColor(COLOR_NOT_TINTED) .setKeywords(getKeywords()) .addRow(getHeaderRow(isWifiEnabled, wifiSliceItem)); - if (!isWiFiPermissionGranted || !mWifiRestriction.isChangeWifiStateAllowed(mContext)) { + if (!isWiFiPermissionGranted || !mWifiRestriction.isChangeWifiStateAllowed(mContext) + || isSatelliteOn()) { return builder; } @@ -416,4 +422,17 @@ public class WifiSlice implements CustomSliceable { return WifiEnterpriseRestrictionUtils.isChangeWifiStateAllowed(context); } } + + private boolean isSatelliteOn() { + SatelliteRepository satelliteRepository = new SatelliteRepository(mContext); + boolean isSatelliteOn = false; + try { + isSatelliteOn = + satelliteRepository.requestIsEnabled(Executors.newSingleThreadExecutor()) + .get(2000, TimeUnit.MILLISECONDS); + } catch (ExecutionException | TimeoutException | InterruptedException e) { + Log.e(TAG, "Error to get satellite status : " + e); + } + return isSatelliteOn; + } } diff --git a/tests/robotests/src/com/android/settings/wifi/WifiEnablerTest.java b/tests/robotests/src/com/android/settings/wifi/WifiEnablerTest.java index 65cc8111e36..6980e8ae1bc 100644 --- a/tests/robotests/src/com/android/settings/wifi/WifiEnablerTest.java +++ b/tests/robotests/src/com/android/settings/wifi/WifiEnablerTest.java @@ -18,12 +18,15 @@ package com.android.settings.wifi; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.content.Context; import android.net.ConnectivityManager; import android.net.wifi.WifiManager; +import android.util.AndroidRuntimeException; import com.android.settings.testutils.shadow.ShadowRestrictedLockUtilsInternal; import com.android.settings.widget.SwitchWidgetController; @@ -65,4 +68,17 @@ public class WifiEnablerTest { assertThat(mEnabler.onSwitchToggled(true)).isTrue(); } + + @Test + public void onSwitchToggled_satelliteOn_startWarningActivity() { + mEnabler.mIsSatelliteOn.set(true); + + try { + mEnabler.onSwitchToggled(true); + } catch (AndroidRuntimeException e) { + // Catch exception of starting activity . + } + + verify(mContext).startActivity(any()); + } } diff --git a/tests/unit/src/com/android/settings/network/AirplaneModePreferenceControllerTest.java b/tests/unit/src/com/android/settings/network/AirplaneModePreferenceControllerTest.java index 1d6a62425cf..7612805370a 100644 --- a/tests/unit/src/com/android/settings/network/AirplaneModePreferenceControllerTest.java +++ b/tests/unit/src/com/android/settings/network/AirplaneModePreferenceControllerTest.java @@ -16,10 +16,14 @@ package com.android.settings.network; +import static android.provider.SettingsSlicesContract.KEY_AIRPLANE_MODE; + import static com.google.common.truth.Truth.assertThat; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.content.ContentResolver; @@ -28,6 +32,7 @@ import android.content.pm.PackageManager; import android.os.Looper; import android.provider.Settings; import android.provider.SettingsSlicesContract; +import android.util.AndroidRuntimeException; import androidx.preference.PreferenceManager; import androidx.preference.PreferenceScreen; @@ -73,12 +78,12 @@ public class AirplaneModePreferenceControllerTest { mResolver = mContext.getContentResolver(); doReturn(mPackageManager).when(mContext).getPackageManager(); mController = new AirplaneModePreferenceController(mContext, - SettingsSlicesContract.KEY_AIRPLANE_MODE); + KEY_AIRPLANE_MODE); mPreferenceManager = new PreferenceManager(mContext); mScreen = mPreferenceManager.createPreferenceScreen(mContext); mPreference = new RestrictedSwitchPreference(mContext); - mPreference.setKey(SettingsSlicesContract.KEY_AIRPLANE_MODE); + mPreference.setKey(KEY_AIRPLANE_MODE); mScreen.addPreference(mPreference); mController.setFragment(null); } @@ -167,4 +172,18 @@ public class AirplaneModePreferenceControllerTest { public void isPublicSlice_returnsTrue() { assertThat(mController.isPublicSlice()).isTrue(); } + + @Test + public void handlePreferenceTreeClick_satelliteOn_startWarningActivity() { + mController.mIsSatelliteOn.set(true); + when(mAirplaneModeEnabler.isInEcmMode()).thenReturn(false); + + try { + mController.handlePreferenceTreeClick(mPreference); + } catch (AndroidRuntimeException e) { + // Catch exception of starting activity . + } + + verify(mContext).startActivity(any()); + } } From c0b39601bf3986eac564ed85916034b26df74d61 Mon Sep 17 00:00:00 2001 From: tomhsu Date: Mon, 6 May 2024 11:37:46 +0000 Subject: [PATCH 13/14] Show dialog on Wifi, and APM' entries in Settings - When satellite mode is switched on Wifi, and APM entry shall show the warning dialog and avoid user uses these functions. Bug: 337154438 Test: Manual test. Test: atest pass Change-Id: I45cd92a8688e7a619613361ea4a8d58a0984d99f (cherry picked from commit 29b2f16edf4a3af2e0dc849dbba4a83ab92e33ae) Merged-In: I45cd92a8688e7a619613361ea4a8d58a0984d99f --- .../AirplaneModePreferenceController.java | 61 +++++++++++++++---- .../network/SatelliteWarningDialogActivity.kt | 2 +- .../android/settings/wifi/WifiEnabler.java | 38 +++++++++++- .../settings/wifi/slice/WifiSlice.java | 21 ++++++- .../settings/wifi/WifiEnablerTest.java | 16 +++++ .../AirplaneModePreferenceControllerTest.java | 23 ++++++- 6 files changed, 141 insertions(+), 20 deletions(-) diff --git a/src/com/android/settings/network/AirplaneModePreferenceController.java b/src/com/android/settings/network/AirplaneModePreferenceController.java index b3fc5177e9d..d73d3fa6d54 100644 --- a/src/com/android/settings/network/AirplaneModePreferenceController.java +++ b/src/com/android/settings/network/AirplaneModePreferenceController.java @@ -17,6 +17,9 @@ package com.android.settings.network; import static android.provider.SettingsSlicesContract.KEY_AIRPLANE_MODE; +import static com.android.settings.network.SatelliteWarningDialogActivity.EXTRA_TYPE_OF_SATELLITE_WARNING_DIALOG; +import static com.android.settings.network.SatelliteWarningDialogActivity.TYPE_IS_AIRPLANE_MODE; + import android.app.Activity; import android.content.ContentResolver; import android.content.Context; @@ -25,6 +28,7 @@ import android.content.pm.PackageManager; import android.net.Uri; import android.provider.SettingsSlicesContract; import android.telephony.TelephonyManager; +import android.util.Log; import androidx.annotation.VisibleForTesting; import androidx.fragment.app.Fragment; @@ -37,13 +41,20 @@ import com.android.settings.R; import com.android.settings.core.TogglePreferenceController; import com.android.settingslib.core.lifecycle.LifecycleObserver; import com.android.settingslib.core.lifecycle.events.OnDestroy; +import com.android.settingslib.core.lifecycle.events.OnResume; import com.android.settingslib.core.lifecycle.events.OnStart; import com.android.settingslib.core.lifecycle.events.OnStop; -public class AirplaneModePreferenceController extends TogglePreferenceController - implements LifecycleObserver, OnStart, OnStop, OnDestroy, - AirplaneModeEnabler.OnAirplaneModeChangedListener { +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.AtomicBoolean; +public class AirplaneModePreferenceController extends TogglePreferenceController + implements LifecycleObserver, OnStart, OnResume, OnStop, OnDestroy, + AirplaneModeEnabler.OnAirplaneModeChangedListener { + private static final String TAG = AirplaneModePreferenceController.class.getSimpleName(); public static final int REQUEST_CODE_EXIT_ECM = 1; /** @@ -59,12 +70,15 @@ public class AirplaneModePreferenceController extends TogglePreferenceController private Fragment mFragment; private AirplaneModeEnabler mAirplaneModeEnabler; private TwoStatePreference mAirplaneModePreference; + private SatelliteRepository mSatelliteRepository; + @VisibleForTesting + AtomicBoolean mIsSatelliteOn = new AtomicBoolean(false); public AirplaneModePreferenceController(Context context, String key) { super(context, key); - if (isAvailable(mContext)) { mAirplaneModeEnabler = new AirplaneModeEnabler(mContext, this); + mSatelliteRepository = new SatelliteRepository(mContext); } } @@ -79,17 +93,27 @@ public class AirplaneModePreferenceController extends TogglePreferenceController @Override public boolean handlePreferenceTreeClick(Preference preference) { - if (KEY_AIRPLANE_MODE.equals(preference.getKey()) && isAvailable() - && mAirplaneModeEnabler.isInEcmMode()) { + if (KEY_AIRPLANE_MODE.equals(preference.getKey()) && isAvailable()) { // In ECM mode launch ECM app dialog - if (mFragment != null) { - mFragment.startActivityForResult( - new Intent(TelephonyManager.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS, null), - REQUEST_CODE_EXIT_ECM); + if (mAirplaneModeEnabler.isInEcmMode()) { + if (mFragment != null) { + mFragment.startActivityForResult( + new Intent(TelephonyManager.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS, null) + REQUEST_CODE_EXIT_ECM); + } + return true; } - return true; - } + if (mIsSatelliteOn.get()) { + mContext.startActivity( + new Intent(mContext, SatelliteWarningDialogActivity.class) + .putExtra( + EXTRA_TYPE_OF_SATELLITE_WARNING_DIALOG, + TYPE_IS_AIRPLANE_MODE) + ); + return true; + } + } return false; } @@ -132,6 +156,17 @@ public class AirplaneModePreferenceController extends TogglePreferenceController } } + @Override + public void onResume() { + try { + mIsSatelliteOn.set( + mSatelliteRepository.requestIsEnabled(Executors.newSingleThreadExecutor()) + .get(2000, TimeUnit.MILLISECONDS)); + } catch (ExecutionException | TimeoutException | InterruptedException e) { + Log.e(TAG, "Error to get satellite status : " + e); + } + } + @Override public void onStop() { if (isAvailable()) { @@ -163,7 +198,7 @@ public class AirplaneModePreferenceController extends TogglePreferenceController @Override public boolean setChecked(boolean isChecked) { - if (isChecked() == isChecked) { + if (isChecked() == isChecked || mIsSatelliteOn.get()) { return false; } if (isAvailable()) { diff --git a/src/com/android/settings/network/SatelliteWarningDialogActivity.kt b/src/com/android/settings/network/SatelliteWarningDialogActivity.kt index a0d494cdef6..0702e4fbc66 100644 --- a/src/com/android/settings/network/SatelliteWarningDialogActivity.kt +++ b/src/com/android/settings/network/SatelliteWarningDialogActivity.kt @@ -41,7 +41,7 @@ class SatelliteWarningDialogActivity : SpaDialogWindowTypeActivity() { } override fun getDialogWindowType(): Int { - return WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW + return WindowManager.LayoutParams.LAST_APPLICATION_WINDOW } @Composable diff --git a/src/com/android/settings/wifi/WifiEnabler.java b/src/com/android/settings/wifi/WifiEnabler.java index 794587de626..d1cf7d679cd 100644 --- a/src/com/android/settings/wifi/WifiEnabler.java +++ b/src/com/android/settings/wifi/WifiEnabler.java @@ -16,6 +16,9 @@ package com.android.settings.wifi; +import static com.android.settings.network.SatelliteWarningDialogActivity.EXTRA_TYPE_OF_SATELLITE_WARNING_DIALOG; +import static com.android.settings.network.SatelliteWarningDialogActivity.TYPE_IS_WIFI; + import android.app.settings.SettingsEnums; import android.content.BroadcastReceiver; import android.content.Context; @@ -27,19 +30,26 @@ import android.net.wifi.SupplicantState; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.provider.Settings; +import android.util.Log; import android.widget.Toast; import androidx.annotation.VisibleForTesting; import com.android.settings.R; +import com.android.settings.network.SatelliteRepository; +import com.android.settings.network.SatelliteWarningDialogActivity; import com.android.settings.widget.SwitchWidgetController; import com.android.settingslib.WirelessUtils; import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicBoolean; public class WifiEnabler implements SwitchWidgetController.OnSwitchChangeListener { - + private static final String TAG = WifiEnabler.class.getSimpleName(); private final SwitchWidgetController mSwitchWidget; private final WifiManager mWifiManager; private final ConnectivityManager mConnectivityManager; @@ -48,7 +58,9 @@ public class WifiEnabler implements SwitchWidgetController.OnSwitchChangeListene private Context mContext; private boolean mListeningToOnSwitchChange = false; private AtomicBoolean mConnected = new AtomicBoolean(false); - + private SatelliteRepository mSatelliteRepository; + @VisibleForTesting + AtomicBoolean mIsSatelliteOn = new AtomicBoolean(false); private boolean mStateMachineEvent; private final IntentFilter mIntentFilter; @@ -93,7 +105,7 @@ public class WifiEnabler implements SwitchWidgetController.OnSwitchChangeListene // The order matters! We really should not depend on this. :( mIntentFilter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION); mIntentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION); - + mSatelliteRepository = new SatelliteRepository(context); setupSwitchController(); } @@ -124,6 +136,14 @@ public class WifiEnabler implements SwitchWidgetController.OnSwitchChangeListene mSwitchWidget.startListening(); mListeningToOnSwitchChange = true; } + // Refresh satellite mode status. + try { + mIsSatelliteOn.set( + mSatelliteRepository.requestIsEnabled(Executors.newSingleThreadExecutor()) + .get(2000, TimeUnit.MILLISECONDS)); + } catch (ExecutionException | TimeoutException | InterruptedException e) { + Log.e(TAG, "Error to get satellite status : " + e); + } } public void pause() { @@ -185,6 +205,18 @@ public class WifiEnabler implements SwitchWidgetController.OnSwitchChangeListene if (mStateMachineEvent) { return true; } + + // Show dialog and do nothing under satellite mode. + if (mIsSatelliteOn.get()) { + mContext.startActivity( + new Intent(mContext, SatelliteWarningDialogActivity.class) + .putExtra( + EXTRA_TYPE_OF_SATELLITE_WARNING_DIALOG, + TYPE_IS_WIFI) + ); + return false; + } + // Show toast message if Wi-Fi is not allowed in airplane mode if (isChecked && !WirelessUtils.isRadioAllowed(mContext, Settings.Global.RADIO_WIFI)) { Toast.makeText(mContext, R.string.wifi_in_airplane_mode, Toast.LENGTH_SHORT).show(); diff --git a/src/com/android/settings/wifi/slice/WifiSlice.java b/src/com/android/settings/wifi/slice/WifiSlice.java index f75fe11953d..599bf6b6d91 100644 --- a/src/com/android/settings/wifi/slice/WifiSlice.java +++ b/src/com/android/settings/wifi/slice/WifiSlice.java @@ -52,6 +52,7 @@ import com.android.settings.SubSettings; import com.android.settings.Utils; import com.android.settings.core.SubSettingLauncher; import com.android.settings.network.NetworkProviderSettings; +import com.android.settings.network.SatelliteRepository; import com.android.settings.network.WifiSwitchPreferenceController; import com.android.settings.slices.CustomSliceable; import com.android.settings.slices.SliceBackgroundWorker; @@ -66,6 +67,10 @@ import com.android.wifitrackerlib.WifiEntry; import java.util.Arrays; import java.util.List; import java.util.Set; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; import java.util.stream.Collectors; /** @@ -225,7 +230,8 @@ public class WifiSlice implements CustomSliceable { .setAccentColor(COLOR_NOT_TINTED) .setKeywords(getKeywords()) .addRow(getHeaderRow(isWifiEnabled, wifiSliceItem)); - if (!isWiFiPermissionGranted || !mWifiRestriction.isChangeWifiStateAllowed(mContext)) { + if (!isWiFiPermissionGranted || !mWifiRestriction.isChangeWifiStateAllowed(mContext) + || isSatelliteOn()) { return builder; } @@ -416,4 +422,17 @@ public class WifiSlice implements CustomSliceable { return WifiEnterpriseRestrictionUtils.isChangeWifiStateAllowed(context); } } + + private boolean isSatelliteOn() { + SatelliteRepository satelliteRepository = new SatelliteRepository(mContext); + boolean isSatelliteOn = false; + try { + isSatelliteOn = + satelliteRepository.requestIsEnabled(Executors.newSingleThreadExecutor()) + .get(2000, TimeUnit.MILLISECONDS); + } catch (ExecutionException | TimeoutException | InterruptedException e) { + Log.e(TAG, "Error to get satellite status : " + e); + } + return isSatelliteOn; + } } diff --git a/tests/robotests/src/com/android/settings/wifi/WifiEnablerTest.java b/tests/robotests/src/com/android/settings/wifi/WifiEnablerTest.java index 65cc8111e36..6980e8ae1bc 100644 --- a/tests/robotests/src/com/android/settings/wifi/WifiEnablerTest.java +++ b/tests/robotests/src/com/android/settings/wifi/WifiEnablerTest.java @@ -18,12 +18,15 @@ package com.android.settings.wifi; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.content.Context; import android.net.ConnectivityManager; import android.net.wifi.WifiManager; +import android.util.AndroidRuntimeException; import com.android.settings.testutils.shadow.ShadowRestrictedLockUtilsInternal; import com.android.settings.widget.SwitchWidgetController; @@ -65,4 +68,17 @@ public class WifiEnablerTest { assertThat(mEnabler.onSwitchToggled(true)).isTrue(); } + + @Test + public void onSwitchToggled_satelliteOn_startWarningActivity() { + mEnabler.mIsSatelliteOn.set(true); + + try { + mEnabler.onSwitchToggled(true); + } catch (AndroidRuntimeException e) { + // Catch exception of starting activity . + } + + verify(mContext).startActivity(any()); + } } diff --git a/tests/unit/src/com/android/settings/network/AirplaneModePreferenceControllerTest.java b/tests/unit/src/com/android/settings/network/AirplaneModePreferenceControllerTest.java index 1d6a62425cf..7612805370a 100644 --- a/tests/unit/src/com/android/settings/network/AirplaneModePreferenceControllerTest.java +++ b/tests/unit/src/com/android/settings/network/AirplaneModePreferenceControllerTest.java @@ -16,10 +16,14 @@ package com.android.settings.network; +import static android.provider.SettingsSlicesContract.KEY_AIRPLANE_MODE; + import static com.google.common.truth.Truth.assertThat; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.content.ContentResolver; @@ -28,6 +32,7 @@ import android.content.pm.PackageManager; import android.os.Looper; import android.provider.Settings; import android.provider.SettingsSlicesContract; +import android.util.AndroidRuntimeException; import androidx.preference.PreferenceManager; import androidx.preference.PreferenceScreen; @@ -73,12 +78,12 @@ public class AirplaneModePreferenceControllerTest { mResolver = mContext.getContentResolver(); doReturn(mPackageManager).when(mContext).getPackageManager(); mController = new AirplaneModePreferenceController(mContext, - SettingsSlicesContract.KEY_AIRPLANE_MODE); + KEY_AIRPLANE_MODE); mPreferenceManager = new PreferenceManager(mContext); mScreen = mPreferenceManager.createPreferenceScreen(mContext); mPreference = new RestrictedSwitchPreference(mContext); - mPreference.setKey(SettingsSlicesContract.KEY_AIRPLANE_MODE); + mPreference.setKey(KEY_AIRPLANE_MODE); mScreen.addPreference(mPreference); mController.setFragment(null); } @@ -167,4 +172,18 @@ public class AirplaneModePreferenceControllerTest { public void isPublicSlice_returnsTrue() { assertThat(mController.isPublicSlice()).isTrue(); } + + @Test + public void handlePreferenceTreeClick_satelliteOn_startWarningActivity() { + mController.mIsSatelliteOn.set(true); + when(mAirplaneModeEnabler.isInEcmMode()).thenReturn(false); + + try { + mController.handlePreferenceTreeClick(mPreference); + } catch (AndroidRuntimeException e) { + // Catch exception of starting activity . + } + + verify(mContext).startActivity(any()); + } } From 864122b8b751988c258f538b534d66a76a6f1365 Mon Sep 17 00:00:00 2001 From: Tom Hsu Date: Wed, 8 May 2024 08:54:58 +0000 Subject: [PATCH 14/14] Fix build break Bug:339348046 Test: Build pass locally Change-Id: I98db39d696617fc81fdad4e73419b34f5265b0ad Merged-In: I45cd92a8688e7a619613361ea4a8d58a0984d99f --- .../settings/network/AirplaneModePreferenceController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/com/android/settings/network/AirplaneModePreferenceController.java b/src/com/android/settings/network/AirplaneModePreferenceController.java index d73d3fa6d54..54602c126bf 100644 --- a/src/com/android/settings/network/AirplaneModePreferenceController.java +++ b/src/com/android/settings/network/AirplaneModePreferenceController.java @@ -98,7 +98,7 @@ public class AirplaneModePreferenceController extends TogglePreferenceController if (mAirplaneModeEnabler.isInEcmMode()) { if (mFragment != null) { mFragment.startActivityForResult( - new Intent(TelephonyManager.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS, null) + new Intent(TelephonyManager.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS, null), REQUEST_CODE_EXIT_ECM); } return true;