Merge "Import translations. DO NOT MERGE ANYWHERE" into main
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 31af599..85dad3c 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -139,7 +139,6 @@
<uses-permission android:name="android.permission.CUSTOMIZE_SYSTEM_UI" />
<uses-permission android:name="android.permission.REMAP_MODIFIER_KEYS" />
<uses-permission android:name="android.permission.ACCESS_GPU_SERVICE" />
- <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<uses-permission android:name="android.permission.MANAGE_GAME_MODE" />
<uses-permission android:name="android.permission.RESTART_PHONE_PROCESS" />
<uses-permission android:name="android.permission.MANAGE_ENHANCED_CONFIRMATION_STATES" />
@@ -3970,6 +3969,9 @@
</intent-filter>
</receiver>
+ <service android:name=".sim.PrimarySubscriptionListChangedService"
+ android:permission="android.permission.BIND_JOB_SERVICE" />
+
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.files"
diff --git a/res/values/integers.xml b/res/values/integers.xml
index 7fb2afd..f62ccae 100644
--- a/res/values/integers.xml
+++ b/res/values/integers.xml
@@ -23,6 +23,7 @@
<integer name="sim_notification_send">104</integer>
<integer name="sim_slot_changed">105</integer>
<integer name="power_monitor_receiver">106</integer>
+ <integer name="primary_subscription_list_changed">107</integer>
<!-- Controls the maximum number of faces enrollable during SUW -->
<integer name="suw_max_faces_enrollable">1</integer>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 2e796a2..8483e6c 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -6283,18 +6283,21 @@
<!-- Cellular security related strings -->
<!-- Title of Cellular security tile in Network & Internet settings page. [CHAR LIMIT=60]-->
- <string name="cellular_security_title">Cellular network security</string>
+ <string name="cellular_security_title">Mobile network security</string>
<!-- Summary of Cellular security tile in Network & Internet settings page. [CHAR LIMIT=NONE]-->
<string name="cellular_security_summary">Network type, encryption, notification controls</string>
+ <!-- Summary of Cellular network security settings page in Network & Internet. [CHAR LIMIT=NONE]-->
+ <string name="cellular_security_top_intro">These settings help protect your calls, messages, and data from outdated or unencrypted networks that could expose you to data theft or surveillance</string>
+
<!-- Title of cellular security settings page [CHAR LIMIT=60]-->
- <string name="cellular_security_settings_title">Cellular network security</string>
+ <string name="cellular_security_settings_title">Mobile network security</string>
<!-- Title of Cellular security notifications section [CHAR LIMIT=60]-->
<string name="cellular_security_notifications">Notifications</string>
<!-- Title of Cellular security notifications toggle [CHAR LIMIT=60]-->
- <string name="cellular_security_notifications_controller_title">Security notifications</string>
+ <string name="cellular_security_notifications_controller_title">Network notifications</string>
<!-- Summary of Cellular security notifications toggle [CHAR LIMIT=NONE]-->
- <string name="cellular_security_notifications_controller_summary">Receive notifications in case the cellular network you are connected to is insecure due to lack of encryption, or if the cellular network records your unique decive or SIM identifiers (IMEI & IMSI)</string>
+ <string name="cellular_security_notifications_controller_summary">Get notified when your device connects to an unencrypted network, or when a network records your unique device or SIM ID</string>
<!--Cellular encryption -->
<!--Cellular encryption title [CHAR LIMIT=60] -->
@@ -12480,9 +12483,9 @@
<string name="enable_2g_summary_disabled_carrier"><xliff:g id="carrier_name_2g" example="Google Fi">%1$s</xliff:g> requires 2G to be available</string>
<!-- Title for toggle if user wants to require cellular encryption [CHAR LIMIT=40] -->
- <string name="require_cellular_encryption_title">Require encryption</string>
+ <string name="require_cellular_encryption_title">Allow only encrypted networks</string>
<!-- Summary for if the user wants to require cellular encryption [CHAR LIMIT=NONE] -->
- <string name="require_cellular_encryption_summary">Encryption is more secure, but you might not be able to connect in some locations. For emergency calls, encryption is never required</string>
+ <string name="require_cellular_encryption_summary">This is more secure but may limit your mobile network connection in some locations. Emergency calling is always allowed.</string>
<!-- Label for All services preference in App info settings [CHAR LIMIT=40] -->
<string name="app_info_all_services_label">All services</string>
diff --git a/res/xml/cellular_security.xml b/res/xml/cellular_security.xml
index e5fee15..8e96bbd 100644
--- a/res/xml/cellular_security.xml
+++ b/res/xml/cellular_security.xml
@@ -18,6 +18,10 @@
xmlns:settings="http://schemas.android.com/apk/res-auto"
android:key="cellular_security_settings_screen"
android:title="@string/cellular_security_settings_title">
+
+ <com.android.settingslib.widget.TopIntroPreference
+ android:key="cellular_security_prefs_top_intro"
+ android:title="@string/cellular_security_top_intro"/>
<PreferenceCategory
android:key="cellular_security_notifications_category"
android:title="@string/cellular_security_notifications"
diff --git a/src/com/android/settings/ResetNetwork.java b/src/com/android/settings/ResetNetwork.java
index 98dbbde..c91ef5c 100644
--- a/src/com/android/settings/ResetNetwork.java
+++ b/src/com/android/settings/ResetNetwork.java
@@ -158,7 +158,7 @@
.setTitleRes(R.string.reset_mobile_network_settings_confirm_title)
.setSourceMetricsCategory(getMetricsCategory());
- if (resetSims && SubscriptionUtil.shouldShowRacDialog(context)) {
+ if (resetSims && SubscriptionUtil.shouldShowRacDialogWhenErasingAllEsims(context)) {
context.startActivity(
EuiccRacConnectivityDialogActivity.getIntent(context, launcher.toIntent()));
} else {
diff --git a/src/com/android/settings/biometrics/face/FaceEnrollEnrolling.java b/src/com/android/settings/biometrics/face/FaceEnrollEnrolling.java
index da3689a..32d2a11 100644
--- a/src/com/android/settings/biometrics/face/FaceEnrollEnrolling.java
+++ b/src/com/android/settings/biometrics/face/FaceEnrollEnrolling.java
@@ -17,10 +17,12 @@
package com.android.settings.biometrics.face;
import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_TIMEOUT;
+import static android.hardware.biometrics.BiometricFaceConstants.FEATURE_REQUIRE_ATTENTION;
+import static android.hardware.biometrics.BiometricFaceConstants.FEATURE_REQUIRE_REQUIRE_DIVERSITY;
import android.app.settings.SettingsEnums;
import android.content.Intent;
-import android.hardware.face.FaceManager;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
@@ -112,10 +114,10 @@
);
if (!getIntent().getBooleanExtra(BiometricEnrollBase.EXTRA_KEY_REQUIRE_DIVERSITY, true)) {
- mDisabledFeatures.add(FaceManager.FEATURE_REQUIRE_REQUIRE_DIVERSITY);
+ mDisabledFeatures.add(FEATURE_REQUIRE_REQUIRE_DIVERSITY);
}
if (!getIntent().getBooleanExtra(BiometricEnrollBase.EXTRA_KEY_REQUIRE_VISION, true)) {
- mDisabledFeatures.add(FaceManager.FEATURE_REQUIRE_ATTENTION);
+ mDisabledFeatures.add(FEATURE_REQUIRE_ATTENTION);
}
startEnrollment();
@@ -190,7 +192,7 @@
public void onEnrollmentError(int errMsgId, CharSequence errString) {
int msgId;
switch (errMsgId) {
- case FaceManager.FACE_ERROR_TIMEOUT:
+ case FACE_ERROR_TIMEOUT:
msgId = R.string.security_settings_face_enroll_error_timeout_dialog_message;
break;
default:
diff --git a/src/com/android/settings/biometrics/face/FaceSettingsAttentionPreferenceController.java b/src/com/android/settings/biometrics/face/FaceSettingsAttentionPreferenceController.java
index b5e9908..1902bc4 100644
--- a/src/com/android/settings/biometrics/face/FaceSettingsAttentionPreferenceController.java
+++ b/src/com/android/settings/biometrics/face/FaceSettingsAttentionPreferenceController.java
@@ -16,6 +16,8 @@
package com.android.settings.biometrics.face;
+import static android.hardware.biometrics.BiometricFaceConstants.FEATURE_REQUIRE_ATTENTION;
+
import android.content.Context;
import android.hardware.face.FaceManager;
import android.hardware.face.FaceManager.GetFeatureCallback;
@@ -42,7 +44,7 @@
private final SetFeatureCallback mSetFeatureCallback = new SetFeatureCallback() {
@Override
public void onCompleted(boolean success, int feature) {
- if (feature == FaceManager.FEATURE_REQUIRE_ATTENTION) {
+ if (feature == FEATURE_REQUIRE_ATTENTION) {
mPreference.setEnabled(true);
if (!success) {
mPreference.setChecked(!mPreference.isChecked());
@@ -60,7 +62,7 @@
public void onCompleted(boolean success, int[] features, boolean[] featureState) {
boolean requireAttentionEnabled = false;
for (int i = 0; i < features.length; i++) {
- if (features[i] == FaceManager.FEATURE_REQUIRE_ATTENTION) {
+ if (features[i] == FEATURE_REQUIRE_ATTENTION) {
requireAttentionEnabled = featureState[i];
}
}
@@ -98,7 +100,7 @@
}
// Set to disabled until we know the true value.
mPreference.setEnabled(false);
- mFaceManager.getFeature(getUserId(), FaceManager.FEATURE_REQUIRE_ATTENTION,
+ mFaceManager.getFeature(getUserId(), FEATURE_REQUIRE_ATTENTION,
mGetFeatureCallback);
// Ideally returns a cached value.
@@ -111,8 +113,8 @@
mPreference.setEnabled(false);
mPreference.setChecked(isChecked);
- mFaceManager.setFeature(getUserId(), FaceManager.FEATURE_REQUIRE_ATTENTION, isChecked,
- mToken, mSetFeatureCallback);
+ mFaceManager.setFeature(getUserId(), FEATURE_REQUIRE_ATTENTION,
+ isChecked, mToken, mSetFeatureCallback);
return true;
}
diff --git a/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java b/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java
index dd30e69..f63b649 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java
@@ -151,4 +151,7 @@
/** Whether the app optimization mode is valid to restore */
boolean isValidToRestoreOptimizationMode(ArrayMap<String, String> deviceInfoMap);
+
+ /** Whether the device is under the battery defender mode */
+ boolean isBatteryDefend(BatteryInfo info);
}
diff --git a/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java b/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java
index 5c66dbc..cc6659a 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java
@@ -235,4 +235,9 @@
public boolean isValidToRestoreOptimizationMode(ArrayMap<String, String> deviceInfoMap) {
return false;
}
+
+ @Override
+ public boolean isBatteryDefend(BatteryInfo info) {
+ return info.isBatteryDefender && !isExtraDefend();
+ }
}
diff --git a/src/com/android/settings/fuelgauge/batterytip/detectors/BatteryDefenderDetector.java b/src/com/android/settings/fuelgauge/batterytip/detectors/BatteryDefenderDetector.java
index db572cd..639b3c7 100644
--- a/src/com/android/settings/fuelgauge/batterytip/detectors/BatteryDefenderDetector.java
+++ b/src/com/android/settings/fuelgauge/batterytip/detectors/BatteryDefenderDetector.java
@@ -36,10 +36,9 @@
@Override
public BatteryTip detect() {
final boolean isBasicBatteryDefend =
- mBatteryInfo.isBatteryDefender
- && !FeatureFactory.getFeatureFactory()
- .getPowerUsageFeatureProvider()
- .isExtraDefend();
+ FeatureFactory.getFeatureFactory()
+ .getPowerUsageFeatureProvider()
+ .isBatteryDefend(mBatteryInfo);
final int state =
isBasicBatteryDefend ? BatteryTip.StateType.NEW : BatteryTip.StateType.INVISIBLE;
final boolean isPluggedIn = mBatteryInfo.pluggedStatus != 0;
diff --git a/src/com/android/settings/homepage/SettingsHomepageActivity.java b/src/com/android/settings/homepage/SettingsHomepageActivity.java
index a2ca9ae..48d918c 100644
--- a/src/com/android/settings/homepage/SettingsHomepageActivity.java
+++ b/src/com/android/settings/homepage/SettingsHomepageActivity.java
@@ -204,7 +204,7 @@
if (mIsEmbeddingActivityEnabled) {
final UserManager um = getSystemService(UserManager.class);
final UserInfo userInfo = um.getUserInfo(getUserId());
- if (!userInfo.isMain()) {
+ if (userInfo.isManagedProfile()) {
final Intent intent = new Intent(getIntent())
.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT)
.putExtra(EXTRA_USER_HANDLE, getUser())
diff --git a/src/com/android/settings/network/EraseEuiccDataController.java b/src/com/android/settings/network/EraseEuiccDataController.java
index 4e89da0..a12d853 100644
--- a/src/com/android/settings/network/EraseEuiccDataController.java
+++ b/src/com/android/settings/network/EraseEuiccDataController.java
@@ -50,7 +50,7 @@
if (!TextUtils.equals(preference.getKey(), getPreferenceKey())) {
return false;
}
- if (SubscriptionUtil.shouldShowRacDialog(mContext)) {
+ if (SubscriptionUtil.shouldShowRacDialogWhenErasingAllEsims(mContext)) {
EuiccRacConnectivityDialogFragment.show(mHostFragment);
} else {
EraseEuiccDataDialogFragment.show(mHostFragment);
diff --git a/src/com/android/settings/network/EraseEuiccDataDialogFragment.java b/src/com/android/settings/network/EraseEuiccDataDialogFragment.java
index 01ced4e..b8e18b3 100644
--- a/src/com/android/settings/network/EraseEuiccDataDialogFragment.java
+++ b/src/com/android/settings/network/EraseEuiccDataDialogFragment.java
@@ -33,7 +33,7 @@
import com.android.settings.R;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
import com.android.settings.system.ResetDashboardFragment;
-import com.android.settings.wifi.dpp.WifiDppUtils;
+import com.android.settings.network.telephony.MobileNetworkUtils;
public class EraseEuiccDataDialogFragment extends InstrumentedDialogFragment implements
DialogInterface.OnClickListener {
@@ -78,7 +78,7 @@
if (which == DialogInterface.BUTTON_POSITIVE) {
Context context = getContext();
- WifiDppUtils.showLockScreen(context, () -> runAsyncWipe(context));
+ MobileNetworkUtils.showLockScreen(context, () -> runAsyncWipe(context));
}
}
diff --git a/src/com/android/settings/network/SatelliteRepository.kt b/src/com/android/settings/network/SatelliteRepository.kt
index cca502a..565fbf3 100644
--- a/src/com/android/settings/network/SatelliteRepository.kt
+++ b/src/com/android/settings/network/SatelliteRepository.kt
@@ -33,6 +33,7 @@
import kotlinx.coroutines.flow.callbackFlow
import kotlinx.coroutines.flow.flowOf
import java.util.concurrent.Executor
+import kotlinx.coroutines.flow.flowOn
/**
* A repository class for interacting with the SatelliteManager API.
@@ -82,6 +83,8 @@
* `false` otherwise.
*/
fun requestIsSessionStarted(executor: Executor): ListenableFuture<Boolean> {
+ isSessionStarted?.let { return immediateFuture(it) }
+
val satelliteManager: SatelliteManager? =
context.getSystemService(SatelliteManager::class.java)
if (satelliteManager == null) {
@@ -110,13 +113,13 @@
}
/**
- * Provides a Flow that emits the enabled state of the satellite modem. Updates are triggered
+ * Provides a Flow that emits the session state of the satellite modem. Updates are triggered
* when the modem state changes.
*
* @param defaultDispatcher The CoroutineDispatcher to use (Defaults to `Dispatchers.Default`).
- * @return A Flow emitting `true` when the modem is enabled and `false` otherwise.
+ * @return A Flow emitting `true` when the session is started and `false` otherwise.
*/
- fun getIsModemEnabledFlow(
+ fun getIsSessionStartedFlow(
defaultDispatcher: CoroutineDispatcher = Dispatchers.Default,
): Flow<Boolean> {
val satelliteManager: SatelliteManager? =
@@ -128,46 +131,27 @@
return callbackFlow {
val callback = SatelliteModemStateCallback { state ->
- val isEnabled = convertSatelliteModemStateToEnabledState(state)
- Log.i(TAG, "Satellite modem state changed: state=$state, isEnabled=$isEnabled")
- trySend(isEnabled)
+ val isSessionStarted = isSatelliteSessionStarted(state)
+ Log.i(TAG, "Satellite modem state changed: state=$state"
+ + ", isSessionStarted=$isSessionStarted")
+ trySend(isSessionStarted)
}
- val result = satelliteManager.registerForModemStateChanged(
+ val registerResult = satelliteManager.registerForModemStateChanged(
defaultDispatcher.asExecutor(),
callback
)
- Log.i(TAG, "Call registerForModemStateChanged: result=$result")
+
+ if (registerResult != SatelliteManager.SATELLITE_RESULT_SUCCESS) {
+ // If the registration failed (e.g., device doesn't support satellite),
+ // SatelliteManager will not emit the current state by callback.
+ // We send `false` value by ourself to make sure the flow has initial value.
+ Log.w(TAG, "Failed to register for satellite modem state change: $registerResult")
+ trySend(false)
+ }
awaitClose { satelliteManager.unregisterForModemStateChanged(callback) }
- }
- }
-
- /**
- * Converts a [SatelliteManager.SatelliteModemState] to a boolean representing whether the modem
- * is enabled.
- *
- * @param state The SatelliteModemState provided by the SatelliteManager.
- * @return `true` if the modem is enabled, `false` otherwise.
- */
- @VisibleForTesting
- fun convertSatelliteModemStateToEnabledState(
- @SatelliteManager.SatelliteModemState state: Int,
- ): Boolean {
- // Mapping table based on logic from b/315928920#comment24
- return when (state) {
- SatelliteManager.SATELLITE_MODEM_STATE_IDLE,
- SatelliteManager.SATELLITE_MODEM_STATE_LISTENING,
- SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING,
- SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_RETRYING,
- SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED,
- SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED -> true
- else -> false
- }
- }
-
- companion object {
- private const val TAG: String = "SatelliteRepository"
+ }.flowOn(Dispatchers.Default)
}
/**
@@ -184,4 +168,15 @@
else -> true
}
}
+
+ companion object {
+ private const val TAG: String = "SatelliteRepository"
+
+ private var isSessionStarted: Boolean? = null
+
+ @VisibleForTesting
+ fun setIsSessionStartedForTesting(isEnabled: Boolean) {
+ this.isSessionStarted = isEnabled
+ }
+ }
}
diff --git a/src/com/android/settings/network/SubscriptionUtil.java b/src/com/android/settings/network/SubscriptionUtil.java
index 682d154..6b2a8d3 100644
--- a/src/com/android/settings/network/SubscriptionUtil.java
+++ b/src/com/android/settings/network/SubscriptionUtil.java
@@ -543,9 +543,7 @@
return;
}
- if (isCarrierRac(context, carrierId)
- && (!isConnectedToWifi(context)
- || isConnectedToMobileDataWithDifferentSubId(context, subId))) {
+ if (shouldShowRacDialogWhenErasingEsim(context, subId, carrierId)) {
context.startActivity(EuiccRacConnectivityDialogActivity.getIntent(context, subId));
} else {
context.startActivity(DeleteEuiccSubscriptionDialogActivity.getIntent(context, subId));
@@ -884,19 +882,36 @@
}
/**
- * Check if warning dialog should be presented when erasing all eSIMS.
+ * Check if warning dialog should be presented when erasing all eSIMs.
*
* @param context Context to check if any sim carrier use RAC and device Wi-Fi connection.
* @return {@code true} if dialog should be presented to the user.
*/
- public static boolean shouldShowRacDialog(@NonNull Context context) {
+ public static boolean shouldShowRacDialogWhenErasingAllEsims(@NonNull Context context) {
if (sEnableRacDialogForTesting != null) {
return sEnableRacDialogForTesting;
}
+
return !isConnectedToWifi(context) && hasSubscriptionWithRacCarrier(context);
}
/**
+ * Check if warning dialog should be presented when erasing eSIM.
+ *
+ * @param context Context to check if any sim carrier use RAC and device Wi-Fi connection.
+ * @param subId Subscription ID for the single eSIM.
+ * @param carrierId Carrier ID for the single eSIM.
+ * @return {@code true} if dialog should be presented to the user.
+ */
+ @VisibleForTesting
+ static boolean shouldShowRacDialogWhenErasingEsim(
+ @NonNull Context context, int subId, int carrierId) {
+ return isCarrierRac(context, carrierId)
+ && !isConnectedToWifi(context)
+ && !isConnectedToMobileDataWithDifferentSubId(context, subId);
+ }
+
+ /**
* Retrieves NetworkCapabilities for the active network.
*
* @param context context
diff --git a/src/com/android/settings/network/telephony/MobileNetworkSwitchController.kt b/src/com/android/settings/network/telephony/MobileNetworkSwitchController.kt
index 41cef50..447909e 100644
--- a/src/com/android/settings/network/telephony/MobileNetworkSwitchController.kt
+++ b/src/com/android/settings/network/telephony/MobileNetworkSwitchController.kt
@@ -59,7 +59,7 @@
val changeable by remember {
combine(
context.callStateFlow(subId).map { it == TelephonyManager.CALL_STATE_IDLE },
- satelliteRepository.getIsModemEnabledFlow()
+ satelliteRepository.getIsSessionStartedFlow()
) { isCallStateIdle, isSatelliteModemEnabled ->
isCallStateIdle && !isSatelliteModemEnabled
}
diff --git a/src/com/android/settings/privatespace/PrivateSpaceSetLockFragment.java b/src/com/android/settings/privatespace/PrivateSpaceSetLockFragment.java
index 830b45e..28ac97f 100644
--- a/src/com/android/settings/privatespace/PrivateSpaceSetLockFragment.java
+++ b/src/com/android/settings/privatespace/PrivateSpaceSetLockFragment.java
@@ -16,6 +16,8 @@
package com.android.settings.privatespace;
+import static android.text.Layout.BREAK_STRATEGY_SIMPLE;
+
import static com.android.settings.privatespace.PrivateSpaceSetupActivity.EXTRA_ACTION_TYPE;
import static com.android.settings.privatespace.PrivateSpaceSetupActivity.SET_LOCK_ACTION;
@@ -47,6 +49,7 @@
*/
public class PrivateSpaceSetLockFragment extends InstrumentedFragment {
private static final String TAG = "PrivateSpaceSetLockFrag";
+ private static final int HEADER_TEXT_MAX_LINES = 4;
@Override
public View onCreateView(
@@ -60,6 +63,8 @@
GlifLayout rootView =
(GlifLayout)
inflater.inflate(R.layout.private_space_setlock_screen, container, false);
+ rootView.getHeaderTextView().setBreakStrategy(BREAK_STRATEGY_SIMPLE);
+ rootView.getHeaderTextView().setMaxLines(HEADER_TEXT_MAX_LINES);
final FooterBarMixin mixin = rootView.getMixin(FooterBarMixin.class);
mixin.setPrimaryButton(
new FooterButton.Builder(getContext())
diff --git a/src/com/android/settings/sim/PrimarySubscriptionListChangedService.kt b/src/com/android/settings/sim/PrimarySubscriptionListChangedService.kt
new file mode 100644
index 0000000..51a910f
--- /dev/null
+++ b/src/com/android/settings/sim/PrimarySubscriptionListChangedService.kt
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.sim
+
+import android.app.job.JobInfo
+import android.app.job.JobParameters
+import android.app.job.JobScheduler
+import android.app.job.JobService
+import android.content.ComponentName
+import android.content.Context
+import android.content.Intent
+import android.util.Log
+import com.android.settings.R
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.SupervisorJob
+import kotlinx.coroutines.launch
+
+/** A JobService work on primary subscription list changed. */
+class PrimarySubscriptionListChangedService : JobService() {
+ private var job: Job? = null
+
+ override fun onStartJob(params: JobParameters): Boolean {
+ job = CoroutineScope(Dispatchers.Default + SupervisorJob()).launch {
+ try {
+ val intent = Intent()
+ intent.putExtras(params.transientExtras)
+ SimSelectNotification.onPrimarySubscriptionListChanged(
+ this@PrimarySubscriptionListChangedService,
+ intent
+ )
+ } catch (exception: Throwable) {
+ Log.e(TAG, "Exception running job", exception)
+ }
+ jobFinished(params, false)
+ }
+ return true
+ }
+
+ override fun onStopJob(params: JobParameters): Boolean {
+ job?.cancel()
+ return false
+ }
+
+ companion object {
+ private const val TAG = "PrimarySubscriptionListChangedService"
+
+ /**
+ * Schedules a service to work on primary subscription changed.
+ *
+ * @param context is the caller context.
+ */
+ @JvmStatic
+ fun scheduleJob(context: Context, intent: Intent) {
+ val component =
+ ComponentName(context, PrimarySubscriptionListChangedService::class.java)
+ val jobScheduler = context.getSystemService(JobScheduler::class.java)!!
+
+ val jobInfoBuilder =
+ JobInfo.Builder(R.integer.primary_subscription_list_changed, component)
+ intent.extras?.let {
+ jobInfoBuilder.setTransientExtras(it)
+ }
+ jobScheduler.schedule(jobInfoBuilder.build())
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/com/android/settings/sim/SimSelectNotification.java b/src/com/android/settings/sim/SimSelectNotification.java
index 2a05105..3d9d41c 100644
--- a/src/com/android/settings/sim/SimSelectNotification.java
+++ b/src/com/android/settings/sim/SimSelectNotification.java
@@ -48,13 +48,28 @@
import android.telephony.TelephonyManager;
import android.util.Log;
+import androidx.annotation.NonNull;
+import androidx.annotation.WorkerThread;
+
import com.android.internal.annotations.VisibleForTesting;
import com.android.settings.HelpTrampoline;
import com.android.settings.R;
+import com.android.settings.network.SatelliteRepository;
import com.android.settings.network.SubscriptionUtil;
+import com.google.common.util.concurrent.ListenableFuture;
+
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
public class SimSelectNotification extends BroadcastReceiver {
private static final String TAG = "SimSelectNotification";
+
+ private static final int DEFAULT_TIMEOUT_MS = 1000;
+
@VisibleForTesting
public static final int SIM_SELECT_NOTIFICATION_ID = 1;
@VisibleForTesting
@@ -89,7 +104,7 @@
switch (action) {
case TelephonyManager.ACTION_PRIMARY_SUBSCRIPTION_LIST_CHANGED:
- onPrimarySubscriptionListChanged(context, intent);
+ PrimarySubscriptionListChangedService.scheduleJob(context, intent);
break;
case Settings.ACTION_ENABLE_MMS_DATA_REQUEST:
onEnableMmsDataRequest(context, intent);
@@ -149,12 +164,41 @@
createEnableMmsNotification(context, notificationTitle, notificationSummary, subId);
}
- private void onPrimarySubscriptionListChanged(Context context, Intent intent) {
- startSimSelectDialogIfNeeded(context, intent);
- sendSimCombinationWarningIfNeeded(context, intent);
+ /**
+ * Handles changes to the primary subscription list, performing actions only
+ * if the device is not currently in a satellite session. This method is
+ * intended to be executed on a worker thread.
+ *
+ * @param context The application context
+ * @param intent The intent signaling a primary subscription change
+ */
+ @WorkerThread
+ public static void onPrimarySubscriptionListChanged(@NonNull Context context,
+ @NonNull Intent intent) {
+ Log.d(TAG, "Checking satellite enabled status");
+ Executor executor = Executors.newSingleThreadExecutor();
+ ListenableFuture<Boolean> isSatelliteSessionStartedFuture =
+ new SatelliteRepository(context).requestIsSessionStarted(executor);
+ boolean isSatelliteSessionStarted = false;
+ try {
+ isSatelliteSessionStarted =
+ isSatelliteSessionStartedFuture.get(DEFAULT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
+ } catch (InterruptedException | ExecutionException | TimeoutException e) {
+ Log.w(TAG, "Can't get satellite session status", e);
+ } finally {
+ if (isSatelliteSessionStarted) {
+ Log.i(TAG, "Device is in a satellite session.g Unable to handle primary"
+ + " subscription list changes");
+ } else {
+ Log.i(TAG, "Device is not in a satellite session. Handle primary"
+ + " subscription list changes");
+ startSimSelectDialogIfNeeded(context, intent);
+ sendSimCombinationWarningIfNeeded(context, intent);
+ }
+ }
}
- private void startSimSelectDialogIfNeeded(Context context, Intent intent) {
+ private static void startSimSelectDialogIfNeeded(Context context, Intent intent) {
int dialogType = intent.getIntExtra(EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE,
EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_NONE);
@@ -194,7 +238,7 @@
}
}
- private void sendSimCombinationWarningIfNeeded(Context context, Intent intent) {
+ private static void sendSimCombinationWarningIfNeeded(Context context, Intent intent) {
final int warningType = intent.getIntExtra(EXTRA_SIM_COMBINATION_WARNING_TYPE,
EXTRA_SIM_COMBINATION_WARNING_TYPE_NONE);
@@ -207,7 +251,7 @@
}
}
- private void createSimSelectNotification(Context context){
+ private static void createSimSelectNotification(Context context) {
final Resources resources = context.getResources();
NotificationChannel notificationChannel = new NotificationChannel(
@@ -217,11 +261,11 @@
Notification.Builder builder =
new Notification.Builder(context, SIM_SELECT_NOTIFICATION_CHANNEL)
- .setSmallIcon(R.drawable.ic_sim_alert)
- .setColor(context.getColor(R.color.sim_noitification))
- .setContentTitle(resources.getText(R.string.sim_notification_title))
- .setContentText(resources.getText(R.string.sim_notification_summary))
- .setAutoCancel(true);
+ .setSmallIcon(R.drawable.ic_sim_alert)
+ .setColor(context.getColor(R.color.sim_noitification))
+ .setContentTitle(resources.getText(R.string.sim_notification_title))
+ .setContentText(resources.getText(R.string.sim_notification_summary))
+ .setAutoCancel(true);
Intent resultIntent = new Intent(Settings.ACTION_WIRELESS_SETTINGS);
resultIntent.setPackage(SETTINGS_PACKAGE_NAME);
resultIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
@@ -279,7 +323,7 @@
notificationManager.cancel(ENABLE_MMS_NOTIFICATION_ID);
}
- private void createSimCombinationWarningNotification(Context context, Intent intent){
+ private static void createSimCombinationWarningNotification(Context context, Intent intent) {
final Resources resources = context.getResources();
final String simNames = intent.getStringExtra(EXTRA_SIM_COMBINATION_NAMES);
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImplTest.java b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImplTest.java
index 3158688..354afd0 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImplTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImplTest.java
@@ -18,6 +18,8 @@
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.when;
import android.content.Context;
@@ -48,6 +50,8 @@
private Context mContext;
@Mock private PackageManager mPackageManager;
+ @Mock private BatteryInfo mBatteryInfo;
+
private PowerUsageFeatureProviderImpl mPowerFeatureProvider;
@Before
@@ -55,73 +59,74 @@
MockitoAnnotations.initMocks(this);
when(mContext.getApplicationContext()).thenReturn(mContext);
- mPowerFeatureProvider = new PowerUsageFeatureProviderImpl(mContext);
+ mPowerFeatureProvider = spy(new PowerUsageFeatureProviderImpl(mContext));
when(mPackageManager.getPackagesForUid(UID_CALENDAR)).thenReturn(PACKAGES_CALENDAR);
when(mPackageManager.getPackagesForUid(UID_MEDIA)).thenReturn(PACKAGES_MEDIA);
when(mPackageManager.getPackagesForUid(UID_SYSTEMUI)).thenReturn(PACKAGES_SYSTEMUI);
mPowerFeatureProvider.mPackageManager = mPackageManager;
+ mBatteryInfo.discharging = false;
}
@Test
- public void testIsBatteryUsageEnabled_returnFalse() {
+ public void isBatteryUsageEnabled_returnFalse() {
assertThat(mPowerFeatureProvider.isBatteryUsageEnabled()).isTrue();
}
@Test
- public void testIsBatteryTipsEnabled_returnFalse() {
+ public void isBatteryTipsEnabled_returnFalse() {
assertThat(mPowerFeatureProvider.isBatteryTipsEnabled()).isFalse();
}
@Test
- public void testIsAppOptimizationModeLogged_returnFalse() {
+ public void isAppOptimizationModeLogged_returnFalse() {
assertThat(mPowerFeatureProvider.isAppOptimizationModeLogged()).isFalse();
}
@Test
- public void testGetBatteryUsageListConsumePowerThreshold_return0() {
+ public void getBatteryUsageListConsumePowerThreshold_return0() {
assertThat(mPowerFeatureProvider.getBatteryUsageListConsumePowerThreshold()).isEqualTo(0.0);
}
@Test
- public void testIsTypeSystem_uidRoot_returnTrue() {
+ public void isTypeSystem_uidRoot_returnTrue() {
assertThat(mPowerFeatureProvider.isTypeSystem(Process.ROOT_UID, null)).isTrue();
}
@Test
- public void testIsTypeSystem_uidSystem_returnTrue() {
+ public void isTypeSystem_uidSystem_returnTrue() {
assertThat(mPowerFeatureProvider.isTypeSystem(Process.SYSTEM_UID, null)).isTrue();
}
@Test
- public void testIsTypeSystem_uidMedia_returnTrue() {
+ public void isTypeSystem_uidMedia_returnTrue() {
assertThat(mPowerFeatureProvider.isTypeSystem(Process.MEDIA_UID, null)).isTrue();
}
@Test
@Ignore
- public void testIsTypeSystem_appCalendar_returnTrue() {
+ public void isTypeSystem_appCalendar_returnTrue() {
assertThat(mPowerFeatureProvider.isTypeSystem(UID_CALENDAR, null)).isTrue();
}
@Test
@Ignore
- public void testIsTypeSystem_appMedia_returnTrue() {
+ public void isTypeSystem_appMedia_returnTrue() {
assertThat(mPowerFeatureProvider.isTypeSystem(UID_MEDIA, null)).isTrue();
}
@Test
@Ignore
- public void testIsTypeSystem_appSystemUi_returnTrue() {
+ public void isTypeSystem_appSystemUi_returnTrue() {
assertThat(mPowerFeatureProvider.isTypeSystem(UID_SYSTEMUI, null)).isTrue();
}
@Test
- public void testIsTypeSystem_uidOther_returnFalse() {
+ public void isTypeSystem_uidOther_returnFalse() {
assertThat(mPowerFeatureProvider.isTypeSystem(UID_OTHER, null)).isFalse();
}
@Test
- public void testIsSmartBatterySupported_smartBatterySupported_returnTrue() {
+ public void isSmartBatterySupported_smartBatterySupported_returnTrue() {
when(mContext.getResources()
.getBoolean(com.android.internal.R.bool.config_smart_battery_available))
.thenReturn(true);
@@ -130,7 +135,7 @@
}
@Test
- public void testIsSmartBatterySupported_smartBatteryNotSupported_returnFalse() {
+ public void isSmartBatterySupported_smartBatteryNotSupported_returnFalse() {
when(mContext.getResources()
.getBoolean(com.android.internal.R.bool.config_smart_battery_available))
.thenReturn(false);
@@ -139,17 +144,49 @@
}
@Test
- public void testIsAdaptiveChargingSupported_returnFalse() {
+ public void isAdaptiveChargingSupported_returnFalse() {
assertThat(mPowerFeatureProvider.isAdaptiveChargingSupported()).isFalse();
}
@Test
- public void testGetResumeChargeIntentWithoutDockDefender_returnNull() {
+ public void getResumeChargeIntentWithoutDockDefender_returnNull() {
assertThat(mPowerFeatureProvider.getResumeChargeIntent(false)).isNull();
}
@Test
- public void testGetResumeChargeIntentWithDockDefender_returnNull() {
+ public void getResumeChargeIntentWithDockDefender_returnNull() {
assertThat(mPowerFeatureProvider.getResumeChargeIntent(true)).isNull();
}
+
+ @Test
+ public void isBatteryDefend_defenderModeAndExtraDefendAreFalse_returnFalse() {
+ mBatteryInfo.isBatteryDefender = false;
+ doReturn(false).when(mPowerFeatureProvider).isExtraDefend();
+
+ assertThat(mPowerFeatureProvider.isBatteryDefend(mBatteryInfo)).isFalse();
+ }
+
+ @Test
+ public void isBatteryDefend_defenderModeIsFalse_returnFalse() {
+ mBatteryInfo.isBatteryDefender = false;
+ doReturn(true).when(mPowerFeatureProvider).isExtraDefend();
+
+ assertThat(mPowerFeatureProvider.isBatteryDefend(mBatteryInfo)).isFalse();
+ }
+
+ @Test
+ public void isBatteryDefend_defenderModeAndExtraDefendAreTrue_returnFalse() {
+ mBatteryInfo.isBatteryDefender = true;
+ doReturn(true).when(mPowerFeatureProvider).isExtraDefend();
+
+ assertThat(mPowerFeatureProvider.isBatteryDefend(mBatteryInfo)).isFalse();
+ }
+
+ @Test
+ public void isBatteryDefend_extraDefendIsFalse_returnTrue() {
+ mBatteryInfo.isBatteryDefender = true;
+ doReturn(false).when(mPowerFeatureProvider).isExtraDefend();
+
+ assertThat(mPowerFeatureProvider.isBatteryDefend(mBatteryInfo)).isTrue();
+ }
}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/detectors/BatteryDefenderDetectorTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/detectors/BatteryDefenderDetectorTest.java
index 0a63ba2..ab1ceb5 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/detectors/BatteryDefenderDetectorTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/detectors/BatteryDefenderDetectorTest.java
@@ -40,53 +40,32 @@
@Mock private BatteryInfo mBatteryInfo;
private BatteryDefenderDetector mBatteryDefenderDetector;
- private Context mContext;
private FakeFeatureFactory mFakeFeatureFactory;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
-
- mBatteryInfo.discharging = false;
-
- mContext = ApplicationProvider.getApplicationContext();
-
- mBatteryDefenderDetector = new BatteryDefenderDetector(mBatteryInfo, mContext);
-
+ final Context context = ApplicationProvider.getApplicationContext();
+ mBatteryDefenderDetector = new BatteryDefenderDetector(mBatteryInfo, context);
mFakeFeatureFactory = FakeFeatureFactory.setupForTest();
}
@Test
- public void testDetect_notDefenderNotExtraDefend_tipInvisible() {
- mBatteryInfo.isBatteryDefender = false;
- when(mFakeFeatureFactory.powerUsageFeatureProvider.isExtraDefend()).thenReturn(false);
+ public void detect_notBatteryDefend_tipInvisible() {
+ when(mFakeFeatureFactory.powerUsageFeatureProvider.isBatteryDefend(mBatteryInfo))
+ .thenReturn(false);
assertThat(mBatteryDefenderDetector.detect().isVisible()).isFalse();
}
@Test
- public void testDetect_notDefenderIsExtraDefend_tipInvisible() {
- mBatteryInfo.isBatteryDefender = false;
- when(mFakeFeatureFactory.powerUsageFeatureProvider.isExtraDefend()).thenReturn(true);
-
- assertThat(mBatteryDefenderDetector.detect().isVisible()).isFalse();
- }
-
- @Test
- public void testDetect_isDefenderIsExtraDefend_tipInvisible() {
- mBatteryInfo.isBatteryDefender = false;
- when(mFakeFeatureFactory.powerUsageFeatureProvider.isExtraDefend()).thenReturn(true);
-
- assertThat(mBatteryDefenderDetector.detect().isVisible()).isFalse();
- }
-
- @Test
- public void testDetect_isDefenderNotExtraDefend_tipNew() {
- mBatteryInfo.isBatteryDefender = true;
- when(mFakeFeatureFactory.powerUsageFeatureProvider.isExtraDefend()).thenReturn(false);
+ public void detect_isBatteryDefend_tipNew() {
+ when(mFakeFeatureFactory.powerUsageFeatureProvider.isBatteryDefend(mBatteryInfo))
+ .thenReturn(true);
assertThat(mBatteryDefenderDetector.detect().getState())
.isEqualTo(BatteryTip.StateType.NEW);
+ assertThat(mBatteryDefenderDetector.detect().isVisible()).isTrue();
}
}
diff --git a/tests/robotests/src/com/android/settings/network/SatelliteRepositoryTest.kt b/tests/robotests/src/com/android/settings/network/SatelliteRepositoryTest.kt
index 3c947ab..62fd10a 100644
--- a/tests/robotests/src/com/android/settings/network/SatelliteRepositoryTest.kt
+++ b/tests/robotests/src/com/android/settings/network/SatelliteRepositoryTest.kt
@@ -120,7 +120,7 @@
@Test
fun requestIsSessionStarted_registerFailed() = runBlocking {
`when`(mockSatelliteManager.registerForModemStateChanged(any(), any())
- ).thenAnswer { invocation ->
+ ).thenAnswer {
SatelliteManager.SATELLITE_RESULT_ERROR
}
@@ -187,7 +187,7 @@
}
@Test
- fun getIsModemEnabledFlow_isSatelliteEnabledState() = runBlocking {
+ fun getIsSessionStartedFlow_isSatelliteEnabledState() = runBlocking {
`when`(
mockSatelliteManager.registerForModemStateChanged(
any(),
@@ -199,13 +199,13 @@
SatelliteManager.SATELLITE_RESULT_SUCCESS
}
- val flow = repository.getIsModemEnabledFlow()
+ val flow = repository.getIsSessionStartedFlow()
assertThat(flow.first()).isTrue()
}
@Test
- fun getIsModemEnabledFlow_isSatelliteDisabledState() = runBlocking {
+ fun getIsSessionStartedFlow_isSatelliteDisabledState() = runBlocking {
`when`(
mockSatelliteManager.registerForModemStateChanged(
any(),
@@ -217,16 +217,28 @@
SatelliteManager.SATELLITE_RESULT_SUCCESS
}
- val flow = repository.getIsModemEnabledFlow()
+ val flow = repository.getIsSessionStartedFlow()
assertThat(flow.first()).isFalse()
}
@Test
- fun getIsModemEnabledFlow_nullSatelliteManager() = runBlocking {
+ fun getIsSessionStartedFlow_nullSatelliteManager() = runBlocking {
`when`(spyContext.getSystemService(SatelliteManager::class.java)).thenReturn(null)
- val flow = repository.getIsModemEnabledFlow()
+ val flow = repository.getIsSessionStartedFlow()
+ assertThat(flow.first()).isFalse()
+ }
+
+ @Test
+ fun getIsSessionStartedFlow_registerFailed() = runBlocking {
+ `when`(mockSatelliteManager.registerForModemStateChanged(any(), any())
+ ).thenAnswer {
+ SatelliteManager.SATELLITE_RESULT_ERROR
+ }
+
+ val flow = repository.getIsSessionStartedFlow()
+
assertThat(flow.first()).isFalse()
}
}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/network/SubscriptionUtilRoboTest.java b/tests/robotests/src/com/android/settings/network/SubscriptionUtilRoboTest.java
index ae504be..a6c9ef6 100644
--- a/tests/robotests/src/com/android/settings/network/SubscriptionUtilRoboTest.java
+++ b/tests/robotests/src/com/android/settings/network/SubscriptionUtilRoboTest.java
@@ -19,11 +19,13 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import static org.robolectric.Shadows.shadowOf;
import android.content.Context;
+import android.content.res.Resources;
import android.net.ConnectivityManager;
import android.net.NetworkCapabilities;
import android.telephony.SubscriptionManager;
@@ -42,6 +44,8 @@
public class SubscriptionUtilRoboTest {
private static final int SUBID_1 = 1;
private static final int SUBID_2 = 2;
+ private static final int RAC_CARRIER_ID = 1;
+ private static final int CARRIER_ID = 2;
private Context mContext;
private NetworkCapabilities mNetworkCapabilities;
@@ -49,13 +53,16 @@
@Mock
private ConnectivityManager mConnectivityManager;
+ @Mock private Resources mResources;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = spy(ApplicationProvider.getApplicationContext());
mShadowSubscriptionManager = shadowOf(mContext.getSystemService(SubscriptionManager.class));
+ when(mContext.getResources()).thenReturn(mResources);
when(mContext.getSystemService(ConnectivityManager.class)).thenReturn(mConnectivityManager);
+ when(mResources.getIntArray(anyInt())).thenReturn(new int[] {RAC_CARRIER_ID});
}
@Test
@@ -74,6 +81,58 @@
assertFalse(SubscriptionUtil.isConnectedToMobileDataWithDifferentSubId(mContext, SUBID_1));
}
+ @Test
+ public void carrierIsNotRAC_showRacDialogForEsim_returnFalse() {
+ assertFalse(
+ SubscriptionUtil.shouldShowRacDialogWhenErasingEsim(mContext, SUBID_1, CARRIER_ID));
+ }
+
+ @Test
+ public void carrierIsNotRAC_noWifi_noDataConnection_showRacDialogForEsimreturnFalse() {
+ addNetworkTransportType(NetworkCapabilities.TRANSPORT_BLUETOOTH);
+
+ assertFalse(
+ SubscriptionUtil.shouldShowRacDialogWhenErasingEsim(mContext, SUBID_1, CARRIER_ID));
+ }
+
+ @Test
+ public void carrierIsRAC_isConnectedToDataOnSubId2_showRacDialogForEsim_returnFalse() {
+ addNetworkTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
+ mShadowSubscriptionManager.setActiveDataSubscriptionId(SUBID_2);
+
+ assertFalse(
+ SubscriptionUtil.shouldShowRacDialogWhenErasingEsim(
+ mContext, SUBID_1, RAC_CARRIER_ID));
+ }
+
+ @Test
+ public void carrierIsRAC_hasWifi_showRacDialogForEsim_returnFalse() {
+ addNetworkTransportType(NetworkCapabilities.TRANSPORT_WIFI);
+
+ assertFalse(
+ SubscriptionUtil.shouldShowRacDialogWhenErasingEsim(
+ mContext, SUBID_1, RAC_CARRIER_ID));
+ }
+
+ @Test
+ public void carrierIsRAC_isConnectedToDataOnSubId1_noWifi_showRacDialogForEsim_returnTrue() {
+ addNetworkTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
+ mShadowSubscriptionManager.setActiveDataSubscriptionId(SUBID_1);
+
+ assertTrue(
+ SubscriptionUtil.shouldShowRacDialogWhenErasingEsim(
+ mContext, SUBID_1, RAC_CARRIER_ID));
+ }
+
+ @Test
+ public void carrierIsRAC_noData_noWifi_showRacDialogForEsim_returnTrue() {
+ addNetworkTransportType(NetworkCapabilities.TRANSPORT_BLUETOOTH);
+
+ assertTrue(
+ SubscriptionUtil.shouldShowRacDialogWhenErasingEsim(
+ mContext, SUBID_1, RAC_CARRIER_ID));
+ }
+
private void addNetworkTransportType(int networkType) {
mNetworkCapabilities =
new NetworkCapabilities.Builder().addTransportType(networkType).build();
diff --git a/tests/robotests/src/com/android/settings/sim/PrimarySubscriptionListChangedServiceTest.java b/tests/robotests/src/com/android/settings/sim/PrimarySubscriptionListChangedServiceTest.java
new file mode 100644
index 0000000..3e868e4
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/sim/PrimarySubscriptionListChangedServiceTest.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.sim;
+
+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.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.job.JobInfo;
+import android.app.job.JobScheduler;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+
+import androidx.test.core.app.ApplicationProvider;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.Robolectric;
+import org.robolectric.RobolectricTestRunner;
+
+import java.util.List;
+import java.util.Objects;
+
+@RunWith(RobolectricTestRunner.class)
+public class PrimarySubscriptionListChangedServiceTest {
+
+ @Test
+ public void schedulePrimarySubscriptionChanged_addSchedule_intentPassToJobInfo() {
+ Robolectric.setupService(PrimarySubscriptionListChangedService.class);
+ Context context = ApplicationProvider.getApplicationContext();
+ Intent intent = new Intent();
+ intent.putExtra("int", 1);
+ intent.putExtra("string", "foo");
+
+ PrimarySubscriptionListChangedService.scheduleJob(context, intent);
+
+ List<JobInfo> jobs = Objects.requireNonNull(context.getSystemService(JobScheduler.class))
+ .getAllPendingJobs();
+ assertThat(jobs).hasSize(1);
+ JobInfo job = jobs.get(0);
+ assertThat(job.isPersisted()).isFalse();
+ Bundle bundle = job.getTransientExtras();
+ assertThat(bundle.getInt("int")).isEqualTo(1);
+ assertThat(bundle.getString("string")).isEqualTo("foo");
+ }
+
+ @Test
+ public void schedulePrimarySubscriptionChanged_addSchedule_whenInvoked() {
+ Context context = spy(ApplicationProvider.getApplicationContext());
+ JobScheduler jobScheduler = mock(JobScheduler.class);
+ when(context.getSystemService(JobScheduler.class)).thenReturn(jobScheduler);
+
+ PrimarySubscriptionListChangedService.scheduleJob(context, new Intent());
+
+ verify(jobScheduler).schedule(any());
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/sim/SimSelectNotificationTest.java b/tests/robotests/src/com/android/settings/sim/SimSelectNotificationTest.java
index cbdcf3c..36f6cd4 100644
--- a/tests/robotests/src/com/android/settings/sim/SimSelectNotificationTest.java
+++ b/tests/robotests/src/com/android/settings/sim/SimSelectNotificationTest.java
@@ -63,6 +63,7 @@
import androidx.test.core.app.ApplicationProvider;
import com.android.settings.R;
+import com.android.settings.network.SatelliteRepository;
import com.android.settings.network.SubscriptionUtil;
import com.android.settings.testutils.shadow.ShadowAlertDialogCompat;
@@ -141,6 +142,8 @@
SubscriptionUtil.setActiveSubscriptionsForTesting(Arrays.asList(mSubInfo));
when(mSubscriptionManager.isActiveSubscriptionId(mSubId)).thenReturn(true);
when(mSubscriptionManager.getActiveSubscriptionInfo(mSubId)).thenReturn(mSubInfo);
+ SatelliteRepository.Companion.setIsSessionStartedForTesting(false);
+
when(mSubInfo.getSubscriptionId()).thenReturn(mSubId);
when(mSubInfo.getDisplayName()).thenReturn(mFakeDisplayName);
when(mContext.getResources()).thenReturn(mResources);
@@ -219,17 +222,30 @@
Intent intent = new Intent(TelephonyManager.ACTION_PRIMARY_SUBSCRIPTION_LIST_CHANGED);
// EXTRA_SUB_ID and EXTRA_ENABLE_MMS_DATA_REQUEST_REASON are required.
- mSimSelectNotification.onReceive(mContext, intent);
+ SimSelectNotification.onPrimarySubscriptionListChanged(mContext, intent);
verify(mNotificationManager, never()).createNotificationChannel(any());
}
@Test
+ public void onReceivePrimarySubListChange_isSatelliteEnabled_activityShouldNotStart() {
+ SatelliteRepository.Companion.setIsSessionStartedForTesting(true);
+
+ Intent intent = new Intent(TelephonyManager.ACTION_PRIMARY_SUBSCRIPTION_LIST_CHANGED);
+ intent.putExtra(EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE,
+ EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_DATA);
+
+ SimSelectNotification.onPrimarySubscriptionListChanged(mContext, intent);
+
+ verify(mContext, never()).startActivity(any());
+ }
+
+ @Test
public void onReceivePrimarySubListChange_WithDataPickExtra_shouldStartActivity() {
Intent intent = new Intent(TelephonyManager.ACTION_PRIMARY_SUBSCRIPTION_LIST_CHANGED);
intent.putExtra(EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE,
EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_DATA);
- mSimSelectNotification.onReceive(mContext, intent);
+ SimSelectNotification.onPrimarySubscriptionListChanged(mContext, intent);
ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
verify(mContext).startActivity(intentCaptor.capture());
@@ -252,12 +268,13 @@
intent.putExtra(EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE,
EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_DISMISS);
- mSimSelectNotification.onReceive(mContext, intent);
+ SimSelectNotification.onPrimarySubscriptionListChanged(mContext, intent);
clearInvocations(mContext);
// Dismiss.
verify(mExecutor).execute(any());
}
+
@Test
public void onReceivePrimarySubListChange_DualCdmaWarning_notificationShouldSend() {
Intent intent = new Intent(TelephonyManager.ACTION_PRIMARY_SUBSCRIPTION_LIST_CHANGED);
@@ -266,7 +283,7 @@
intent.putExtra(EXTRA_SIM_COMBINATION_WARNING_TYPE,
EXTRA_SIM_COMBINATION_WARNING_TYPE_DUAL_CDMA);
- mSimSelectNotification.onReceive(mContext, intent);
+ SimSelectNotification.onPrimarySubscriptionListChanged(mContext, intent);
// Capture the notification channel created and verify its fields.
ArgumentCaptor<NotificationChannel> nc = ArgumentCaptor.forClass(NotificationChannel.class);
diff --git a/tests/robotests/src/com/android/settings/sound/MediaOutputPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/sound/MediaOutputPreferenceControllerTest.java
index 5dc602a..cd64225 100644
--- a/tests/robotests/src/com/android/settings/sound/MediaOutputPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/sound/MediaOutputPreferenceControllerTest.java
@@ -241,8 +241,6 @@
mScreen.addPreference(mPreference);
mController.displayPreference(mScreen);
mController.setCallback(mAudioSwitchPreferenceCallback);
-
- mSetFlagsRule.initAllFlagsToReleaseConfigDefault();
}
@After
diff --git a/tests/robotests/src/com/android/settings/uwb/UwbPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/uwb/UwbPreferenceControllerTest.java
index 23aca51..941aa3f 100644
--- a/tests/robotests/src/com/android/settings/uwb/UwbPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/uwb/UwbPreferenceControllerTest.java
@@ -49,6 +49,7 @@
import com.android.settings.core.BasePreferenceController;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -60,6 +61,7 @@
/** Unit tests for UWB preference toggle. */
@RunWith(RobolectricTestRunner.class)
+@Ignore("b/337171922")
public class UwbPreferenceControllerTest {
private static final String TEST_SUMMARY = "uwb";
private static final String TEST_AIRPLANE_SUMMARY = "apm_uwb";
diff --git a/tests/robotests/src/com/android/settings/wallpaper/FallbackHomeActivityTest.java b/tests/robotests/src/com/android/settings/wallpaper/FallbackHomeActivityTest.java
index c1debb5..6c656a1 100644
--- a/tests/robotests/src/com/android/settings/wallpaper/FallbackHomeActivityTest.java
+++ b/tests/robotests/src/com/android/settings/wallpaper/FallbackHomeActivityTest.java
@@ -44,7 +44,6 @@
import org.robolectric.annotation.Config;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
-import org.robolectric.annotation.LooperMode;
import org.robolectric.shadow.api.Shadow;
import org.robolectric.shadows.ShadowApplication;
@@ -52,7 +51,6 @@
import java.util.List;
@RunWith(RobolectricTestRunner.class)
-@LooperMode(LooperMode.Mode.LEGACY)
public class FallbackHomeActivityTest {
public final MockitoRule mMockitoRule = MockitoJUnit.rule();
diff --git a/tests/robotests/src/com/android/settings/wallpaper/WallpaperSuggestionActivityTest.java b/tests/robotests/src/com/android/settings/wallpaper/WallpaperSuggestionActivityTest.java
index dd82714..3f6d785 100644
--- a/tests/robotests/src/com/android/settings/wallpaper/WallpaperSuggestionActivityTest.java
+++ b/tests/robotests/src/com/android/settings/wallpaper/WallpaperSuggestionActivityTest.java
@@ -42,12 +42,10 @@
import org.robolectric.annotation.Config;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
-import org.robolectric.annotation.LooperMode;
import org.robolectric.annotation.Resetter;
import org.robolectric.shadows.ShadowApplication;
@RunWith(RobolectricTestRunner.class)
-@LooperMode(LooperMode.Mode.LEGACY)
public class WallpaperSuggestionActivityTest {
@Mock
diff --git a/tests/robotests/src/com/android/settings/wallpaper/WallpaperTypePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/wallpaper/WallpaperTypePreferenceControllerTest.java
index 995bac6..78a5712 100644
--- a/tests/robotests/src/com/android/settings/wallpaper/WallpaperTypePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/wallpaper/WallpaperTypePreferenceControllerTest.java
@@ -33,10 +33,8 @@
import org.mockito.junit.MockitoRule;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
-import org.robolectric.annotation.LooperMode;
@RunWith(RobolectricTestRunner.class)
-@LooperMode(LooperMode.Mode.LEGACY)
public class WallpaperTypePreferenceControllerTest {
public final MockitoRule mMockitoRule = MockitoJUnit.rule();
diff --git a/tests/robotests/src/com/android/settings/widget/RestrictedButtonTest.java b/tests/robotests/src/com/android/settings/widget/RestrictedButtonTest.java
index b3c7049..4b05b91 100644
--- a/tests/robotests/src/com/android/settings/widget/RestrictedButtonTest.java
+++ b/tests/robotests/src/com/android/settings/widget/RestrictedButtonTest.java
@@ -39,13 +39,11 @@
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
-import org.robolectric.annotation.LooperMode;
import java.util.ArrayList;
import java.util.List;
@RunWith(RobolectricTestRunner.class)
-@LooperMode(LooperMode.Mode.LEGACY)
@Config(shadows = {ShadowUserManager.class, ShadowDevicePolicyManager.class})
public class RestrictedButtonTest {
diff --git a/tests/robotests/src/com/android/settings/widget/VideoPreferenceTest.java b/tests/robotests/src/com/android/settings/widget/VideoPreferenceTest.java
index 293c4e4..2492de1 100644
--- a/tests/robotests/src/com/android/settings/widget/VideoPreferenceTest.java
+++ b/tests/robotests/src/com/android/settings/widget/VideoPreferenceTest.java
@@ -47,7 +47,6 @@
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
-import org.robolectric.annotation.LooperMode;
import org.robolectric.shadows.androidx.fragment.FragmentController;
@RunWith(RobolectricTestRunner.class)
@@ -141,7 +140,6 @@
assertThat(mAnimationController.isPlaying()).isTrue();
}
- @LooperMode(LooperMode.Mode.LEGACY)
@Test
@Config(qualifiers = "mcc999")
public void onViewVisible_createAnimationController() {
diff --git a/tests/robotests/src/com/android/settings/wifi/WifiDialogActivityTest.java b/tests/robotests/src/com/android/settings/wifi/WifiDialogActivityTest.java
index 886a4bc..d1cbd0e 100644
--- a/tests/robotests/src/com/android/settings/wifi/WifiDialogActivityTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/WifiDialogActivityTest.java
@@ -57,10 +57,8 @@
import org.mockito.MockitoAnnotations;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
-import org.robolectric.annotation.LooperMode;
@RunWith(RobolectricTestRunner.class)
-@LooperMode(LooperMode.Mode.LEGACY)
public class WifiDialogActivityTest {
static final String CALLING_PACKAGE = "calling_package";
diff --git a/tests/unit/src/com/android/settings/network/SubscriptionUtilTest.java b/tests/unit/src/com/android/settings/network/SubscriptionUtilTest.java
index 46c281f..0de0907 100644
--- a/tests/unit/src/com/android/settings/network/SubscriptionUtilTest.java
+++ b/tests/unit/src/com/android/settings/network/SubscriptionUtilTest.java
@@ -658,36 +658,36 @@
}
@Test
- public void hasSubscriptionWithRacCarrier_hasNoWifi_showRacDialog_returnTrue() {
+ public void hasSubscriptionWithRacCarrier_hasNoWifi_showRacDialogForAllEsims_returnTrue() {
when(mResources.getIntArray(anyInt())).thenReturn(CARRIERS_THAT_USE_RAC);
final SubscriptionInfo info = mock(SubscriptionInfo.class);
when(info.getCarrierId()).thenReturn(RAC_CARRIER_ID);
when(mSubMgr.getAvailableSubscriptionInfoList()).thenReturn(Arrays.asList(info));
addNetworkTransportType(NetworkCapabilities.TRANSPORT_BLUETOOTH);
- assertTrue(SubscriptionUtil.shouldShowRacDialog(mContext));
+ assertTrue(SubscriptionUtil.shouldShowRacDialogWhenErasingAllEsims(mContext));
}
@Test
- public void hasSubscriptionWithRacCarrier_hasWifi_showRacDialog_returnFalse() {
+ public void hasSubscriptionWithRacCarrier_hasWifi_showRacDialogForAllEsims_returnFalse() {
when(mResources.getIntArray(anyInt())).thenReturn(CARRIERS_THAT_USE_RAC);
final SubscriptionInfo info = mock(SubscriptionInfo.class);
when(info.getCarrierId()).thenReturn(RAC_CARRIER_ID);
when(mSubMgr.getAvailableSubscriptionInfoList()).thenReturn(Arrays.asList(info));
addNetworkTransportType(NetworkCapabilities.TRANSPORT_WIFI);
- assertFalse(SubscriptionUtil.shouldShowRacDialog(mContext));
+ assertFalse(SubscriptionUtil.shouldShowRacDialogWhenErasingAllEsims(mContext));
}
@Test
- public void hasNoSubscriptionWithRacCarrier_hasNoWifi_showRacDialog_returnFalse() {
+ public void hasNoSubscriptionWithRacCarrier_hasNoWifi_showRacDialogForAllEsims_returnFalse() {
when(mResources.getIntArray(anyInt())).thenReturn(CARRIERS_THAT_USE_RAC);
final SubscriptionInfo info = mock(SubscriptionInfo.class);
when(info.getCarrierId()).thenReturn(NO_RAC_CARRIER_ID);
when(mSubMgr.getAvailableSubscriptionInfoList()).thenReturn(Arrays.asList(info));
addNetworkTransportType(NetworkCapabilities.TRANSPORT_WIFI);
- assertFalse(SubscriptionUtil.shouldShowRacDialog(mContext));
+ assertFalse(SubscriptionUtil.shouldShowRacDialogWhenErasingAllEsims(mContext));
}
private void addNetworkTransportType(int networkType) {