diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 9ae77b24c15..14879e24ab2 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -5192,6 +5192,18 @@
android:theme="@style/Theme.SpaLib.Dialog">
+
+
+
+
+
+
+
+
+ settings:controller="com.android.settings.connecteddevice.audiosharing.AudioSharingCallAudioPreferenceController" />
+ android:title="@string/audio_streams_main_page_title" />
\ No newline at end of file
diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java
index 9ebc12454cf..3367bf18f9f 100644
--- a/src/com/android/settings/Settings.java
+++ b/src/com/android/settings/Settings.java
@@ -47,6 +47,7 @@ public class Settings extends SettingsActivity {
public static class MemtagPageActivity extends SettingsActivity { /* empty */}
public static class BluetoothSettingsActivity extends SettingsActivity { /* empty */ }
+ public static class BluetoothDashboardActivity extends SettingsActivity { /* empty */ }
public static class CreateShortcutActivity extends SettingsActivity { /* empty */ }
public static class FaceSettingsActivity extends SettingsActivity { /* empty */ }
/** Container for {@link FaceSettings} to use with a pre-defined task affinity. */
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java
index 39b13133dd4..795f999a030 100644
--- a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java
@@ -264,7 +264,7 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
mIsSetupWizard = WizardManagerHelper.isAnySetupWizard(getIntent());
if (mCanAssumeUdfps || mCanAssumeSfps) {
- updateTitleAndDescription();
+ updateTitleAndDescription(true);
} else {
setHeaderText(R.string.security_settings_fingerprint_enroll_repeat_title);
}
@@ -387,7 +387,7 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
protected void onStart() {
super.onStart();
updateProgress(false /* animate */);
- updateTitleAndDescription();
+ updateTitleAndDescription(true);
if (mRestoring) {
startIconAnimation();
}
@@ -491,12 +491,14 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
return new Intent(this, FingerprintEnrollFinish.class);
}
- private void updateTitleAndDescription() {
+ private void updateTitleAndDescription(boolean force) {
if (mCanAssumeUdfps) {
updateTitleAndDescriptionForUdfps();
return;
} else if (mCanAssumeSfps) {
- updateTitleAndDescriptionForSfps();
+ if (force || mSfpsEnrollmentFeature.shouldUpdateTitleAndDescription()) {
+ updateTitleAndDescriptionForSfps();
+ }
return;
}
@@ -814,12 +816,15 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
public void onEnrollmentProgressChange(int steps, int remaining) {
updateProgress(true /* animate */);
final int percent = (int) (((float) (steps - remaining) / (float) steps) * 100);
- if (mCanAssumeSfps && mIsAccessibilityEnabled) {
- CharSequence announcement = getString(
- R.string.security_settings_sfps_enroll_progress_a11y_message, percent);
- announceEnrollmentProgress(announcement);
+ if (mCanAssumeSfps) {
+ mSfpsEnrollmentFeature.handleOnEnrollmentProgressChange(steps, remaining);
+ if (mIsAccessibilityEnabled) {
+ CharSequence announcement = getString(
+ R.string.security_settings_sfps_enroll_progress_a11y_message, percent);
+ announceEnrollmentProgress(announcement);
+ }
}
- updateTitleAndDescription();
+ updateTitleAndDescription(false);
animateFlash();
if (mCanAssumeUdfps) {
if (mIsAccessibilityEnabled) {
@@ -850,6 +855,9 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
if (mUdfpsEnrollHelper != null) {
mUdfpsEnrollHelper.onAcquired(isAcquiredGood);
}
+ if (mCanAssumeSfps) {
+ mSfpsEnrollmentFeature.handleOnAcquired(isAcquiredGood);
+ }
}
@Override
diff --git a/src/com/android/settings/biometrics/fingerprint/MessageDisplayController.java b/src/com/android/settings/biometrics/fingerprint/MessageDisplayController.java
index 4dc75b9d375..639bb3df497 100644
--- a/src/com/android/settings/biometrics/fingerprint/MessageDisplayController.java
+++ b/src/com/android/settings/biometrics/fingerprint/MessageDisplayController.java
@@ -177,6 +177,11 @@ public class MessageDisplayController extends FingerprintManager.EnrollmentCallb
mEnrollmentCallback.onEnrollmentError(errMsgId, errString);
}
+ @Override
+ public void onAcquired(boolean isAcquiredGood) {
+ mEnrollmentCallback.onAcquired(isAcquiredGood);
+ }
+
private Message getMessageToDisplay(long timeStamp) {
ProgressMessage progressMessageToDisplay = getProgressMessageToDisplay(timeStamp);
if (mMustDisplayProgress) {
diff --git a/src/com/android/settings/biometrics/fingerprint/feature/SfpsEnrollmentFeature.java b/src/com/android/settings/biometrics/fingerprint/feature/SfpsEnrollmentFeature.java
index f99d394dceb..bdf9530828b 100644
--- a/src/com/android/settings/biometrics/fingerprint/feature/SfpsEnrollmentFeature.java
+++ b/src/com/android/settings/biometrics/fingerprint/feature/SfpsEnrollmentFeature.java
@@ -93,4 +93,25 @@ public interface SfpsEnrollmentFeature {
* @param lottieView the view related to the lottie
*/
default void handleOnEnrollmentLottieComposition(LottieAnimationView lottieView) {}
+
+ /**
+ * Indicates if the title and description should be updated.
+ * @return true to update the title and description; false otherwise.
+ */
+ default boolean shouldUpdateTitleAndDescription() {
+ return true;
+ }
+
+ /**
+ * Notifies an acquisition happens.
+ * @param isAcquiredGood isAcquiredGood
+ */
+ default void handleOnAcquired(boolean isAcquiredGood) {}
+
+ /**
+ * Notifies an enrollment progress changes event.
+ * @param steps steps
+ * @param remaining remaining
+ */
+ default void handleOnEnrollmentProgressChange(int steps, int remaining) {}
}
diff --git a/src/com/android/settings/connecteddevice/audiosharing/CallsAndAlarmsDialogFragment.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingCallAudioDialogFragment.java
similarity index 93%
rename from src/com/android/settings/connecteddevice/audiosharing/CallsAndAlarmsDialogFragment.java
rename to src/com/android/settings/connecteddevice/audiosharing/AudioSharingCallAudioDialogFragment.java
index df94694b492..db82619ca60 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/CallsAndAlarmsDialogFragment.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingCallAudioDialogFragment.java
@@ -32,7 +32,7 @@ import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
import java.util.List;
/** Provides a dialog to choose the active device for calls and alarms. */
-public class CallsAndAlarmsDialogFragment extends InstrumentedDialogFragment {
+public class AudioSharingCallAudioDialogFragment extends InstrumentedDialogFragment {
private static final String TAG = "CallsAndAlarmsDialog";
private static final String BUNDLE_KEY_DEVICE_ITEMS = "bundle_key_device_items";
@@ -55,7 +55,7 @@ public class CallsAndAlarmsDialogFragment extends InstrumentedDialogFragment {
}
/**
- * Display the {@link CallsAndAlarmsDialogFragment} dialog.
+ * Display the {@link AudioSharingCallAudioDialogFragment} dialog.
*
* @param host The Fragment this dialog will be hosted.
* @param deviceItems The connected device items in audio sharing session.
@@ -71,7 +71,8 @@ public class CallsAndAlarmsDialogFragment extends InstrumentedDialogFragment {
if (manager.findFragmentByTag(TAG) == null) {
final Bundle bundle = new Bundle();
bundle.putParcelableList(BUNDLE_KEY_DEVICE_ITEMS, deviceItems);
- final CallsAndAlarmsDialogFragment dialog = new CallsAndAlarmsDialogFragment();
+ final AudioSharingCallAudioDialogFragment dialog =
+ new AudioSharingCallAudioDialogFragment();
dialog.setArguments(bundle);
dialog.show(manager, TAG);
}
diff --git a/src/com/android/settings/connecteddevice/audiosharing/CallsAndAlarmsPreferenceController.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingCallAudioPreferenceController.java
similarity index 96%
rename from src/com/android/settings/connecteddevice/audiosharing/CallsAndAlarmsPreferenceController.java
rename to src/com/android/settings/connecteddevice/audiosharing/AudioSharingCallAudioPreferenceController.java
index 8aaebc6dbd2..e848f88576b 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/CallsAndAlarmsPreferenceController.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingCallAudioPreferenceController.java
@@ -51,6 +51,8 @@ import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
import com.android.settingslib.utils.ThreadUtils;
+import com.google.common.collect.ImmutableList;
+
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -60,7 +62,7 @@ import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicBoolean;
/** PreferenceController to control the dialog to choose the active device for calls and alarms */
-public class CallsAndAlarmsPreferenceController extends AudioSharingBasePreferenceController
+public class AudioSharingCallAudioPreferenceController extends AudioSharingBasePreferenceController
implements BluetoothCallback {
private static final String TAG = "CallsAndAlarmsPreferenceController";
private static final String PREF_KEY = "calls_and_alarms";
@@ -131,7 +133,7 @@ public class CallsAndAlarmsPreferenceController extends AudioSharingBasePreferen
}
};
- public CallsAndAlarmsPreferenceController(Context context) {
+ public AudioSharingCallAudioPreferenceController(Context context) {
super(context, PREF_KEY);
mBtManager = Utils.getLocalBtManager(mContext);
mProfileManager = mBtManager == null ? null : mBtManager.getProfileManager();
@@ -176,16 +178,13 @@ public class CallsAndAlarmsPreferenceController extends AudioSharingBasePreferen
}
updateDeviceItemsInSharingSession();
if (mDeviceItemsInSharingSession.size() >= 1) {
- CallsAndAlarmsDialogFragment.show(
+ AudioSharingCallAudioDialogFragment.show(
mFragment,
mDeviceItemsInSharingSession,
(AudioSharingDeviceItem item) -> {
- if (!mGroupedConnectedDevices.containsKey(
- item.getGroupId())) {
- return;
- }
List devices =
- mGroupedConnectedDevices.get(item.getGroupId());
+ mGroupedConnectedDevices.getOrDefault(
+ item.getGroupId(), ImmutableList.of());
@Nullable
CachedBluetoothDevice lead =
AudioSharingUtils.getLeadDevice(devices);
diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDashboardFragment.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDashboardFragment.java
index 275d1976086..c3248c7e573 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDashboardFragment.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDashboardFragment.java
@@ -33,7 +33,7 @@ public class AudioSharingDashboardFragment extends DashboardFragment
SettingsMainSwitchBar mMainSwitchBar;
private AudioSharingSwitchBarController mSwitchBarController;
private AudioSharingDeviceVolumeGroupController mAudioSharingDeviceVolumeGroupController;
- private CallsAndAlarmsPreferenceController mCallsAndAlarmsPreferenceController;
+ private AudioSharingCallAudioPreferenceController mAudioSharingCallAudioPreferenceController;
private AudioSharingPlaySoundPreferenceController mAudioSharingPlaySoundPreferenceController;
private AudioStreamsCategoryController mAudioStreamsCategoryController;
@@ -67,8 +67,9 @@ public class AudioSharingDashboardFragment extends DashboardFragment
mAudioSharingDeviceVolumeGroupController =
use(AudioSharingDeviceVolumeGroupController.class);
mAudioSharingDeviceVolumeGroupController.init(this);
- mCallsAndAlarmsPreferenceController = use(CallsAndAlarmsPreferenceController.class);
- mCallsAndAlarmsPreferenceController.init(this);
+ mAudioSharingCallAudioPreferenceController =
+ use(AudioSharingCallAudioPreferenceController.class);
+ mAudioSharingCallAudioPreferenceController.init(this);
mAudioSharingPlaySoundPreferenceController =
use(AudioSharingPlaySoundPreferenceController.class);
mAudioStreamsCategoryController = use(AudioStreamsCategoryController.class);
@@ -100,7 +101,7 @@ public class AudioSharingDashboardFragment extends DashboardFragment
private void updateVisibilityForAttachedPreferences() {
mAudioSharingDeviceVolumeGroupController.updateVisibility();
- mCallsAndAlarmsPreferenceController.updateVisibility();
+ mAudioSharingCallAudioPreferenceController.updateVisibility();
mAudioSharingPlaySoundPreferenceController.updateVisibility();
mAudioStreamsCategoryController.updateVisibility();
}
diff --git a/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamMediaService.java b/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamMediaService.java
index 2e4930cf4b3..ea5eede9df9 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamMediaService.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamMediaService.java
@@ -42,6 +42,7 @@ import com.android.settings.bluetooth.Utils;
import com.android.settings.connecteddevice.audiosharing.AudioSharingUtils;
import com.android.settingslib.bluetooth.BluetoothCallback;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
+import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.bluetooth.VolumeControlProfile;
@@ -60,6 +61,7 @@ public class AudioStreamMediaService extends Service {
private static final String LEAVE_BROADCAST_ACTION = "leave_broadcast_action";
private static final String LEAVE_BROADCAST_TEXT = "Leave Broadcast";
private static final String CHANNEL_ID = "bluetooth_notification_channel";
+ private static final String DEFAULT_DEVICE_NAME = "";
private static final int STATIC_PLAYBACK_DURATION = 100;
private static final int STATIC_PLAYBACK_POSITION = 30;
private static final int ZERO_PLAYBACK_SPEED = 0;
@@ -355,16 +357,34 @@ public class AudioStreamMediaService extends Service {
return mIsMuted ? mPlayStatePausingBuilder.build() : mPlayStatePlayingBuilder.build();
}
+ private String getDeviceName() {
+ if (mDevices == null || mDevices.isEmpty() || mLocalBtManager == null) {
+ return DEFAULT_DEVICE_NAME;
+ }
+
+ CachedBluetoothDeviceManager manager = mLocalBtManager.getCachedDeviceManager();
+ if (manager == null) {
+ return DEFAULT_DEVICE_NAME;
+ }
+
+ CachedBluetoothDevice device = manager.findDevice(mDevices.get(0));
+ return device != null ? device.getName() : DEFAULT_DEVICE_NAME;
+ }
+
private Notification buildNotification() {
+ String deviceName = getDeviceName();
+ Notification.MediaStyle mediaStyle =
+ new Notification.MediaStyle()
+ .setMediaSession(
+ mLocalSession != null ? mLocalSession.getSessionToken() : null);
+ if (deviceName != null && !deviceName.isEmpty()) {
+ mediaStyle.setRemotePlaybackInfo(
+ deviceName, com.android.internal.R.drawable.ic_bt_headset_hfp, null);
+ }
Notification.Builder notificationBuilder =
new Notification.Builder(this, CHANNEL_ID)
.setSmallIcon(com.android.settingslib.R.drawable.ic_bt_le_audio_sharing)
- .setStyle(
- new Notification.MediaStyle()
- .setMediaSession(
- mLocalSession != null
- ? mLocalSession.getSessionToken()
- : null))
+ .setStyle(mediaStyle)
.setContentText(this.getString(BROADCAST_CONTENT_TEXT))
.setSilent(true);
return notificationBuilder.build();
diff --git a/src/com/android/settings/core/gateway/SettingsGateway.java b/src/com/android/settings/core/gateway/SettingsGateway.java
index 7c601c0d613..1c14712df30 100644
--- a/src/com/android/settings/core/gateway/SettingsGateway.java
+++ b/src/com/android/settings/core/gateway/SettingsGateway.java
@@ -86,6 +86,7 @@ import com.android.settings.bluetooth.BluetoothPairingDetail;
import com.android.settings.bugreporthandler.BugReportHandlerPicker;
import com.android.settings.communal.CommunalDashboardFragment;
import com.android.settings.connecteddevice.AdvancedConnectedDeviceDashboardFragment;
+import com.android.settings.connecteddevice.BluetoothDashboardFragment;
import com.android.settings.connecteddevice.ConnectedDeviceDashboardFragment;
import com.android.settings.connecteddevice.NfcAndPaymentFragment;
import com.android.settings.connecteddevice.PreviouslyConnectedDeviceDashboardFragment;
@@ -213,6 +214,7 @@ public class SettingsGateway {
AdvancedConnectedDeviceDashboardFragment.class.getName(),
CreateShortcut.class.getName(),
BluetoothPairingDetail.class.getName(),
+ BluetoothDashboardFragment.class.getName(),
WifiNetworkDetailsFragment.class.getName(),
ConfigureWifiSettings.class.getName(),
SavedAccessPointsWifiSettings2.class.getName(),
diff --git a/src/com/android/settings/fuelgauge/BatterySettingsStorage.java b/src/com/android/settings/fuelgauge/BatterySettingsStorage.java
index 99edbecd617..4c8b9b83cd1 100644
--- a/src/com/android/settings/fuelgauge/BatterySettingsStorage.java
+++ b/src/com/android/settings/fuelgauge/BatterySettingsStorage.java
@@ -57,7 +57,8 @@ import java.util.List;
/** An implementation to backup and restore battery configurations. */
public final class BatterySettingsStorage extends ObservableBackupRestoreStorage {
- public static final String TAG = "BatteryBackupHelper";
+ private static final String NAME = "BatteryBackupHelper";
+ private static final String TAG = "BatterySettingsStorage";
// Definition for the device build information.
public static final String KEY_BUILD_BRAND = "device_build_brand";
@@ -89,7 +90,7 @@ public final class BatterySettingsStorage extends ObservableBackupRestoreStorage
*/
public static @NonNull BatterySettingsStorage get(@NonNull Context context) {
return (BatterySettingsStorage)
- BackupRestoreStorageManager.getInstance(context).getOrThrow(TAG);
+ BackupRestoreStorageManager.getInstance(context).getOrThrow(NAME);
}
public BatterySettingsStorage(@NonNull Context context) {
@@ -99,7 +100,7 @@ public final class BatterySettingsStorage extends ObservableBackupRestoreStorage
@NonNull
@Override
public String getName() {
- return TAG;
+ return NAME;
}
@Override
diff --git a/src/com/android/settings/network/MobileDataEnabledFlow.kt b/src/com/android/settings/network/MobileDataEnabledFlow.kt
index 23423771f1f..1f995a94b0a 100644
--- a/src/com/android/settings/network/MobileDataEnabledFlow.kt
+++ b/src/com/android/settings/network/MobileDataEnabledFlow.kt
@@ -28,8 +28,8 @@ import kotlinx.coroutines.flow.merge
*
* Note: This flow can only notify enabled status changes, cannot provide the latest status.
*/
-fun Context.mobileDataEnabledFlow(subId: Int): Flow {
- val flow = settingsGlobalChangeFlow(Settings.Global.MOBILE_DATA)
+fun Context.mobileDataEnabledFlow(subId: Int, sendInitialValue: Boolean = true): Flow {
+ val flow = settingsGlobalChangeFlow(Settings.Global.MOBILE_DATA, sendInitialValue)
return when (subId) {
SubscriptionManager.INVALID_SUBSCRIPTION_ID -> flow
else -> {
diff --git a/src/com/android/settings/network/ProxySubscriptionManager.java b/src/com/android/settings/network/ProxySubscriptionManager.java
index 7e276e889be..614491a5016 100644
--- a/src/com/android/settings/network/ProxySubscriptionManager.java
+++ b/src/com/android/settings/network/ProxySubscriptionManager.java
@@ -28,7 +28,6 @@ import android.telephony.SubscriptionManager;
import android.util.Log;
import androidx.annotation.Keep;
-import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleObserver;
@@ -242,15 +241,6 @@ public class ProxySubscriptionManager implements LifecycleObserver {
return mSubscriptionMonitor.getAccessibleSubscriptionInfo(subId);
}
- /**
- * Gets a list of active, visible subscription Id(s) of the currently active SIM(s).
- *
- * @return the list of subId's that are active and visible; the length may be 0.
- */
- public @NonNull int[] getActiveSubscriptionIdList() {
- return mSubscriptionMonitor.getActiveSubscriptionIdList();
- }
-
/**
* Clear data cached within proxy
*/
diff --git a/src/com/android/settings/network/telephony/AutoDataSwitchPreferenceController.java b/src/com/android/settings/network/telephony/AutoDataSwitchPreferenceController.java
index ef74a2ebdf0..fcbfdef4a72 100644
--- a/src/com/android/settings/network/telephony/AutoDataSwitchPreferenceController.java
+++ b/src/com/android/settings/network/telephony/AutoDataSwitchPreferenceController.java
@@ -19,20 +19,14 @@ package com.android.settings.network.telephony;
import static androidx.lifecycle.Lifecycle.Event.ON_PAUSE;
import static androidx.lifecycle.Lifecycle.Event.ON_RESUME;
-import android.app.settings.SettingsEnums;
import android.content.Context;
import android.os.Handler;
import android.os.Looper;
-import android.os.PersistableBundle;
-import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
-import android.telephony.ims.ImsException;
-import android.telephony.ims.ImsManager;
-import android.telephony.ims.ImsMmTelManager;
-import android.util.Log;
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import androidx.lifecycle.LifecycleObserver;
import androidx.lifecycle.OnLifecycleEvent;
import androidx.preference.Preference;
@@ -40,15 +34,11 @@ import androidx.preference.PreferenceScreen;
import androidx.preference.TwoStatePreference;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.settings.R;
import com.android.settings.datausage.DataUsageUtils;
import com.android.settings.flags.Flags;
import com.android.settings.network.MobileDataContentObserver;
-import com.android.settings.network.ProxySubscriptionManager;
import com.android.settings.network.SubscriptionsChangeListener;
-import com.android.settings.network.ims.WifiCallingQueryImsState;
-import com.android.settings.overlay.FeatureFactory;
-import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
+import com.android.settings.network.telephony.wificalling.CrossSimCallingViewModel;
/**
* Controls whether switch mobile data to the non-default SIM if the non-default SIM has better
@@ -63,25 +53,29 @@ import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
public class AutoDataSwitchPreferenceController extends TelephonyTogglePreferenceController
implements LifecycleObserver,
SubscriptionsChangeListener.SubscriptionsChangeListenerClient {
- private static final String LOG_TAG = "AutoDataSwitchPrefCtrl";
+ @Nullable
private TwoStatePreference mPreference;
+ @Nullable
private SubscriptionsChangeListener mChangeListener;
+ @Nullable
private TelephonyManager mManager;
+ @Nullable
private MobileDataContentObserver mMobileDataContentObserver;
+ @Nullable
+ private CrossSimCallingViewModel mCrossSimCallingViewModel;
+ @Nullable
private PreferenceScreen mScreen;
- private final MetricsFeatureProvider mMetricsFeatureProvider;
-
- public AutoDataSwitchPreferenceController(Context context,
- String preferenceKey) {
+ public AutoDataSwitchPreferenceController(
+ @NonNull Context context, @NonNull String preferenceKey) {
super(context, preferenceKey);
- mMetricsFeatureProvider = FeatureFactory.getFeatureFactory().getMetricsFeatureProvider();
}
- void init(int subId) {
+ void init(int subId, @Nullable CrossSimCallingViewModel crossSimCallingViewModel) {
this.mSubId = subId;
mManager = mContext.getSystemService(TelephonyManager.class).createForSubscriptionId(subId);
+ mCrossSimCallingViewModel = crossSimCallingViewModel;
}
@OnLifecycleEvent(ON_RESUME)
@@ -121,35 +115,15 @@ public class AutoDataSwitchPreferenceController extends TelephonyTogglePreferenc
TelephonyManager.MOBILE_DATA_POLICY_AUTO_DATA_SWITCH);
}
- private int getOtherSubId(@NonNull int[] subIds) {
- if (subIds.length > 1) {
- for (int subId : subIds) {
- if (subId != mSubId) {
- return subId;
- }
- }
- }
- return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
- }
-
- private boolean isEnabled(int subId) {
- if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
- return false;
- }
- TelephonyManager telephonyManager = mContext.getSystemService(
- TelephonyManager.class).createForSubscriptionId(subId);
- return telephonyManager != null && telephonyManager.isMobileDataPolicyEnabled(
- TelephonyManager.MOBILE_DATA_POLICY_AUTO_DATA_SWITCH);
- }
-
@Override
public boolean setChecked(boolean isChecked) {
- mManager.setMobileDataPolicyEnabled(
- TelephonyManager.MOBILE_DATA_POLICY_AUTO_DATA_SWITCH,
- isChecked);
- if (mContext.getResources().getBoolean(
- R.bool.config_auto_data_switch_enables_cross_sim_calling)) {
- trySetCrossSimCalling(mContext, getActiveSubscriptionIdList(), isChecked /* enabled */);
+ if (mManager != null) {
+ mManager.setMobileDataPolicyEnabled(
+ TelephonyManager.MOBILE_DATA_POLICY_AUTO_DATA_SWITCH,
+ isChecked);
+ }
+ if (mCrossSimCallingViewModel != null) {
+ mCrossSimCallingViewModel.updateCrossSimCalling();
}
return true;
}
@@ -159,40 +133,6 @@ public class AutoDataSwitchPreferenceController extends TelephonyTogglePreferenc
return DataUsageUtils.hasMobileData(mContext);
}
- private boolean isCrossSimCallingAllowedByPlatform(Context context, int subId) {
- if ((new WifiCallingQueryImsState(context, subId)).isWifiCallingSupported()) {
- PersistableBundle bundle = getCarrierConfigForSubId(subId);
- return (bundle != null) && bundle.getBoolean(
- CarrierConfigManager.KEY_CARRIER_CROSS_SIM_IMS_AVAILABLE_BOOL,
- false /*default*/);
- }
- return false;
- }
-
- protected ImsMmTelManager getImsMmTelManager(Context context, int subId) {
- ImsManager imsMgr = context.getSystemService(ImsManager.class);
- return (imsMgr == null) ? null : imsMgr.getImsMmTelManager(subId);
- }
-
- private void trySetCrossSimCallingPerSub(Context context, int subId, boolean enabled) {
- try {
- getImsMmTelManager(context, subId).setCrossSimCallingEnabled(enabled);
- } catch (ImsException | IllegalArgumentException | NullPointerException exception) {
- Log.w(LOG_TAG, "failed to change cross SIM calling configuration to " + enabled
- + " for subID " + subId + "with exception: ", exception);
- }
- }
-
- private void trySetCrossSimCalling(Context context, int[] subIds, boolean enabled) {
- mMetricsFeatureProvider.action(mContext,
- SettingsEnums.ACTION_UPDATE_CROSS_SIM_CALLING_ON_AUTO_DATA_SWITCH_EVENT, enabled);
- for (int subId : subIds) {
- if (isCrossSimCallingAllowedByPlatform(context, subId)) {
- trySetCrossSimCallingPerSub(context, subId, enabled);
- }
- }
- }
-
@Override
public int getAvailabilityStatus(int subId) {
if (Flags.isDualSimOnboardingEnabled()
@@ -221,20 +161,11 @@ public class AutoDataSwitchPreferenceController extends TelephonyTogglePreferenc
updateState(mPreference);
}
- private int[] getActiveSubscriptionIdList() {
- return ProxySubscriptionManager.getInstance(mContext).getActiveSubscriptionIdList();
- }
-
/**
* Trigger displaying preference when Mobile data content changed.
*/
@VisibleForTesting
public void refreshPreference() {
- if (mContext.getResources().getBoolean(
- R.bool.config_auto_data_switch_enables_cross_sim_calling)) {
- int[] subIds = getActiveSubscriptionIdList();
- trySetCrossSimCalling(mContext, subIds, isEnabled(getOtherSubId(subIds)));
- }
if (mScreen != null) {
super.displayPreference(mScreen);
}
diff --git a/src/com/android/settings/network/telephony/MobileNetworkSettings.java b/src/com/android/settings/network/telephony/MobileNetworkSettings.java
index d57de1a788f..c9a2a0bf733 100644
--- a/src/com/android/settings/network/telephony/MobileNetworkSettings.java
+++ b/src/com/android/settings/network/telephony/MobileNetworkSettings.java
@@ -38,6 +38,7 @@ import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
+import androidx.lifecycle.ViewModelProvider;
import androidx.preference.Preference;
import com.android.settings.R;
@@ -53,6 +54,7 @@ import com.android.settings.network.telephony.cdma.CdmaSubscriptionPreferenceCon
import com.android.settings.network.telephony.cdma.CdmaSystemSelectPreferenceController;
import com.android.settings.network.telephony.gsm.AutoSelectPreferenceController;
import com.android.settings.network.telephony.gsm.OpenNetworkSelectPagePreferenceController;
+import com.android.settings.network.telephony.wificalling.CrossSimCallingViewModel;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.wifi.WifiPickerTrackerHelper;
import com.android.settingslib.core.AbstractPreferenceController;
@@ -240,7 +242,9 @@ public class MobileNetworkSettings extends AbstractMobileNetworkSettings impleme
use(CarrierSettingsVersionPreferenceController.class).init(mSubId);
use(BillingCyclePreferenceController.class).init(mSubId);
use(MmsMessagePreferenceController.class).init(mSubId);
- use(AutoDataSwitchPreferenceController.class).init(mSubId);
+ final var crossSimCallingViewModel =
+ new ViewModelProvider(this).get(CrossSimCallingViewModel.class);
+ use(AutoDataSwitchPreferenceController.class).init(mSubId, crossSimCallingViewModel);
use(DisabledSubscriptionController.class).init(mSubId);
use(DeleteSimProfilePreferenceController.class).init(mSubId);
use(DisableSimFooterPreferenceController.class).init(mSubId);
diff --git a/src/com/android/settings/network/telephony/SubscriptionRepository.kt b/src/com/android/settings/network/telephony/SubscriptionRepository.kt
index 4fd28a20f93..3ee854843fc 100644
--- a/src/com/android/settings/network/telephony/SubscriptionRepository.kt
+++ b/src/com/android/settings/network/telephony/SubscriptionRepository.kt
@@ -124,6 +124,14 @@ fun Context.getSelectableSubscriptionInfoList(): List {
}
}
// Matching the sorting order in SubscriptionManagerService.getAvailableSubscriptionInfoList
- .sortedWith(compareBy({ it.simSlotIndex }, { it.subscriptionId }))
+ .sortedWith(compareBy({ it.sortableSimSlotIndex }, { it.subscriptionId }))
.also { Log.d(TAG, "getSelectableSubscriptionInfoList: $it") }
}
+
+/** Subscription with invalid sim slot index has lowest sort order. */
+private val SubscriptionInfo.sortableSimSlotIndex: Int
+ get() = if (simSlotIndex != SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
+ simSlotIndex
+ } else {
+ Int.MAX_VALUE
+ }
diff --git a/src/com/android/settings/network/telephony/ims/ImsMmTelRepository.kt b/src/com/android/settings/network/telephony/ims/ImsMmTelRepository.kt
index dd1cbd5bc11..9bc10e555e1 100644
--- a/src/com/android/settings/network/telephony/ims/ImsMmTelRepository.kt
+++ b/src/com/android/settings/network/telephony/ims/ImsMmTelRepository.kt
@@ -51,6 +51,8 @@ interface ImsMmTelRepository {
@MmTelFeature.MmTelCapabilities.MmTelCapability capability: Int,
@AccessNetworkConstants.TransportType transportType: Int,
): Boolean
+
+ suspend fun setCrossSimCallingEnabled(enabled: Boolean)
}
class ImsMmTelRepositoryImpl(
@@ -130,6 +132,7 @@ class ImsMmTelRepositoryImpl(
@MmTelFeature.MmTelCapabilities.MmTelCapability capability: Int,
@AccessNetworkConstants.TransportType transportType: Int,
): Boolean = withContext(Dispatchers.Default) {
+ val logName = "isSupported(capability=$capability,transportType=$transportType)"
suspendCancellableCoroutine { continuation ->
try {
imsMmTelManager.isSupported(
@@ -140,9 +143,18 @@ class ImsMmTelRepositoryImpl(
)
} catch (e: Exception) {
continuation.resume(false)
- Log.w(TAG, "[$subId] isSupported failed", e)
+ Log.w(TAG, "[$subId] $logName failed", e)
}
- }.also { Log.d(TAG, "[$subId] isSupported = $it") }
+ }.also { Log.d(TAG, "[$subId] $logName = $it") }
+ }
+
+ override suspend fun setCrossSimCallingEnabled(enabled: Boolean) {
+ try {
+ imsMmTelManager.setCrossSimCallingEnabled(enabled)
+ Log.d(TAG, "[$subId] setCrossSimCallingEnabled: $enabled")
+ } catch (e: Exception) {
+ Log.e(TAG, "[$subId] failed setCrossSimCallingEnabled to $enabled", e)
+ }
}
private companion object {
diff --git a/src/com/android/settings/network/telephony/wificalling/CrossSimCallingViewModel.kt b/src/com/android/settings/network/telephony/wificalling/CrossSimCallingViewModel.kt
new file mode 100644
index 00000000000..5dcac1ebaac
--- /dev/null
+++ b/src/com/android/settings/network/telephony/wificalling/CrossSimCallingViewModel.kt
@@ -0,0 +1,119 @@
+/*
+ * 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.network.telephony.wificalling
+
+import android.app.Application
+import android.app.settings.SettingsEnums
+import android.telephony.CarrierConfigManager
+import android.telephony.SubscriptionManager
+import android.telephony.TelephonyManager
+import androidx.lifecycle.AndroidViewModel
+import androidx.lifecycle.viewModelScope
+import com.android.settings.R
+import com.android.settings.network.mobileDataEnabledFlow
+import com.android.settings.network.telephony.ims.ImsMmTelRepositoryImpl
+import com.android.settings.network.telephony.requireSubscriptionManager
+import com.android.settings.network.telephony.safeGetConfig
+import com.android.settings.network.telephony.subscriptionsChangedFlow
+import com.android.settings.network.telephony.telephonyManager
+import com.android.settings.overlay.FeatureFactory.Companion.featureFactory
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.channels.Channel
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.flatMapLatest
+import kotlinx.coroutines.flow.launchIn
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.merge
+import kotlinx.coroutines.flow.onEach
+import kotlinx.coroutines.flow.receiveAsFlow
+import kotlinx.coroutines.plus
+
+@OptIn(ExperimentalCoroutinesApi::class)
+class CrossSimCallingViewModel(
+ private val application: Application,
+) : AndroidViewModel(application) {
+
+ private val subscriptionManager = application.requireSubscriptionManager()
+ private val carrierConfigManager =
+ application.getSystemService(CarrierConfigManager::class.java)!!
+ private val scope = viewModelScope + Dispatchers.Default
+ private val metricsFeatureProvider = featureFactory.metricsFeatureProvider
+ private val updateChannel = Channel()
+
+ init {
+ val resources = application.resources
+ if (resources.getBoolean(R.bool.config_auto_data_switch_enables_cross_sim_calling)) {
+ application.subscriptionsChangedFlow()
+ .flatMapLatest {
+ val activeSubIds = subscriptionManager.activeSubscriptionIdList.toList()
+ merge(
+ activeSubIds.anyMobileDataEnableChangedFlow(),
+ updateChannel.receiveAsFlow(),
+ ).map {
+ activeSubIds to crossSimCallNewEnabled(activeSubIds)
+ }
+ }
+ .distinctUntilChanged()
+ .onEach { (activeSubIds, newEnabled) ->
+ updateCrossSimCalling(activeSubIds, newEnabled)
+ }
+ .launchIn(scope)
+ }
+ }
+
+ fun updateCrossSimCalling() {
+ updateChannel.trySend(Unit)
+ }
+
+ private fun List.anyMobileDataEnableChangedFlow() = map { subId ->
+ application.mobileDataEnabledFlow(subId = subId, sendInitialValue = false)
+ }.merge()
+
+ private suspend fun updateCrossSimCalling(activeSubIds: List, newEnabled: Boolean) {
+ metricsFeatureProvider.action(
+ application,
+ SettingsEnums.ACTION_UPDATE_CROSS_SIM_CALLING_ON_AUTO_DATA_SWITCH_EVENT,
+ newEnabled,
+ )
+ activeSubIds.filter { crossSimAvailable(it) }.forEach { subId ->
+ ImsMmTelRepositoryImpl(application, subId)
+ .setCrossSimCallingEnabled(newEnabled)
+ }
+ }
+
+ private suspend fun crossSimAvailable(subId: Int): Boolean =
+ WifiCallingRepository(application, subId).isWifiCallingSupported() &&
+ crossSimImsAvailable(subId)
+
+ private fun crossSimImsAvailable(subId: Int): Boolean =
+ carrierConfigManager.safeGetConfig(
+ keys = listOf(CarrierConfigManager.KEY_CARRIER_CROSS_SIM_IMS_AVAILABLE_BOOL),
+ subId = subId,
+ ).getBoolean(CarrierConfigManager.KEY_CARRIER_CROSS_SIM_IMS_AVAILABLE_BOOL, false)
+
+ private fun crossSimCallNewEnabled(activeSubscriptionIdList: List): Boolean {
+ val defaultDataSubId = SubscriptionManager.getDefaultDataSubscriptionId()
+ return SubscriptionManager.isValidSubscriptionId(defaultDataSubId) &&
+ activeSubscriptionIdList.any { subId ->
+ subId != defaultDataSubId &&
+ application.telephonyManager(subId).isMobileDataPolicyEnabled(
+ TelephonyManager.MOBILE_DATA_POLICY_AUTO_DATA_SWITCH
+ )
+ }
+ }
+}
diff --git a/src/com/android/settings/network/telephony/wificalling/WifiCallingRepository.kt b/src/com/android/settings/network/telephony/wificalling/WifiCallingRepository.kt
index ac95404e78e..a5d4ba832ab 100644
--- a/src/com/android/settings/network/telephony/wificalling/WifiCallingRepository.kt
+++ b/src/com/android/settings/network/telephony/wificalling/WifiCallingRepository.kt
@@ -29,17 +29,19 @@ import com.android.settings.network.telephony.ims.ImsMmTelRepository
import com.android.settings.network.telephony.ims.ImsMmTelRepositoryImpl
import com.android.settings.network.telephony.ims.imsFeatureProvisionedFlow
import com.android.settings.network.telephony.subscriptionsChangedFlow
+import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.withContext
class WifiCallingRepository(
private val context: Context,
private val subId: Int,
- private val imsMmTelRepository : ImsMmTelRepository = ImsMmTelRepositoryImpl(context, subId)
+ private val imsMmTelRepository: ImsMmTelRepository = ImsMmTelRepositoryImpl(context, subId)
) {
private val telephonyManager = context.getSystemService(TelephonyManager::class.java)!!
.createForSubscriptionId(subId)
@@ -76,10 +78,14 @@ class WifiCallingRepository(
private fun isWifiCallingSupportedFlow(): Flow {
return imsMmTelRepository.imsReadyFlow().map { imsReady ->
- imsReady && imsMmTelRepository.isSupported(
- capability = MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE,
- transportType = AccessNetworkConstants.TRANSPORT_TYPE_WLAN,
- )
+ imsReady && isWifiCallingSupported()
}
}
+
+ suspend fun isWifiCallingSupported(): Boolean = withContext(Dispatchers.Default) {
+ imsMmTelRepository.isSupported(
+ capability = MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE,
+ transportType = AccessNetworkConstants.TRANSPORT_TYPE_WLAN,
+ )
+ }
}
diff --git a/src/com/android/settings/spa/network/AutomaticDataSwitchingPreference.kt b/src/com/android/settings/spa/network/AutomaticDataSwitchingPreference.kt
index 824a93532b2..e79be4a9cc6 100644
--- a/src/com/android/settings/spa/network/AutomaticDataSwitchingPreference.kt
+++ b/src/com/android/settings/spa/network/AutomaticDataSwitchingPreference.kt
@@ -20,8 +20,10 @@ import android.telephony.TelephonyManager
import androidx.compose.runtime.Composable
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.res.stringResource
+import androidx.lifecycle.viewmodel.compose.viewModel
import com.android.settings.R
import com.android.settings.network.telephony.TelephonyRepository
+import com.android.settings.network.telephony.wificalling.CrossSimCallingViewModel
import com.android.settingslib.spa.widget.preference.SwitchPreference
import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel
import kotlinx.coroutines.Dispatchers
@@ -34,6 +36,7 @@ fun AutomaticDataSwitchingPreference(
) {
val autoDataSummary = stringResource(id = R.string.primary_sim_automatic_data_msg)
val coroutineScope = rememberCoroutineScope()
+ val crossSimCallingViewModel = viewModel() // handles backup calling
SwitchPreference(
object : SwitchPreferenceModel {
override val title = stringResource(id = R.string.primary_sim_automatic_data_title)
@@ -42,6 +45,7 @@ fun AutomaticDataSwitchingPreference(
override val onCheckedChange: (Boolean) -> Unit = { newEnabled ->
coroutineScope.launch(Dispatchers.Default) {
setAutoDataEnabled(newEnabled)
+ crossSimCallingViewModel.updateCrossSimCalling()
}
}
}
@@ -54,5 +58,4 @@ fun TelephonyRepository.setAutomaticData(subId: Int, newEnabled: Boolean) {
policy = TelephonyManager.MOBILE_DATA_POLICY_AUTO_DATA_SWITCH,
enabled = newEnabled,
)
- //TODO: setup backup calling
}
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/CallsAndAlarmsDialogFragmentTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingCallAudioDialogFragmentTest.java
similarity index 95%
rename from tests/robotests/src/com/android/settings/connecteddevice/audiosharing/CallsAndAlarmsDialogFragmentTest.java
rename to tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingCallAudioDialogFragmentTest.java
index 53e0d71c5d6..4477fa3bff2 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/CallsAndAlarmsDialogFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingCallAudioDialogFragmentTest.java
@@ -51,7 +51,7 @@ import java.util.ArrayList;
ShadowAlertDialogCompat.class,
ShadowBluetoothAdapter.class,
})
-public class CallsAndAlarmsDialogFragmentTest {
+public class AudioSharingCallAudioDialogFragmentTest {
@Rule public final MockitoRule mocks = MockitoJUnit.rule();
@Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
@@ -64,7 +64,7 @@ public class CallsAndAlarmsDialogFragmentTest {
new AudioSharingDeviceItem(TEST_DEVICE_NAME2, /* groupId= */ 1, /* isActive= */ true);
private Fragment mParent;
- private CallsAndAlarmsDialogFragment mFragment;
+ private AudioSharingCallAudioDialogFragment mFragment;
private ShadowBluetoothAdapter mShadowBluetoothAdapter;
@Before
@@ -76,7 +76,7 @@ public class CallsAndAlarmsDialogFragmentTest {
BluetoothStatusCodes.FEATURE_SUPPORTED);
mShadowBluetoothAdapter.setIsLeAudioBroadcastAssistantSupported(
BluetoothStatusCodes.FEATURE_SUPPORTED);
- mFragment = new CallsAndAlarmsDialogFragment();
+ mFragment = new AudioSharingCallAudioDialogFragment();
mParent = new Fragment();
FragmentController.setupFragment(
mParent, FragmentActivity.class, /* containerViewId= */ 0, /* bundle= */ null);
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/CallsAndAlarmsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingCallAudioPreferenceControllerTest.java
similarity index 98%
rename from tests/robotests/src/com/android/settings/connecteddevice/audiosharing/CallsAndAlarmsPreferenceControllerTest.java
rename to tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingCallAudioPreferenceControllerTest.java
index 614cb5ba3b9..bdfc71fed0e 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/CallsAndAlarmsPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingCallAudioPreferenceControllerTest.java
@@ -88,7 +88,7 @@ import java.util.List;
ShadowBluetoothUtils.class,
ShadowThreadUtils.class,
})
-public class CallsAndAlarmsPreferenceControllerTest {
+public class AudioSharingCallAudioPreferenceControllerTest {
private static final String PREF_KEY = "calls_and_alarms";
private static final String TEST_DEVICE_NAME1 = "test1";
private static final String TEST_DEVICE_NAME2 = "test2";
@@ -118,7 +118,7 @@ public class CallsAndAlarmsPreferenceControllerTest {
@Mock private CachedBluetoothDevice mCachedDevice3;
@Mock private BluetoothLeBroadcastReceiveState mState;
@Mock private ContentResolver mContentResolver;
- private CallsAndAlarmsPreferenceController mController;
+ private AudioSharingCallAudioPreferenceController mController;
@Spy private ContentObserver mContentObserver;
private ShadowBluetoothAdapter mShadowBluetoothAdapter;
private LocalBluetoothManager mBtManager;
@@ -151,7 +151,7 @@ public class CallsAndAlarmsPreferenceControllerTest {
bisSyncState.add(1L);
when(mState.getBisSyncState()).thenReturn(bisSyncState);
when(mContext.getContentResolver()).thenReturn(mContentResolver);
- mController = new CallsAndAlarmsPreferenceController(mContext);
+ mController = new AudioSharingCallAudioPreferenceController(mContext);
mController.init(null);
mContentObserver = mController.getSettingsObserver();
mPreference = new Preference(mContext);
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/db/AppUsageEventEntityTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/db/AppUsageEventEntityTest.java
index eb72b963e0b..dc9b51d20d1 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/db/AppUsageEventEntityTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/db/AppUsageEventEntityTest.java
@@ -27,7 +27,7 @@ import org.robolectric.RobolectricTestRunner;
public final class AppUsageEventEntityTest {
@Test
public void testBuilder_returnsExpectedResult() {
- final long uid = 101L;
+ final int uid = 101;
final long userId = 1001L;
final long timestamp = 10001L;
final int appUsageEventType = 1;
diff --git a/tests/robotests/src/com/android/settings/network/telephony/AutoDataSwitchPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/telephony/AutoDataSwitchPreferenceControllerTest.java
index 29592cf9189..8db4681784e 100644
--- a/tests/robotests/src/com/android/settings/network/telephony/AutoDataSwitchPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/network/telephony/AutoDataSwitchPreferenceControllerTest.java
@@ -85,7 +85,7 @@ public class AutoDataSwitchPreferenceControllerTest {
return true;
}
};
- mController.init(SUB_ID_1);
+ mController.init(SUB_ID_1, null);
}
@Test
diff --git a/tests/robotests/src/com/android/settings/testutils/BatteryTestUtils.java b/tests/robotests/src/com/android/settings/testutils/BatteryTestUtils.java
index 915231f2573..10b17a7b862 100644
--- a/tests/robotests/src/com/android/settings/testutils/BatteryTestUtils.java
+++ b/tests/robotests/src/com/android/settings/testutils/BatteryTestUtils.java
@@ -169,7 +169,7 @@ public class BatteryTestUtils {
Context context, long userId, long timestamp, String packageName, boolean multiple) {
final AppUsageEventEntity entity =
new AppUsageEventEntity(
- /* uid= */ 101L,
+ /* uid= */ 101,
userId,
timestamp,
/* appUsageEventType= */ 2,
diff --git a/tests/spa_unit/src/com/android/settings/network/telephony/SubscriptionRepositoryTest.kt b/tests/spa_unit/src/com/android/settings/network/telephony/SubscriptionRepositoryTest.kt
index b2ee018faf0..e233fa428a5 100644
--- a/tests/spa_unit/src/com/android/settings/network/telephony/SubscriptionRepositoryTest.kt
+++ b/tests/spa_unit/src/com/android/settings/network/telephony/SubscriptionRepositoryTest.kt
@@ -115,6 +115,27 @@ class SubscriptionRepositoryTest {
.containsExactly(SIM_SLOT_INDEX_0, SIM_SLOT_INDEX_1).inOrder()
}
+ @Test
+ fun getSelectableSubscriptionInfoList_oneNotInSlot_inSlotSortedFirst() {
+ mockSubscriptionManager.stub {
+ on { getAvailableSubscriptionInfoList() } doReturn listOf(
+ SubscriptionInfo.Builder().apply {
+ setSimSlotIndex(SubscriptionManager.INVALID_SIM_SLOT_INDEX)
+ setId(SUB_ID_3_NOT_IN_SLOT)
+ }.build(),
+ SubscriptionInfo.Builder().apply {
+ setSimSlotIndex(SIM_SLOT_INDEX_1)
+ setId(SUB_ID_IN_SLOT_1)
+ }.build(),
+ )
+ }
+
+ val subInfos = context.getSelectableSubscriptionInfoList()
+
+ assertThat(subInfos.map { it.simSlotIndex })
+ .containsExactly(SIM_SLOT_INDEX_1, SubscriptionManager.INVALID_SIM_SLOT_INDEX).inOrder()
+ }
+
@Test
fun getSelectableSubscriptionInfoList_sameGroupAndOneHasSlot_returnTheOneWithSimSlotIndex() {
mockSubscriptionManager.stub {
diff --git a/tests/spa_unit/src/com/android/settings/network/telephony/ims/ImsMmTelRepositoryTest.kt b/tests/spa_unit/src/com/android/settings/network/telephony/ims/ImsMmTelRepositoryTest.kt
index f198660e5da..04cba732b73 100644
--- a/tests/spa_unit/src/com/android/settings/network/telephony/ims/ImsMmTelRepositoryTest.kt
+++ b/tests/spa_unit/src/com/android/settings/network/telephony/ims/ImsMmTelRepositoryTest.kt
@@ -43,6 +43,7 @@ import org.mockito.kotlin.doThrow
import org.mockito.kotlin.eq
import org.mockito.kotlin.mock
import org.mockito.kotlin.stub
+import org.mockito.kotlin.verify
@RunWith(AndroidJUnit4::class)
class ImsMmTelRepositoryTest {
@@ -155,6 +156,13 @@ class ImsMmTelRepositoryTest {
assertThat(isSupported).isTrue()
}
+ @Test
+ fun setCrossSimCallingEnabled() = runBlocking {
+ repository.setCrossSimCallingEnabled(true)
+
+ verify(mockImsMmTelManager).setCrossSimCallingEnabled(true)
+ }
+
private companion object {
const val SUB_ID = 1
const val CAPABILITY = MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE
diff --git a/tests/spa_unit/src/com/android/settings/network/telephony/wificalling/WifiCallingRepositoryTest.kt b/tests/spa_unit/src/com/android/settings/network/telephony/wificalling/WifiCallingRepositoryTest.kt
index 1f3acc29afb..0144f6669cb 100644
--- a/tests/spa_unit/src/com/android/settings/network/telephony/wificalling/WifiCallingRepositoryTest.kt
+++ b/tests/spa_unit/src/com/android/settings/network/telephony/wificalling/WifiCallingRepositoryTest.kt
@@ -17,15 +17,18 @@
package com.android.settings.network.telephony.wificalling
import android.content.Context
+import android.telephony.AccessNetworkConstants
import android.telephony.CarrierConfigManager
import android.telephony.CarrierConfigManager.KEY_USE_WFC_HOME_NETWORK_MODE_IN_ROAMING_NETWORK_BOOL
import android.telephony.TelephonyManager
import android.telephony.ims.ImsMmTelManager
+import android.telephony.ims.feature.MmTelFeature
import androidx.core.os.persistableBundleOf
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.settings.network.telephony.ims.ImsMmTelRepository
import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.runBlocking
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.kotlin.any
@@ -98,6 +101,22 @@ class WifiCallingRepositoryTest {
assertThat(wiFiCallingMode).isEqualTo(ImsMmTelManager.WIFI_MODE_WIFI_PREFERRED)
}
+ @Test
+ fun isWifiCallingSupported() = runBlocking {
+ mockImsMmTelRepository.stub {
+ onBlocking {
+ isSupported(
+ capability = MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE,
+ transportType = AccessNetworkConstants.TRANSPORT_TYPE_WLAN,
+ )
+ } doReturn true
+ }
+
+ val isSupported = repository.isWifiCallingSupported()
+
+ assertThat(isSupported).isTrue()
+ }
+
private fun mockUseWfcHomeModeForRoaming(config: Boolean) {
mockCarrierConfigManager.stub {
on {