diff --git a/res/values/strings.xml b/res/values/strings.xml
index 075056db64e..50556de6e0b 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -7930,16 +7930,28 @@
Select activation type
-
+
Time
-
+
Ex. \"9:30 – 5:00 PM\"
-
+
Calendar
-
+
Ex. \"Personal calendar\"
+
+ ON
+
+
+ %1$s • %2$s
+
+
+ Tap to set up
+
+
+ Paused
+
Limit interruptions
diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingNamePreference.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingNamePreference.java
index 0bb6b607041..bfccdc4c672 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingNamePreference.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingNamePreference.java
@@ -95,14 +95,14 @@ public class AudioSharingNamePreference extends ValidatedEditTextPreference {
}
private void configureInvisibleStateForQrCodeIcon(ImageButton shareButton, View divider) {
- divider.setVisibility(View.INVISIBLE);
- shareButton.setVisibility(View.INVISIBLE);
+ divider.setVisibility(View.GONE);
+ shareButton.setVisibility(View.GONE);
shareButton.setOnClickListener(null);
}
private void launchAudioSharingQrCodeFragment() {
new SubSettingLauncher(getContext())
- .setTitleText(getContext().getString(R.string.audio_streams_qr_code_page_title))
+ .setTitleRes(R.string.audio_streams_qr_code_page_title)
.setDestination(AudioStreamsQrCodeFragment.class.getName())
.setSourceMetricsCategory(SettingsEnums.AUDIO_SHARING_SETTINGS)
.launch();
diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingNamePreferenceController.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingNamePreferenceController.java
index 24b8f20cf51..894ba487014 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingNamePreferenceController.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingNamePreferenceController.java
@@ -26,6 +26,7 @@ import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
import androidx.lifecycle.DefaultLifecycleObserver;
import androidx.lifecycle.LifecycleOwner;
import androidx.preference.Preference;
@@ -56,7 +57,8 @@ public class AudioSharingNamePreferenceController extends BasePreferenceControll
private static final boolean DEBUG = BluetoothUtils.D;
private static final String PREF_KEY = "audio_sharing_stream_name";
- private final BluetoothLeBroadcast.Callback mBroadcastCallback =
+ @VisibleForTesting
+ final BluetoothLeBroadcast.Callback mBroadcastCallback =
new BluetoothLeBroadcast.Callback() {
@Override
public void onBroadcastMetadataChanged(
diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingPasswordPreferenceController.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingPasswordPreferenceController.java
index 258cf3be843..14930e11a6a 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingPasswordPreferenceController.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingPasswordPreferenceController.java
@@ -19,12 +19,19 @@ package com.android.settings.connecteddevice.audiosharing;
import static com.android.settings.connecteddevice.audiosharing.AudioSharingUtils.isBroadcasting;
import android.app.settings.SettingsEnums;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.SharedPreferences;
+import android.database.ContentObserver;
+import android.os.Handler;
+import android.os.Looper;
+import android.provider.Settings;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import androidx.lifecycle.DefaultLifecycleObserver;
+import androidx.lifecycle.LifecycleOwner;
import androidx.preference.PreferenceScreen;
import com.android.settings.R;
@@ -41,15 +48,19 @@ import java.nio.charset.StandardCharsets;
public class AudioSharingPasswordPreferenceController extends BasePreferenceController
implements ValidatedEditTextPreference.Validator,
- AudioSharingPasswordPreference.OnDialogEventListener {
-
+ AudioSharingPasswordPreference.OnDialogEventListener,
+ DefaultLifecycleObserver {
private static final String TAG = "AudioSharingPasswordPreferenceController";
private static final String PREF_KEY = "audio_sharing_stream_password";
private static final String SHARED_PREF_NAME = "audio_sharing_settings";
private static final String SHARED_PREF_KEY = "default_password";
+ @Nullable private final ContentResolver mContentResolver;
+ @Nullable private final SharedPreferences mSharedPref;
@Nullable private final LocalBluetoothManager mBtManager;
@Nullable private final LocalBluetoothLeBroadcast mBroadcast;
@Nullable private AudioSharingPasswordPreference mPreference;
+ private final ContentObserver mSettingsObserver;
+ private final SharedPreferences.OnSharedPreferenceChangeListener mSharedPrefChangeListener;
private final AudioSharingPasswordValidator mAudioSharingPasswordValidator;
private final MetricsFeatureProvider mMetricsFeatureProvider;
@@ -61,9 +72,44 @@ public class AudioSharingPasswordPreferenceController extends BasePreferenceCont
? mBtManager.getProfileManager().getLeAudioBroadcastProfile()
: null;
mAudioSharingPasswordValidator = new AudioSharingPasswordValidator();
+ mContentResolver = context.getContentResolver();
+ mSettingsObserver = new PasswordSettingsObserver();
+ mSharedPref = context.getSharedPreferences(SHARED_PREF_NAME, Context.MODE_PRIVATE);
+ mSharedPrefChangeListener = new PasswordSharedPrefChangeListener();
mMetricsFeatureProvider = FeatureFactory.getFeatureFactory().getMetricsFeatureProvider();
}
+ @Override
+ public void onStart(@NonNull LifecycleOwner owner) {
+ if (!isAvailable()) {
+ Log.d(TAG, "Feature is not available.");
+ return;
+ }
+ if (mContentResolver != null) {
+ mContentResolver.registerContentObserver(
+ Settings.Secure.getUriFor(Settings.Secure.BLUETOOTH_LE_BROADCAST_CODE),
+ false,
+ mSettingsObserver);
+ }
+ if (mSharedPref != null) {
+ mSharedPref.registerOnSharedPreferenceChangeListener(mSharedPrefChangeListener);
+ }
+ }
+
+ @Override
+ public void onStop(@NonNull LifecycleOwner owner) {
+ if (!isAvailable()) {
+ Log.d(TAG, "Feature is not available.");
+ return;
+ }
+ if (mContentResolver != null) {
+ mContentResolver.unregisterContentObserver(mSettingsObserver);
+ }
+ if (mSharedPref != null) {
+ mSharedPref.unregisterOnSharedPreferenceChangeListener(mSharedPrefChangeListener);
+ }
+ }
+
@Override
public int getAvailabilityStatus() {
return AudioSharingUtils.isFeatureEnabled() ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
@@ -125,7 +171,6 @@ public class AudioSharingPasswordPreferenceController extends BasePreferenceCont
persistDefaultPassword(mContext, password);
mBroadcast.setBroadcastCode(
isPublicBroadcast ? new byte[0] : password.getBytes());
- updatePreference();
mMetricsFeatureProvider.action(
mContext,
SettingsEnums.ACTION_AUDIO_STREAM_PASSWORD_UPDATED,
@@ -164,32 +209,52 @@ public class AudioSharingPasswordPreferenceController extends BasePreferenceCont
});
}
- private static void persistDefaultPassword(Context context, String defaultPassword) {
+ private class PasswordSettingsObserver extends ContentObserver {
+ PasswordSettingsObserver() {
+ super(new Handler(Looper.getMainLooper()));
+ }
+
+ @Override
+ public void onChange(boolean selfChange) {
+ Log.d(TAG, "onChange, broadcast password has been changed");
+ updatePreference();
+ }
+ }
+
+ private class PasswordSharedPrefChangeListener
+ implements SharedPreferences.OnSharedPreferenceChangeListener {
+ @Override
+ public void onSharedPreferenceChanged(
+ SharedPreferences sharedPreferences, @Nullable String key) {
+ if (!SHARED_PREF_KEY.equals(key)) {
+ return;
+ }
+ Log.d(TAG, "onSharedPreferenceChanged, default password has been changed");
+ updatePreference();
+ }
+ }
+
+ private void persistDefaultPassword(Context context, String defaultPassword) {
if (getDefaultPassword(context).equals(defaultPassword)) {
return;
}
-
- SharedPreferences sharedPref =
- context.getSharedPreferences(SHARED_PREF_NAME, Context.MODE_PRIVATE);
- if (sharedPref == null) {
+ if (mSharedPref == null) {
Log.w(TAG, "persistDefaultPassword(): sharedPref is empty!");
return;
}
- SharedPreferences.Editor editor = sharedPref.edit();
+ SharedPreferences.Editor editor = mSharedPref.edit();
editor.putString(SHARED_PREF_KEY, defaultPassword);
editor.apply();
}
- private static String getDefaultPassword(Context context) {
- SharedPreferences sharedPref =
- context.getSharedPreferences(SHARED_PREF_NAME, Context.MODE_PRIVATE);
- if (sharedPref == null) {
+ private String getDefaultPassword(Context context) {
+ if (mSharedPref == null) {
Log.w(TAG, "getDefaultPassword(): sharedPref is empty!");
return "";
}
- String value = sharedPref.getString(SHARED_PREF_KEY, "");
+ String value = mSharedPref.getString(SHARED_PREF_KEY, "");
if (value != null && value.isEmpty()) {
Log.w(TAG, "getDefaultPassword(): default password is empty!");
}
diff --git a/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AddSourceWaitForResponseState.java b/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AddSourceWaitForResponseState.java
index 24a28dd0602..7be01a20235 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AddSourceWaitForResponseState.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AddSourceWaitForResponseState.java
@@ -36,7 +36,8 @@ class AddSourceWaitForResponseState extends AudioStreamStateHandler {
@Nullable private static AddSourceWaitForResponseState sInstance = null;
- private AddSourceWaitForResponseState() {}
+ @VisibleForTesting
+ AddSourceWaitForResponseState() {}
static AddSourceWaitForResponseState getInstance() {
if (sInstance == null) {
diff --git a/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamStateHandler.java b/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamStateHandler.java
index b0c5b6baebf..4bb84751b36 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamStateHandler.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamStateHandler.java
@@ -35,10 +35,10 @@ class AudioStreamStateHandler {
private static final boolean DEBUG = BluetoothUtils.D;
@VisibleForTesting static final int EMPTY_STRING_RES = 0;
- final AudioStreamsRepository mAudioStreamsRepository = AudioStreamsRepository.getInstance();
final Handler mHandler = new Handler(Looper.getMainLooper());
final MetricsFeatureProvider mMetricsFeatureProvider =
FeatureFactory.getFeatureFactory().getMetricsFeatureProvider();
+ AudioStreamsRepository mAudioStreamsRepository = AudioStreamsRepository.getInstance();
AudioStreamStateHandler() {}
@@ -112,4 +112,9 @@ class AudioStreamStateHandler {
AudioStreamsProgressCategoryController.AudioStreamState getStateEnum() {
return AudioStreamsProgressCategoryController.AudioStreamState.UNKNOWN;
}
+
+ @VisibleForTesting
+ void setAudioStreamsRepositoryForTesting(AudioStreamsRepository repository) {
+ mAudioStreamsRepository = repository;
+ }
}
diff --git a/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamsActiveDeviceSummaryUpdater.java b/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamsActiveDeviceSummaryUpdater.java
index ab22b0702bc..47ee440694f 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamsActiveDeviceSummaryUpdater.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamsActiveDeviceSummaryUpdater.java
@@ -16,24 +16,22 @@
package com.android.settings.connecteddevice.audiosharing.audiostreams;
+import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.text.TextUtils;
-import android.util.Log;
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.settings.R;
import com.android.settings.bluetooth.Utils;
import com.android.settingslib.bluetooth.BluetoothCallback;
-import com.android.settingslib.bluetooth.BluetoothUtils;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.utils.ThreadUtils;
public class AudioStreamsActiveDeviceSummaryUpdater implements BluetoothCallback {
- private static final String TAG = "AudioStreamsActiveDeviceSummaryUpdater";
- private static final boolean DEBUG = BluetoothUtils.D;
private final LocalBluetoothManager mBluetoothManager;
private Context mContext;
@Nullable private String mSummary;
@@ -47,17 +45,20 @@ public class AudioStreamsActiveDeviceSummaryUpdater implements BluetoothCallback
}
@Override
- public void onActiveDeviceChanged(
- @Nullable CachedBluetoothDevice activeDevice, int bluetoothProfile) {
- if (DEBUG) {
- Log.d(
- TAG,
- "onActiveDeviceChanged() with activeDevice : "
- + (activeDevice == null ? "null" : activeDevice.getAddress())
- + " on profile : "
- + bluetoothProfile);
+ public void onBluetoothStateChanged(@AdapterState int bluetoothState) {
+ if (bluetoothState == BluetoothAdapter.STATE_OFF) {
+ notifyChangeIfNeeded();
}
- if (bluetoothProfile == BluetoothProfile.LE_AUDIO) {
+ }
+
+ @Override
+ public void onProfileConnectionStateChanged(
+ @NonNull CachedBluetoothDevice cachedDevice,
+ @ConnectionState int state,
+ int bluetoothProfile) {
+ if (bluetoothProfile == BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT
+ && (state == BluetoothAdapter.STATE_CONNECTED
+ || state == BluetoothAdapter.STATE_DISCONNECTED)) {
notifyChangeIfNeeded();
}
}
diff --git a/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamsCategoryController.java b/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamsCategoryController.java
index 3174ace8520..0107c6ee49b 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamsCategoryController.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamsCategoryController.java
@@ -16,12 +16,12 @@
package com.android.settings.connecteddevice.audiosharing.audiostreams;
+import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.util.Log;
import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
import androidx.lifecycle.LifecycleOwner;
import com.android.settings.bluetooth.Utils;
@@ -44,9 +44,13 @@ public class AudioStreamsCategoryController extends AudioSharingBasePreferenceCo
private final BluetoothCallback mBluetoothCallback =
new BluetoothCallback() {
@Override
- public void onActiveDeviceChanged(
- @Nullable CachedBluetoothDevice activeDevice, int bluetoothProfile) {
- if (bluetoothProfile == BluetoothProfile.LE_AUDIO) {
+ public void onProfileConnectionStateChanged(
+ @NonNull CachedBluetoothDevice cachedDevice,
+ @ConnectionState int state,
+ int bluetoothProfile) {
+ if (bluetoothProfile == BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT
+ && (state == BluetoothAdapter.STATE_CONNECTED
+ || state == BluetoothAdapter.STATE_DISCONNECTED)) {
updateVisibility();
}
}
diff --git a/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamsHelper.java b/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamsHelper.java
index 775186a859e..6e335a0971c 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamsHelper.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamsHelper.java
@@ -71,7 +71,8 @@ public class AudioStreamsHelper {
*
* @param source The LE broadcast metadata representing the audio source.
*/
- void addSource(BluetoothLeBroadcastMetadata source) {
+ @VisibleForTesting
+ public void addSource(BluetoothLeBroadcastMetadata source) {
if (mLeBroadcastAssistant == null) {
Log.w(TAG, "addSource(): LeBroadcastAssistant is null!");
return;
@@ -97,7 +98,8 @@ public class AudioStreamsHelper {
}
/** Removes sources from LE broadcasts associated for all active sinks based on broadcast Id. */
- void removeSource(int broadcastId) {
+ @VisibleForTesting
+ public void removeSource(int broadcastId) {
if (mLeBroadcastAssistant == null) {
Log.w(TAG, "removeSource(): LeBroadcastAssistant is null!");
return;
diff --git a/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamsProgressCategoryCallback.java b/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamsProgressCategoryCallback.java
index cb3a0daac2f..3370d8dbfd5 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamsProgressCategoryCallback.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamsProgressCategoryCallback.java
@@ -19,7 +19,6 @@ package com.android.settings.connecteddevice.audiosharing.audiostreams;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothLeBroadcastMetadata;
import android.bluetooth.BluetoothLeBroadcastReceiveState;
-import android.util.Log;
public class AudioStreamsProgressCategoryCallback extends AudioStreamsBroadcastAssistantCallback {
private static final String TAG = "AudioStreamsProgressCategoryCallback";
@@ -53,10 +52,6 @@ public class AudioStreamsProgressCategoryCallback extends AudioStreamsBroadcastA
@Override
public void onSearchStarted(int reason) {
super.onSearchStarted(reason);
- if (mCategoryController == null) {
- Log.w(TAG, "onSearchStarted() : mCategoryController is null!");
- return;
- }
mCategoryController.setScanning(true);
}
@@ -69,10 +64,6 @@ public class AudioStreamsProgressCategoryCallback extends AudioStreamsBroadcastA
@Override
public void onSearchStopped(int reason) {
super.onSearchStopped(reason);
- if (mCategoryController == null) {
- Log.w(TAG, "onSearchStopped() : mCategoryController is null!");
- return;
- }
mCategoryController.setScanning(false);
}
@@ -86,10 +77,6 @@ public class AudioStreamsProgressCategoryCallback extends AudioStreamsBroadcastA
@Override
public void onSourceFound(BluetoothLeBroadcastMetadata source) {
super.onSourceFound(source);
- if (mCategoryController == null) {
- Log.w(TAG, "onSourceFound() : mCategoryController is null!");
- return;
- }
mCategoryController.handleSourceFound(source);
}
diff --git a/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamsProgressCategoryController.java b/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamsProgressCategoryController.java
index 890879e817c..9bbf135285c 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamsProgressCategoryController.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamsProgressCategoryController.java
@@ -20,6 +20,7 @@ import static java.util.Collections.emptyList;
import android.app.AlertDialog;
import android.app.settings.SettingsEnums;
+import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothLeBroadcastMetadata;
import android.bluetooth.BluetoothLeBroadcastReceiveState;
import android.bluetooth.BluetoothProfile;
@@ -27,10 +28,12 @@ import android.content.Context;
import android.util.Log;
import androidx.annotation.NonNull;
+import androidx.fragment.app.Fragment;
import androidx.lifecycle.DefaultLifecycleObserver;
import androidx.lifecycle.LifecycleOwner;
import androidx.preference.PreferenceScreen;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.settings.R;
import com.android.settings.bluetooth.Utils;
import com.android.settings.connecteddevice.ConnectedDeviceDashboardFragment;
@@ -55,13 +58,35 @@ public class AudioStreamsProgressCategoryController extends BasePreferenceContro
implements DefaultLifecycleObserver {
private static final String TAG = "AudioStreamsProgressCategoryController";
private static final boolean DEBUG = BluetoothUtils.D;
- private static final int UNSET_BROADCAST_ID = -1;
- private final BluetoothCallback mBluetoothCallback =
+ @VisibleForTesting static final int UNSET_BROADCAST_ID = -1;
+
+ @VisibleForTesting
+ final BluetoothCallback mBluetoothCallback =
new BluetoothCallback() {
@Override
- public void onActiveDeviceChanged(
- @Nullable CachedBluetoothDevice activeDevice, int bluetoothProfile) {
- if (bluetoothProfile == BluetoothProfile.LE_AUDIO) {
+ public void onBluetoothStateChanged(@AdapterState int bluetoothState) {
+ Log.d(TAG, "onBluetoothStateChanged() with bluetoothState : " + bluetoothState);
+ if (bluetoothState == BluetoothAdapter.STATE_OFF) {
+ mExecutor.execute(() -> init());
+ }
+ }
+
+ @Override
+ public void onProfileConnectionStateChanged(
+ @NonNull CachedBluetoothDevice cachedDevice,
+ @ConnectionState int state,
+ int bluetoothProfile) {
+ Log.d(
+ TAG,
+ "onProfileConnectionStateChanged() with cachedDevice : "
+ + cachedDevice.getAddress()
+ + " with state : "
+ + state
+ + " on profile : "
+ + bluetoothProfile);
+ if (bluetoothProfile == BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT
+ && (state == BluetoothAdapter.STATE_CONNECTED
+ || state == BluetoothAdapter.STATE_DISCONNECTED)) {
mExecutor.execute(() -> init());
}
}
@@ -92,7 +117,7 @@ public class AudioStreamsProgressCategoryController extends BasePreferenceContro
SOURCE_ADDED,
}
- private final Executor mExecutor;
+ @VisibleForTesting Executor mExecutor;
private final AudioStreamsProgressCategoryCallback mBroadcastAssistantCallback;
private final AudioStreamsHelper mAudioStreamsHelper;
private final MediaControlHelper mMediaControlHelper;
@@ -103,7 +128,7 @@ public class AudioStreamsProgressCategoryController extends BasePreferenceContro
private @Nullable BluetoothLeBroadcastMetadata mSourceFromQrCode;
private SourceOriginForLogging mSourceFromQrCodeOriginForLogging;
@Nullable private AudioStreamsProgressCategoryPreference mCategoryPreference;
- @Nullable private AudioStreamsDashboardFragment mFragment;
+ @Nullable private Fragment mFragment;
public AudioStreamsProgressCategoryController(Context context, String preferenceKey) {
super(context, preferenceKey);
@@ -142,12 +167,12 @@ public class AudioStreamsProgressCategoryController extends BasePreferenceContro
mExecutor.execute(this::stopScanning);
}
- void setFragment(AudioStreamsDashboardFragment fragment) {
+ void setFragment(Fragment fragment) {
mFragment = fragment;
}
@Nullable
- AudioStreamsDashboardFragment getFragment() {
+ Fragment getFragment() {
return mFragment;
}
@@ -546,7 +571,8 @@ public class AudioStreamsProgressCategoryController extends BasePreferenceContro
return preference;
}
- private void moveToState(AudioStreamPreference preference, AudioStreamState state) {
+ @VisibleForTesting
+ void moveToState(AudioStreamPreference preference, AudioStreamState state) {
AudioStreamStateHandler stateHandler =
switch (state) {
case SYNCED -> SyncedState.getInstance();
diff --git a/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamsScanQrCodeController.java b/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamsScanQrCodeController.java
index 5f50be72790..d0d82fbc678 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamsScanQrCodeController.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamsScanQrCodeController.java
@@ -16,6 +16,7 @@
package com.android.settings.connecteddevice.audiosharing.audiostreams;
+import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.util.Log;
@@ -47,9 +48,13 @@ public class AudioStreamsScanQrCodeController extends BasePreferenceController
final BluetoothCallback mBluetoothCallback =
new BluetoothCallback() {
@Override
- public void onActiveDeviceChanged(
- @Nullable CachedBluetoothDevice activeDevice, int bluetoothProfile) {
- if (bluetoothProfile == BluetoothProfile.LE_AUDIO) {
+ public void onProfileConnectionStateChanged(
+ @NonNull CachedBluetoothDevice cachedDevice,
+ @ConnectionState int state,
+ int bluetoothProfile) {
+ if (bluetoothProfile == BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT
+ && (state == BluetoothAdapter.STATE_CONNECTED
+ || state == BluetoothAdapter.STATE_DISCONNECTED)) {
updateVisibility();
}
}
diff --git a/src/com/android/settings/connecteddevice/audiosharing/audiostreams/SourceAddedState.java b/src/com/android/settings/connecteddevice/audiosharing/audiostreams/SourceAddedState.java
index ee84429663a..88393ab1b67 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/audiostreams/SourceAddedState.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/audiostreams/SourceAddedState.java
@@ -25,6 +25,7 @@ import androidx.preference.Preference;
import com.android.settings.R;
import com.android.settings.core.SubSettingLauncher;
+import com.android.settings.dashboard.DashboardFragment;
class SourceAddedState extends AudioStreamStateHandler {
@VisibleForTesting
@@ -32,7 +33,8 @@ class SourceAddedState extends AudioStreamStateHandler {
@Nullable private static SourceAddedState sInstance = null;
- private SourceAddedState() {}
+ @VisibleForTesting
+ SourceAddedState() {}
static SourceAddedState getInstance() {
if (sInstance == null) {
@@ -80,13 +82,13 @@ class SourceAddedState extends AudioStreamStateHandler {
AudioStreamDetailsFragment.BROADCAST_ID_ARG, p.getAudioStreamBroadcastId());
new SubSettingLauncher(p.getContext())
- .setTitleText(
- p.getContext().getString(R.string.audio_streams_detail_page_title))
+ .setTitleRes(R.string.audio_streams_detail_page_title)
.setDestination(AudioStreamDetailsFragment.class.getName())
.setSourceMetricsCategory(
- controller.getFragment() == null
+ !(controller.getFragment() instanceof DashboardFragment)
? SettingsEnums.PAGE_UNKNOWN
- : controller.getFragment().getMetricsCategory())
+ : ((DashboardFragment) controller.getFragment())
+ .getMetricsCategory())
.setArguments(broadcast)
.launch();
return true;
diff --git a/src/com/android/settings/connecteddevice/audiosharing/audiostreams/WaitForSyncState.java b/src/com/android/settings/connecteddevice/audiosharing/audiostreams/WaitForSyncState.java
index 55f61fdd0e2..9689b263a47 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/audiostreams/WaitForSyncState.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/audiostreams/WaitForSyncState.java
@@ -39,7 +39,8 @@ class WaitForSyncState extends AudioStreamStateHandler {
@Nullable private static WaitForSyncState sInstance = null;
- private WaitForSyncState() {}
+ @VisibleForTesting
+ WaitForSyncState() {}
static WaitForSyncState getInstance() {
if (sInstance == null) {
@@ -114,7 +115,8 @@ class WaitForSyncState extends AudioStreamStateHandler {
SettingsEnums.DIALOG_AUDIO_STREAM_MAIN_WAIT_FOR_SYNC_TIMEOUT);
}
- private void launchQrCodeScanFragment(Context context, Fragment fragment) {
+ @VisibleForTesting
+ void launchQrCodeScanFragment(Context context, Fragment fragment) {
new SubSettingLauncher(context)
.setTitleRes(R.string.audio_streams_main_page_scan_qr_code_title)
.setDestination(AudioStreamsQrCodeScanFragment.class.getName())
diff --git a/src/com/android/settings/fuelgauge/batteryusage/BatteryDiffData.java b/src/com/android/settings/fuelgauge/batteryusage/BatteryDiffData.java
index 7b5cd9f9e00..b5d50994ed7 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/BatteryDiffData.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/BatteryDiffData.java
@@ -99,7 +99,8 @@ public class BatteryDiffData {
return mScreenOnTime;
}
- List getAppDiffEntryList() {
+ /** Gets the {@link BatteryDiffEntry} list for apps. */
+ public List getAppDiffEntryList() {
return mAppEntries;
}
@@ -298,8 +299,7 @@ public class BatteryDiffData {
* Sets total consume power, and adjusts the percentages to ensure the total round percentage
* could be 100%, and then sorts entries based on the sorting key.
*/
- @VisibleForTesting
- static void processAndSortEntries(final List batteryDiffEntries) {
+ public static void processAndSortEntries(final List batteryDiffEntries) {
if (batteryDiffEntries.isEmpty()) {
return;
}
diff --git a/src/com/android/settings/network/telephony/wificalling/WifiCallingRepository.kt b/src/com/android/settings/network/telephony/wificalling/WifiCallingRepository.kt
index a5d4ba832ab..b5cdedae96c 100644
--- a/src/com/android/settings/network/telephony/wificalling/WifiCallingRepository.kt
+++ b/src/com/android/settings/network/telephony/wificalling/WifiCallingRepository.kt
@@ -21,14 +21,16 @@ 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.SubscriptionManager
-import android.telephony.TelephonyManager
import android.telephony.ims.ImsMmTelManager.WiFiCallingMode
import android.telephony.ims.feature.MmTelFeature
import android.telephony.ims.stub.ImsRegistrationImplBase
+import androidx.lifecycle.LifecycleOwner
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 com.android.settings.network.telephony.telephonyManager
+import com.android.settingslib.spa.framework.util.collectLatestWithLifecycle
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
@@ -38,13 +40,19 @@ import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.withContext
-class WifiCallingRepository(
+interface IWifiCallingRepository {
+ /** TODO: Move this to UI layer, when UI layer migrated to Kotlin. */
+ fun collectIsWifiCallingReadyFlow(lifecycleOwner: LifecycleOwner, action: (Boolean) -> Unit)
+}
+
+class WifiCallingRepository
+@JvmOverloads
+constructor(
private val context: Context,
private val subId: Int,
private val imsMmTelRepository: ImsMmTelRepository = ImsMmTelRepositoryImpl(context, subId)
-) {
- private val telephonyManager = context.getSystemService(TelephonyManager::class.java)!!
- .createForSubscriptionId(subId)
+) : IWifiCallingRepository {
+ private val telephonyManager = context.telephonyManager(subId)
private val carrierConfigManager = context.getSystemService(CarrierConfigManager::class.java)!!
@@ -59,6 +67,14 @@ class WifiCallingRepository(
.getConfigForSubId(subId, KEY_USE_WFC_HOME_NETWORK_MODE_IN_ROAMING_NETWORK_BOOL)
.getBoolean(KEY_USE_WFC_HOME_NETWORK_MODE_IN_ROAMING_NETWORK_BOOL)
+ /** TODO: Move this to UI layer, when UI layer migrated to Kotlin. */
+ override fun collectIsWifiCallingReadyFlow(
+ lifecycleOwner: LifecycleOwner,
+ action: (Boolean) -> Unit,
+ ) {
+ wifiCallingReadyFlow().collectLatestWithLifecycle(lifecycleOwner, action = action)
+ }
+
@OptIn(ExperimentalCoroutinesApi::class)
fun wifiCallingReadyFlow(): Flow {
if (!SubscriptionManager.isValidSubscriptionId(subId)) return flowOf(false)
diff --git a/src/com/android/settings/notification/modes/IconUtil.java b/src/com/android/settings/notification/modes/IconUtil.java
index c6ecaa0a56d..1e653bf03fe 100644
--- a/src/com/android/settings/notification/modes/IconUtil.java
+++ b/src/com/android/settings/notification/modes/IconUtil.java
@@ -24,6 +24,7 @@ import android.graphics.drawable.LayerDrawable;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.OvalShape;
+import androidx.annotation.AttrRes;
import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;
@@ -32,10 +33,18 @@ import com.android.settingslib.Utils;
class IconUtil {
- static Drawable applyTint(@NonNull Context context, @NonNull Drawable icon) {
+ static Drawable applyNormalTint(@NonNull Context context, @NonNull Drawable icon) {
+ return applyTint(context, icon, android.R.attr.colorControlNormal);
+ }
+
+ static Drawable applyAccentTint(@NonNull Context context, @NonNull Drawable icon) {
+ return applyTint(context, icon, android.R.attr.colorAccent);
+ }
+
+ private static Drawable applyTint(@NonNull Context context, @NonNull Drawable icon,
+ @AttrRes int colorAttr) {
icon = icon.mutate();
- icon.setTintList(
- Utils.getColorAttr(context, android.R.attr.colorControlNormal));
+ icon.setTintList(Utils.getColorAttr(context, colorAttr));
return icon;
}
diff --git a/src/com/android/settings/notification/modes/ZenModeButtonPreferenceController.java b/src/com/android/settings/notification/modes/ZenModeButtonPreferenceController.java
index 79da24da57a..4a99b33749c 100644
--- a/src/com/android/settings/notification/modes/ZenModeButtonPreferenceController.java
+++ b/src/com/android/settings/notification/modes/ZenModeButtonPreferenceController.java
@@ -27,7 +27,7 @@ import com.android.settingslib.notification.modes.ZenMode;
import com.android.settingslib.notification.modes.ZenModesBackend;
import com.android.settingslib.widget.LayoutPreference;
-public class ZenModeButtonPreferenceController extends AbstractZenModePreferenceController {
+class ZenModeButtonPreferenceController extends AbstractZenModePreferenceController {
private Button mZenButton;
diff --git a/src/com/android/settings/notification/modes/ZenModeDisplayEffectPreferenceController.java b/src/com/android/settings/notification/modes/ZenModeDisplayEffectPreferenceController.java
index b42e5b8eed3..b0d395296e9 100644
--- a/src/com/android/settings/notification/modes/ZenModeDisplayEffectPreferenceController.java
+++ b/src/com/android/settings/notification/modes/ZenModeDisplayEffectPreferenceController.java
@@ -26,7 +26,7 @@ import androidx.preference.TwoStatePreference;
import com.android.settingslib.notification.modes.ZenMode;
import com.android.settingslib.notification.modes.ZenModesBackend;
-public class ZenModeDisplayEffectPreferenceController extends AbstractZenModePreferenceController
+class ZenModeDisplayEffectPreferenceController extends AbstractZenModePreferenceController
implements Preference.OnPreferenceChangeListener {
public ZenModeDisplayEffectPreferenceController(Context context, String key,
@@ -37,24 +37,20 @@ public class ZenModeDisplayEffectPreferenceController extends AbstractZenModePre
@Override
public void updateState(Preference preference, @NonNull ZenMode zenMode) {
TwoStatePreference pref = (TwoStatePreference) preference;
- ZenDeviceEffects effects = zenMode.getRule().getDeviceEffects();
- if (effects == null) {
- pref.setChecked(false);
- } else {
- switch (getPreferenceKey()) {
- case "effect_greyscale":
- pref.setChecked(effects.shouldDisplayGrayscale());
- break;
- case "effect_aod":
- pref.setChecked(effects.shouldSuppressAmbientDisplay());
- break;
- case "effect_wallpaper":
- pref.setChecked(effects.shouldDimWallpaper());
- break;
- case "effect_dark_theme":
- pref.setChecked(effects.shouldUseNightMode());
- break;
- }
+ ZenDeviceEffects effects = zenMode.getDeviceEffects();
+ switch (getPreferenceKey()) {
+ case "effect_greyscale":
+ pref.setChecked(effects.shouldDisplayGrayscale());
+ break;
+ case "effect_aod":
+ pref.setChecked(effects.shouldSuppressAmbientDisplay());
+ break;
+ case "effect_wallpaper":
+ pref.setChecked(effects.shouldDimWallpaper());
+ break;
+ case "effect_dark_theme":
+ pref.setChecked(effects.shouldUseNightMode());
+ break;
}
}
diff --git a/src/com/android/settings/notification/modes/ZenModeHeaderController.java b/src/com/android/settings/notification/modes/ZenModeHeaderController.java
index 857d07949aa..1845ee8f190 100644
--- a/src/com/android/settings/notification/modes/ZenModeHeaderController.java
+++ b/src/com/android/settings/notification/modes/ZenModeHeaderController.java
@@ -66,7 +66,7 @@ class ZenModeHeaderController extends AbstractZenModePreferenceController {
FutureUtil.whenDone(
zenMode.getIcon(mContext, ZenIconLoader.getInstance()),
- icon -> mHeaderController.setIcon(IconUtil.applyTint(mContext, icon))
+ icon -> mHeaderController.setIcon(IconUtil.applyNormalTint(mContext, icon))
.done(/* rebindActions= */ false),
mContext.getMainExecutor());
}
diff --git a/src/com/android/settings/notification/modes/ZenModeIconPickerIconPreferenceController.java b/src/com/android/settings/notification/modes/ZenModeIconPickerIconPreferenceController.java
index d891e66c2f7..d1d53af9ddf 100644
--- a/src/com/android/settings/notification/modes/ZenModeIconPickerIconPreferenceController.java
+++ b/src/com/android/settings/notification/modes/ZenModeIconPickerIconPreferenceController.java
@@ -55,7 +55,7 @@ class ZenModeIconPickerIconPreferenceController extends AbstractZenModePreferenc
FutureUtil.whenDone(
zenMode.getIcon(mContext, ZenIconLoader.getInstance()),
- icon -> mHeaderController.setIcon(IconUtil.applyTint(mContext, icon))
+ icon -> mHeaderController.setIcon(IconUtil.applyNormalTint(mContext, icon))
.done(/* rebindActions= */ false),
mContext.getMainExecutor());
}
diff --git a/src/com/android/settings/notification/modes/ZenModesListItemPreference.java b/src/com/android/settings/notification/modes/ZenModesListItemPreference.java
index 0b04ac6c087..1bc6e55acce 100644
--- a/src/com/android/settings/notification/modes/ZenModesListItemPreference.java
+++ b/src/com/android/settings/notification/modes/ZenModesListItemPreference.java
@@ -16,18 +16,31 @@
package com.android.settings.notification.modes;
import android.content.Context;
+import android.widget.TextView;
+import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.PreferenceViewHolder;
+
+import com.android.settings.R;
import com.android.settingslib.RestrictedPreference;
+import com.android.settingslib.Utils;
import com.android.settingslib.notification.modes.ZenIconLoader;
import com.android.settingslib.notification.modes.ZenMode;
+import com.google.common.base.Strings;
+
/**
* Preference representing a single mode item on the modes aggregator page. Clicking on this
* preference leads to an individual mode's configuration page.
*/
class ZenModesListItemPreference extends RestrictedPreference {
- final Context mContext;
- ZenMode mZenMode;
+
+ private final Context mContext;
+ private ZenMode mZenMode;
+
+ private TextView mTitleView;
+ private TextView mSummaryView;
ZenModesListItemPreference(Context context, ZenMode zenMode) {
super(context);
@@ -36,6 +49,18 @@ class ZenModesListItemPreference extends RestrictedPreference {
setKey(zenMode.getId());
}
+ @Override
+ public void onBindViewHolder(PreferenceViewHolder holder) {
+ super.onBindViewHolder(holder);
+ if (holder.findViewById(android.R.id.title) instanceof TextView titleView) {
+ mTitleView = titleView;
+ }
+ if (holder.findViewById(android.R.id.summary) instanceof TextView summaryView) {
+ mSummaryView = summaryView;
+ }
+ updateTextColor(mZenMode);
+ }
+
@Override
public void onClick() {
ZenSubSettingLauncher.forMode(mContext, mZenMode.getId()).launch();
@@ -43,13 +68,47 @@ class ZenModesListItemPreference extends RestrictedPreference {
public void setZenMode(ZenMode zenMode) {
mZenMode = zenMode;
- setTitle(mZenMode.getRule().getName());
- setSummary(mZenMode.getRule().getTriggerDescription());
- setIconSize(ICON_SIZE_SMALL);
+ setTitle(mZenMode.getName());
+ CharSequence statusText = switch (mZenMode.getStatus()) {
+ case ENABLED_AND_ACTIVE ->
+ Strings.isNullOrEmpty(mZenMode.getTriggerDescription())
+ ? mContext.getString(R.string.zen_mode_active_text)
+ : mContext.getString(
+ R.string.zen_mode_format_status_and_trigger,
+ mContext.getString(R.string.zen_mode_active_text),
+ mZenMode.getRule().getTriggerDescription());
+ case ENABLED -> mZenMode.getRule().getTriggerDescription();
+ case DISABLED_BY_USER -> mContext.getString(R.string.zen_mode_disabled_by_user);
+ case DISABLED_BY_OTHER -> mContext.getString(R.string.zen_mode_disabled_tap_to_set_up);
+ };
+ setSummary(statusText);
+ setIconSize(ICON_SIZE_SMALL);
FutureUtil.whenDone(
mZenMode.getIcon(mContext, ZenIconLoader.getInstance()),
- icon -> setIcon(IconUtil.applyTint(mContext, icon)),
+ icon -> setIcon(
+ zenMode.isActive()
+ ? IconUtil.applyAccentTint(mContext, icon)
+ : IconUtil.applyNormalTint(mContext, icon)),
mContext.getMainExecutor());
+
+ updateTextColor(zenMode);
+ }
+
+ private void updateTextColor(@Nullable ZenMode zenMode) {
+ boolean isActive = zenMode != null && zenMode.isActive();
+ if (mTitleView != null) {
+ mTitleView.setTextColor(Utils.getColorAttr(mContext,
+ isActive ? android.R.attr.colorAccent : android.R.attr.textColorPrimary));
+ }
+ if (mSummaryView != null) {
+ mSummaryView.setTextColor(Utils.getColorAttr(mContext,
+ isActive ? android.R.attr.colorAccent : android.R.attr.textColorSecondary));
+ }
+ }
+
+ @VisibleForTesting(otherwise = VisibleForTesting.NONE)
+ ZenMode getZenMode() {
+ return mZenMode;
}
}
diff --git a/src/com/android/settings/wifi/calling/WifiCallingSettingsForSub.java b/src/com/android/settings/wifi/calling/WifiCallingSettingsForSub.java
index 82537d48392..e5581d34b62 100644
--- a/src/com/android/settings/wifi/calling/WifiCallingSettingsForSub.java
+++ b/src/com/android/settings/wifi/calling/WifiCallingSettingsForSub.java
@@ -33,7 +33,6 @@ import android.telephony.TelephonyCallback;
import android.telephony.TelephonyManager;
import android.telephony.ims.ImsManager;
import android.telephony.ims.ImsMmTelManager;
-import android.telephony.ims.ProvisioningManager;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
@@ -42,12 +41,14 @@ import android.view.ViewGroup;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
+import androidx.lifecycle.LifecycleOwner;
import androidx.preference.Preference;
import androidx.preference.Preference.OnPreferenceClickListener;
import androidx.preference.PreferenceScreen;
-import com.android.ims.ImsConfig;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.flags.Flags;
@@ -57,8 +58,12 @@ import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.Utils;
import com.android.settings.core.SubSettingLauncher;
import com.android.settings.network.ims.WifiCallingQueryImsState;
+import com.android.settings.network.telephony.wificalling.IWifiCallingRepository;
+import com.android.settings.network.telephony.wificalling.WifiCallingRepository;
import com.android.settings.widget.SettingsMainSwitchPreference;
+import kotlin.Unit;
+
import java.util.List;
/**
@@ -103,7 +108,6 @@ public class WifiCallingSettingsForSub extends SettingsPreferenceFragment
private int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
private ImsMmTelManager mImsMmTelManager;
- private ProvisioningManager mProvisioningManager;
private TelephonyManager mTelephonyManager;
private PhoneTelephonyCallback mTelephonyCallback;
@@ -188,19 +192,6 @@ public class WifiCallingSettingsForSub extends SettingsPreferenceFragment
return true;
};
- private final ProvisioningManager.Callback mProvisioningCallback =
- new ProvisioningManager.Callback() {
- @Override
- public void onProvisioningIntChanged(int item, int value) {
- if (item == ImsConfig.ConfigConstants.VOICE_OVER_WIFI_SETTING_ENABLED
- || item == ImsConfig.ConfigConstants.VLT_SETTING_ENABLED) {
- // The provisioning policy might have changed. Update the body to make sure
- // this change takes effect if needed.
- updateBody();
- }
- }
- };
-
@VisibleForTesting
void showAlert(Intent intent) {
final Context context = getActivity();
@@ -263,14 +254,6 @@ public class WifiCallingSettingsForSub extends SettingsPreferenceFragment
return new WifiCallingQueryImsState(getContext(), subId);
}
- @VisibleForTesting
- ProvisioningManager getImsProvisioningManager() {
- if (!SubscriptionManager.isValidSubscriptionId(mSubId)) {
- return null;
- }
- return ProvisioningManager.createForSubscriptionId(mSubId);
- }
-
@VisibleForTesting
ImsMmTelManager getImsMmTelManager() {
if (!SubscriptionManager.isValidSubscriptionId(mSubId)) {
@@ -294,7 +277,6 @@ public class WifiCallingSettingsForSub extends SettingsPreferenceFragment
FRAGMENT_BUNDLE_SUBID, SubscriptionManager.INVALID_SUBSCRIPTION_ID);
}
- mProvisioningManager = getImsProvisioningManager();
mImsMmTelManager = getImsMmTelManager();
mSwitchBar = (SettingsMainSwitchPreference) findPreference(SWITCH_BAR);
@@ -336,19 +318,33 @@ public class WifiCallingSettingsForSub extends SettingsPreferenceFragment
return view;
}
+ @Override
+ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+ getWifiCallingRepository().collectIsWifiCallingReadyFlow(
+ getLifecycleOwner(), (isWifiWifiCallingReadyFlow) -> {
+ if (!isWifiWifiCallingReadyFlow) {
+ // This screen is not allowed to be shown due to provisioning policy and
+ // should therefore be closed.
+ finish();
+ }
+ return Unit.INSTANCE;
+ });
+ }
+
@VisibleForTesting
- boolean isWfcProvisionedOnDevice() {
- return queryImsState(mSubId).isWifiCallingProvisioned();
+ @NonNull
+ IWifiCallingRepository getWifiCallingRepository() {
+ return new WifiCallingRepository(requireContext(), mSubId);
+ }
+
+ @VisibleForTesting
+ @NonNull
+ LifecycleOwner getLifecycleOwner() {
+ return getViewLifecycleOwner();
}
private void updateBody() {
- if (!isWfcProvisionedOnDevice()) {
- // This screen is not allowed to be shown due to provisioning policy and should
- // therefore be closed.
- finish();
- return;
- }
-
final CarrierConfigManager configManager = (CarrierConfigManager)
getSystemService(Context.CARRIER_CONFIG_SERVICE);
boolean isWifiOnlySupported = true;
@@ -448,8 +444,6 @@ public class WifiCallingSettingsForSub extends SettingsPreferenceFragment
if (intent.getBooleanExtra(Phone.EXTRA_KEY_ALERT_SHOW, false)) {
showAlert(intent);
}
- // Register callback for provisioning changes.
- registerProvisioningChangedCallback();
}
@Override
@@ -462,8 +456,6 @@ public class WifiCallingSettingsForSub extends SettingsPreferenceFragment
mSwitchBar.removeOnSwitchChangeListener(this);
}
context.unregisterReceiver(mIntentReceiver);
- // Remove callback for provisioning changes.
- unregisterProvisioningChangedCallback();
}
/**
@@ -699,27 +691,6 @@ public class WifiCallingSettingsForSub extends SettingsPreferenceFragment
return SubscriptionManager.getResourcesForSubId(getContext(), mSubId);
}
- @VisibleForTesting
- void registerProvisioningChangedCallback() {
- if (mProvisioningManager == null) {
- return;
- }
- try {
- mProvisioningManager.registerProvisioningChangedCallback(getContext().getMainExecutor(),
- mProvisioningCallback);
- } catch (Exception ex) {
- Log.w(TAG, "onResume: Unable to register callback for provisioning changes.");
- }
- }
-
- @VisibleForTesting
- void unregisterProvisioningChangedCallback() {
- if (mProvisioningManager == null) {
- return;
- }
- mProvisioningManager.unregisterProvisioningChangedCallback(mProvisioningCallback);
- }
-
/**
* Determine whether to override roaming Wi-Fi calling preference when device is connected to
* non-terrestrial network.
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingNamePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingNamePreferenceControllerTest.java
new file mode 100644
index 00000000000..618e02129e6
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingNamePreferenceControllerTest.java
@@ -0,0 +1,319 @@
+/*
+ * 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.connecteddevice.audiosharing;
+
+import static com.android.settings.core.BasePreferenceController.AVAILABLE;
+import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.settings.SettingsEnums;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothLeBroadcast;
+import android.bluetooth.BluetoothLeBroadcastMetadata;
+import android.bluetooth.BluetoothStatusCodes;
+import android.content.Context;
+import android.platform.test.flag.junit.SetFlagsRule;
+
+import androidx.lifecycle.LifecycleOwner;
+import androidx.preference.PreferenceScreen;
+import androidx.test.core.app.ApplicationProvider;
+
+import com.android.settings.bluetooth.Utils;
+import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
+import com.android.settings.testutils.shadow.ShadowBluetoothUtils;
+import com.android.settingslib.bluetooth.BluetoothEventManager;
+import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast;
+import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant;
+import com.android.settingslib.bluetooth.LocalBluetoothManager;
+import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
+import com.android.settingslib.bluetooth.VolumeControlProfile;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+import com.android.settingslib.flags.Flags;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Spy;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadow.api.Shadow;
+import org.robolectric.shadows.ShadowLooper;
+
+import java.util.concurrent.Executor;
+
+@RunWith(RobolectricTestRunner.class)
+@Config(
+ shadows = {
+ ShadowBluetoothAdapter.class,
+ ShadowBluetoothUtils.class,
+ })
+public class AudioSharingNamePreferenceControllerTest {
+ private static final String PREF_KEY = "audio_sharing_stream_name";
+ private static final String BROADCAST_NAME = "broadcast_name";
+ private static final CharSequence UPDATED_NAME = "updated_name";
+
+ @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+ @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+ @Spy Context mContext = ApplicationProvider.getApplicationContext();
+ @Mock private LocalBluetoothLeBroadcast mBroadcast;
+ @Mock private LocalBluetoothLeBroadcastAssistant mAssistant;
+ @Mock private VolumeControlProfile mVolumeControl;
+ @Mock private LocalBluetoothManager mLocalBtManager;
+ @Mock private BluetoothEventManager mEventManager;
+ @Mock private LocalBluetoothProfileManager mProfileManager;
+ @Mock private PreferenceScreen mScreen;
+ private AudioSharingNamePreferenceController mController;
+ private ShadowBluetoothAdapter mShadowBluetoothAdapter;
+ private Lifecycle mLifecycle;
+ private LifecycleOwner mLifecycleOwner;
+ private AudioSharingNamePreference mPreference;
+ private FakeFeatureFactory mFeatureFactory;
+
+ @Before
+ public void setUp() {
+ mShadowBluetoothAdapter = Shadow.extract(BluetoothAdapter.getDefaultAdapter());
+ mShadowBluetoothAdapter.setEnabled(true);
+ mShadowBluetoothAdapter.setIsLeAudioBroadcastSourceSupported(
+ BluetoothStatusCodes.FEATURE_SUPPORTED);
+ mShadowBluetoothAdapter.setIsLeAudioBroadcastAssistantSupported(
+ BluetoothStatusCodes.FEATURE_SUPPORTED);
+ ShadowBluetoothUtils.sLocalBluetoothManager = mLocalBtManager;
+ mLocalBtManager = Utils.getLocalBtManager(mContext);
+ when(mLocalBtManager.getEventManager()).thenReturn(mEventManager);
+ when(mLocalBtManager.getProfileManager()).thenReturn(mProfileManager);
+ when(mProfileManager.getLeAudioBroadcastProfile()).thenReturn(mBroadcast);
+ when(mProfileManager.getLeAudioBroadcastAssistantProfile()).thenReturn(mAssistant);
+ when(mProfileManager.getVolumeControlProfile()).thenReturn(mVolumeControl);
+ when(mBroadcast.isProfileReady()).thenReturn(true);
+ when(mAssistant.isProfileReady()).thenReturn(true);
+ when(mVolumeControl.isProfileReady()).thenReturn(true);
+ when(mBroadcast.isProfileReady()).thenReturn(true);
+ mFeatureFactory = FakeFeatureFactory.setupForTest();
+ mLifecycleOwner = () -> mLifecycle;
+ mLifecycle = new Lifecycle(mLifecycleOwner);
+ mController = new AudioSharingNamePreferenceController(mContext, PREF_KEY);
+ mPreference = spy(new AudioSharingNamePreference(mContext));
+ when(mScreen.findPreference(PREF_KEY)).thenReturn(mPreference);
+ }
+
+ @Test
+ public void getAvailabilityStatus_flagOn_available() {
+ mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
+ }
+
+ @Test
+ public void getAvailabilityStatus_flagOff_unsupported() {
+ mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
+ }
+
+ @Test
+ public void onStart_flagOff_doNothing() {
+ mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
+ mController.onStart(mLifecycleOwner);
+ verify(mBroadcast, never())
+ .registerServiceCallBack(
+ any(Executor.class), any(BluetoothLeBroadcast.Callback.class));
+ }
+
+ @Test
+ public void onStart_flagOn_registerCallbacks() {
+ mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
+ mController.onStart(mLifecycleOwner);
+ verify(mBroadcast)
+ .registerServiceCallBack(
+ any(Executor.class), any(BluetoothLeBroadcast.Callback.class));
+ }
+
+ @Test
+ public void onStart_flagOn_serviceNotReady_registerCallbacks() {
+ mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
+ when(mBroadcast.isProfileReady()).thenReturn(false);
+ mController.onStart(mLifecycleOwner);
+ verify(mProfileManager)
+ .addServiceListener(any(LocalBluetoothProfileManager.ServiceListener.class));
+ }
+
+ @Test
+ public void onServiceConnected_removeCallbacks() {
+ mController.onServiceConnected();
+ verify(mProfileManager)
+ .removeServiceListener(any(LocalBluetoothProfileManager.ServiceListener.class));
+ }
+
+ @Test
+ public void onStop_flagOff_doNothing() {
+ mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
+ mController.onStart(mLifecycleOwner);
+ mController.onStop(mLifecycleOwner);
+ verify(mBroadcast, never())
+ .unregisterServiceCallBack(any(BluetoothLeBroadcast.Callback.class));
+ }
+
+ @Test
+ public void onStop_flagOn_unregisterCallbacks() {
+ mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
+ mController.onStart(mLifecycleOwner);
+ mController.onStop(mLifecycleOwner);
+ verify(mBroadcast).unregisterServiceCallBack(any(BluetoothLeBroadcast.Callback.class));
+ }
+
+ @Test
+ public void displayPreference_updateName_showIcon() {
+ when(mBroadcast.getBroadcastName()).thenReturn(BROADCAST_NAME);
+ when(mBroadcast.isEnabled(any())).thenReturn(true);
+ mController.displayPreference(mScreen);
+ ShadowLooper.idleMainLooper();
+
+ assertThat(mPreference.getText()).isEqualTo(BROADCAST_NAME);
+ assertThat(mPreference.getSummary()).isEqualTo(BROADCAST_NAME);
+ verify(mPreference).setValidator(any());
+ verify(mPreference).setShowQrCodeIcon(true);
+ }
+
+ @Test
+ public void displayPreference_updateName_hideIcon() {
+ when(mBroadcast.getBroadcastName()).thenReturn(BROADCAST_NAME);
+ when(mBroadcast.isEnabled(any())).thenReturn(false);
+ mController.displayPreference(mScreen);
+ ShadowLooper.idleMainLooper();
+
+ assertThat(mPreference.getText()).isEqualTo(BROADCAST_NAME);
+ assertThat(mPreference.getSummary()).isEqualTo(BROADCAST_NAME);
+ verify(mPreference).setValidator(any());
+ verify(mPreference).setShowQrCodeIcon(false);
+ }
+
+ @Test
+ public void onPreferenceChange_noChange_doNothing() {
+ when(mPreference.getSummary()).thenReturn(BROADCAST_NAME);
+ mController.displayPreference(mScreen);
+ boolean changed = mController.onPreferenceChange(mPreference, BROADCAST_NAME);
+ ShadowLooper.idleMainLooper();
+
+ verify(mBroadcast, never()).setBroadcastName(anyString());
+ verify(mBroadcast, never()).setProgramInfo(anyString());
+ verify(mBroadcast, never()).updateBroadcast();
+ verify(mFeatureFactory.metricsFeatureProvider, never()).action(any(), anyInt(), anyInt());
+
+ assertThat(changed).isFalse();
+ }
+
+ @Test
+ public void onPreferenceChange_changed_updateName_broadcasting() {
+ when(mPreference.getSummary()).thenReturn(BROADCAST_NAME);
+ when(mBroadcast.isEnabled(any())).thenReturn(true);
+ mController.displayPreference(mScreen);
+ boolean changed = mController.onPreferenceChange(mPreference, UPDATED_NAME);
+ ShadowLooper.idleMainLooper();
+
+ verify(mBroadcast).setBroadcastName(UPDATED_NAME.toString());
+ verify(mBroadcast).setProgramInfo(UPDATED_NAME.toString());
+ verify(mBroadcast).updateBroadcast();
+ verify(mFeatureFactory.metricsFeatureProvider)
+ .action(mContext, SettingsEnums.ACTION_AUDIO_STREAM_NAME_UPDATED, 1);
+ assertThat(changed).isTrue();
+ }
+
+ @Test
+ public void onPreferenceChange_changed_updateName_notBroadcasting() {
+ when(mPreference.getSummary()).thenReturn(BROADCAST_NAME);
+ when(mBroadcast.isEnabled(any())).thenReturn(false);
+ mController.displayPreference(mScreen);
+ boolean changed = mController.onPreferenceChange(mPreference, UPDATED_NAME);
+ ShadowLooper.idleMainLooper();
+
+ verify(mBroadcast).setBroadcastName(UPDATED_NAME.toString());
+ verify(mBroadcast).setProgramInfo(UPDATED_NAME.toString());
+ verify(mBroadcast, never()).updateBroadcast();
+ verify(mFeatureFactory.metricsFeatureProvider)
+ .action(mContext, SettingsEnums.ACTION_AUDIO_STREAM_NAME_UPDATED, 0);
+ assertThat(changed).isTrue();
+ }
+
+ @Test
+ public void unrelatedCallbacks_doNotUpdateIcon() {
+ mController.displayPreference(mScreen);
+ mController.mBroadcastCallback.onBroadcastStartFailed(/* reason= */ 0);
+ mController.mBroadcastCallback.onBroadcastStarted(/* reason= */ 0, /* broadcastId= */ 0);
+ mController.mBroadcastCallback.onBroadcastStopFailed(/* reason= */ 0);
+ mController.mBroadcastCallback.onBroadcastUpdateFailed(
+ /* reason= */ 0, /* broadcastId= */ 0);
+ mController.mBroadcastCallback.onBroadcastUpdated(/* reason= */ 0, /* broadcastId= */ 0);
+ mController.mBroadcastCallback.onPlaybackStarted(/* reason= */ 0, /* broadcastId= */ 0);
+ mController.mBroadcastCallback.onPlaybackStopped(/* reason= */ 0, /* broadcastId= */ 0);
+
+ ShadowLooper.idleMainLooper();
+ // Should be called once in displayPreference, but not called after callbacks
+ verify(mPreference).setShowQrCodeIcon(anyBoolean());
+ }
+
+ @Test
+ public void broadcastOnCallback_updateIcon() {
+ mController.displayPreference(mScreen);
+ mController.mBroadcastCallback.onBroadcastMetadataChanged(
+ /* broadcastId= */ 0, mock(BluetoothLeBroadcastMetadata.class));
+
+ ShadowLooper.idleMainLooper();
+
+ // Should be called twice, in displayPreference and also after callback
+ verify(mPreference, times(2)).setShowQrCodeIcon(anyBoolean());
+ }
+
+ @Test
+ public void broadcastStopCallback_updateIcon() {
+ mController.displayPreference(mScreen);
+ mController.mBroadcastCallback.onBroadcastStopped(/* reason= */ 0, /* broadcastId= */ 0);
+
+ ShadowLooper.idleMainLooper();
+
+ // Should be called twice, in displayPreference and also after callback
+ verify(mPreference, times(2)).setShowQrCodeIcon(anyBoolean());
+ }
+
+ @Test
+ public void idTextValid_emptyString() {
+ boolean valid = mController.isTextValid("");
+
+ assertThat(valid).isFalse();
+ }
+
+ @Test
+ public void idTextValid_validName() {
+ boolean valid = mController.isTextValid("valid name");
+
+ assertThat(valid).isTrue();
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingNamePreferenceTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingNamePreferenceTest.java
new file mode 100644
index 00000000000..13e2a9d4636
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingNamePreferenceTest.java
@@ -0,0 +1,141 @@
+/*
+ * 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.connecteddevice.audiosharing;
+
+import static com.google.common.truth.Truth.assertThat;
+
+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.settings.SettingsEnums;
+import android.content.Context;
+import android.content.Intent;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.ImageButton;
+import android.widget.LinearLayout;
+
+import androidx.preference.PreferenceViewHolder;
+import androidx.test.core.app.ApplicationProvider;
+
+import com.android.settings.R;
+import com.android.settings.SettingsActivity;
+import com.android.settings.connecteddevice.audiosharing.audiostreams.AudioStreamsQrCodeFragment;
+import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.robolectric.RobolectricTestRunner;
+
+@RunWith(RobolectricTestRunner.class)
+public class AudioSharingNamePreferenceTest {
+ @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+ private Context mContext;
+ private AudioSharingNamePreference mPreference;
+
+ @Before
+ public void setup() {
+ mContext = ApplicationProvider.getApplicationContext();
+ mPreference = spy(new AudioSharingNamePreference(mContext, null));
+ }
+
+ @Test
+ public void initialize_correctLayout() {
+ assertThat(mPreference.getLayoutResource())
+ .isEqualTo(
+ com.android.settingslib.widget.preference.twotarget.R.layout
+ .preference_two_target);
+ assertThat(mPreference.getWidgetLayoutResource())
+ .isEqualTo(R.layout.preference_widget_qrcode);
+ }
+
+ @Test
+ public void onBindViewHolder_correctLayout_noQrCodeButton() {
+ LayoutInflater inflater = LayoutInflater.from(mContext);
+ View view = inflater.inflate(mPreference.getLayoutResource(), null);
+ LinearLayout widgetView = view.findViewById(android.R.id.widget_frame);
+ assertThat(widgetView).isNotNull();
+ inflater.inflate(mPreference.getWidgetLayoutResource(), widgetView, true);
+
+ var holder = PreferenceViewHolder.createInstanceForTests(view);
+ mPreference.setShowQrCodeIcon(false);
+ mPreference.onBindViewHolder(holder);
+
+ ImageButton shareButton = (ImageButton) holder.findViewById(R.id.button_icon);
+ View divider =
+ holder.findViewById(
+ com.android.settingslib.widget.preference.twotarget.R.id
+ .two_target_divider);
+
+ assertThat(shareButton).isNotNull();
+ assertThat(shareButton.getVisibility()).isEqualTo(View.GONE);
+ assertThat(shareButton.hasOnClickListeners()).isFalse();
+ assertThat(divider).isNotNull();
+ assertThat(divider.getVisibility()).isEqualTo(View.GONE);
+ }
+
+ @Test
+ public void onBindViewHolder_correctLayout_showQrCodeButton() {
+ LayoutInflater inflater = LayoutInflater.from(mContext);
+ View view = inflater.inflate(mPreference.getLayoutResource(), null);
+ LinearLayout widgetView = view.findViewById(android.R.id.widget_frame);
+ assertThat(widgetView).isNotNull();
+ inflater.inflate(mPreference.getWidgetLayoutResource(), widgetView, true);
+
+ var holder = PreferenceViewHolder.createInstanceForTests(view);
+ mPreference.setShowQrCodeIcon(true);
+ mPreference.onBindViewHolder(holder);
+
+ ImageButton shareButton = (ImageButton) holder.findViewById(R.id.button_icon);
+ View divider =
+ holder.findViewById(
+ com.android.settingslib.widget.preference.twotarget.R.id
+ .two_target_divider);
+
+ assertThat(shareButton).isNotNull();
+ assertThat(shareButton.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(shareButton.getDrawable()).isNotNull();
+ assertThat(shareButton.hasOnClickListeners()).isTrue();
+ assertThat(divider).isNotNull();
+ assertThat(divider.getVisibility()).isEqualTo(View.VISIBLE);
+
+ // mContext is not an Activity context, calling startActivity() from outside of an Activity
+ // context requires the FLAG_ACTIVITY_NEW_TASK flag, create a mock to avoid this
+ // AndroidRuntimeException.
+ Context activityContext = mock(Context.class);
+ when(mPreference.getContext()).thenReturn(activityContext);
+ shareButton.callOnClick();
+
+ ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(Intent.class);
+ verify(activityContext).startActivity(argumentCaptor.capture());
+
+ Intent intent = argumentCaptor.getValue();
+ assertThat(intent.getStringExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT))
+ .isEqualTo(AudioStreamsQrCodeFragment.class.getName());
+ assertThat(intent.getIntExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT_TITLE_RESID, 0))
+ .isEqualTo(R.string.audio_streams_qr_code_page_title);
+ assertThat(intent.getIntExtra(MetricsFeatureProvider.EXTRA_SOURCE_METRICS_CATEGORY, 0))
+ .isEqualTo(SettingsEnums.AUDIO_SHARING_SETTINGS);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingNameTextValidatorTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingNameTextValidatorTest.java
new file mode 100644
index 00000000000..ada6117b34a
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingNameTextValidatorTest.java
@@ -0,0 +1,52 @@
+/*
+ * 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.connecteddevice.audiosharing;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+
+@RunWith(RobolectricTestRunner.class)
+public class AudioSharingNameTextValidatorTest {
+ private AudioSharingNameTextValidator mValidator;
+
+ @Before
+ public void setUp() {
+ mValidator = new AudioSharingNameTextValidator();
+ }
+
+ @Test
+ public void testValidNames() {
+ assertThat(mValidator.isTextValid("ValidName")).isTrue();
+ assertThat(mValidator.isTextValid("12345678")).isTrue();
+ assertThat(mValidator.isTextValid("Name_With_Underscores")).isTrue();
+ assertThat(mValidator.isTextValid("ÄÖÜß")).isTrue();
+ assertThat(mValidator.isTextValid("ThisNameIsExactly32Characters!")).isTrue();
+ }
+
+ @Test
+ public void testInvalidNames() {
+ assertThat(mValidator.isTextValid(null)).isFalse();
+ assertThat(mValidator.isTextValid("")).isFalse();
+ assertThat(mValidator.isTextValid("abc")).isFalse();
+ assertThat(mValidator.isTextValid("ThisNameIsWayTooLongForAnAudioSharingName")).isFalse();
+ assertThat(mValidator.isTextValid("Invalid\uDC00")).isFalse();
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingPasswordPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingPasswordPreferenceControllerTest.java
new file mode 100644
index 00000000000..5bfb9663e11
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingPasswordPreferenceControllerTest.java
@@ -0,0 +1,335 @@
+/*
+ * 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.connecteddevice.audiosharing;
+
+import static com.android.settings.core.BasePreferenceController.AVAILABLE;
+import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.settings.SettingsEnums;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothStatusCodes;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.database.ContentObserver;
+import android.platform.test.flag.junit.SetFlagsRule;
+
+import androidx.lifecycle.LifecycleOwner;
+import androidx.preference.PreferenceScreen;
+import androidx.test.core.app.ApplicationProvider;
+
+import com.android.settings.R;
+import com.android.settings.bluetooth.Utils;
+import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
+import com.android.settings.testutils.shadow.ShadowBluetoothUtils;
+import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast;
+import com.android.settingslib.bluetooth.LocalBluetoothManager;
+import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+import com.android.settingslib.flags.Flags;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.Spy;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadow.api.Shadow;
+import org.robolectric.shadows.ShadowLooper;
+
+import java.nio.charset.StandardCharsets;
+
+@RunWith(RobolectricTestRunner.class)
+@Config(
+ shadows = {
+ ShadowBluetoothAdapter.class,
+ ShadowBluetoothUtils.class,
+ })
+public class AudioSharingPasswordPreferenceControllerTest {
+ private static final String PREF_KEY = "audio_sharing_stream_password";
+ private static final String SHARED_PREF_KEY = "default_password";
+ private static final String BROADCAST_PASSWORD = "password";
+ private static final String EDITTEXT_PASSWORD = "edittext_password";
+ private static final String HIDDEN_PASSWORD = "********";
+
+ @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+ @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+ @Spy Context mContext = ApplicationProvider.getApplicationContext();
+ @Mock private LocalBluetoothLeBroadcast mBroadcast;
+ @Mock private LocalBluetoothManager mLocalBtManager;
+ @Mock private LocalBluetoothProfileManager mProfileManager;
+ @Mock private SharedPreferences mSharedPreferences;
+ @Mock private SharedPreferences.Editor mEditor;
+ @Mock private ContentResolver mContentResolver;
+ @Mock private PreferenceScreen mScreen;
+ private AudioSharingPasswordPreferenceController mController;
+ private ShadowBluetoothAdapter mShadowBluetoothAdapter;
+ private Lifecycle mLifecycle;
+ private LifecycleOwner mLifecycleOwner;
+ private AudioSharingPasswordPreference mPreference;
+ private FakeFeatureFactory mFeatureFactory;
+
+ @Before
+ public void setUp() {
+ mShadowBluetoothAdapter = Shadow.extract(BluetoothAdapter.getDefaultAdapter());
+ mShadowBluetoothAdapter.setEnabled(true);
+ mShadowBluetoothAdapter.setIsLeAudioBroadcastSourceSupported(
+ BluetoothStatusCodes.FEATURE_SUPPORTED);
+ mShadowBluetoothAdapter.setIsLeAudioBroadcastAssistantSupported(
+ BluetoothStatusCodes.FEATURE_SUPPORTED);
+ mLocalBtManager = Utils.getLocalBtManager(mContext);
+ when(mLocalBtManager.getProfileManager()).thenReturn(mProfileManager);
+ when(mProfileManager.getLeAudioBroadcastProfile()).thenReturn(mBroadcast);
+ mFeatureFactory = FakeFeatureFactory.setupForTest();
+ when(mContext.getContentResolver()).thenReturn(mContentResolver);
+ when(mContext.getSharedPreferences(anyString(), anyInt())).thenReturn(mSharedPreferences);
+ when(mSharedPreferences.edit()).thenReturn(mEditor);
+ when(mEditor.putString(anyString(), anyString())).thenReturn(mEditor);
+ mLifecycleOwner = () -> mLifecycle;
+ mLifecycle = new Lifecycle(mLifecycleOwner);
+ mController = new AudioSharingPasswordPreferenceController(mContext, PREF_KEY);
+ mPreference = spy(new AudioSharingPasswordPreference(mContext));
+ when(mScreen.findPreference(PREF_KEY)).thenReturn(mPreference);
+ }
+
+ @Test
+ public void getAvailabilityStatus_flagOn_available() {
+ mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
+ }
+
+ @Test
+ public void getAvailabilityStatus_flagOff_unsupported() {
+ mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
+ }
+
+ @Test
+ public void onStart_flagOff_doNothing() {
+ mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
+ mController.onStart(mLifecycleOwner);
+ verify(mContentResolver, never()).registerContentObserver(any(), anyBoolean(), any());
+ verify(mSharedPreferences, never()).registerOnSharedPreferenceChangeListener(any());
+ }
+
+ @Test
+ public void onStart_flagOn_registerCallbacks() {
+ mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
+ mController.onStart(mLifecycleOwner);
+ verify(mContentResolver).registerContentObserver(any(), anyBoolean(), any());
+ verify(mSharedPreferences).registerOnSharedPreferenceChangeListener(any());
+ }
+
+ @Test
+ public void onStop_flagOff_doNothing() {
+ mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
+ mController.onStop(mLifecycleOwner);
+ verify(mContentResolver, never()).unregisterContentObserver(any());
+ verify(mSharedPreferences, never()).unregisterOnSharedPreferenceChangeListener(any());
+ }
+
+ @Test
+ public void onStop_flagOn_registerCallbacks() {
+ mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
+ mController.onStop(mLifecycleOwner);
+ verify(mContentResolver).unregisterContentObserver(any());
+ verify(mSharedPreferences).unregisterOnSharedPreferenceChangeListener(any());
+ }
+
+ @Test
+ public void displayPreference_setupPreference_noPassword() {
+ when(mSharedPreferences.getString(anyString(), anyString())).thenReturn(EDITTEXT_PASSWORD);
+ when(mBroadcast.getBroadcastCode()).thenReturn(new byte[] {});
+
+ mController.displayPreference(mScreen);
+ ShadowLooper.idleMainLooper();
+
+ assertThat(mPreference.isPassword()).isTrue();
+ assertThat(mPreference.getDialogLayoutResource())
+ .isEqualTo(R.layout.audio_sharing_password_dialog);
+ assertThat(mPreference.getText()).isEqualTo(EDITTEXT_PASSWORD);
+ assertThat(mPreference.getSummary())
+ .isEqualTo(mContext.getString(R.string.audio_streams_no_password_summary));
+ verify(mPreference).setValidator(any());
+ verify(mPreference).setOnDialogEventListener(any());
+ }
+
+ @Test
+ public void contentObserver_updatePreferenceOnChange() {
+ mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
+ when(mBroadcast.getBroadcastCode())
+ .thenReturn(BROADCAST_PASSWORD.getBytes(StandardCharsets.UTF_8));
+ mController.onStart(mLifecycleOwner);
+ mController.displayPreference(mScreen);
+ ShadowLooper.idleMainLooper();
+
+ ArgumentCaptor observerCaptor =
+ ArgumentCaptor.forClass(ContentObserver.class);
+ verify(mContentResolver)
+ .registerContentObserver(any(), anyBoolean(), observerCaptor.capture());
+
+ var observer = observerCaptor.getValue();
+ assertThat(observer).isNotNull();
+ observer.onChange(true);
+ verify(mPreference).setText(anyString());
+ verify(mPreference).setSummary(anyString());
+ }
+
+ @Test
+ public void sharedPrefChangeListener_updatePreferenceOnChange() {
+ mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
+ when(mBroadcast.getBroadcastCode())
+ .thenReturn(BROADCAST_PASSWORD.getBytes(StandardCharsets.UTF_8));
+ mController.onStart(mLifecycleOwner);
+ mController.displayPreference(mScreen);
+ ShadowLooper.idleMainLooper();
+
+ ArgumentCaptor captor =
+ ArgumentCaptor.forClass(SharedPreferences.OnSharedPreferenceChangeListener.class);
+ verify(mSharedPreferences).registerOnSharedPreferenceChangeListener(captor.capture());
+
+ var observer = captor.getValue();
+ assertThat(captor).isNotNull();
+ observer.onSharedPreferenceChanged(mSharedPreferences, SHARED_PREF_KEY);
+ verify(mPreference).setText(anyString());
+ verify(mPreference).setSummary(anyString());
+ }
+
+ @Test
+ public void displayPreference_setupPreference_hasPassword() {
+ when(mBroadcast.getBroadcastCode())
+ .thenReturn(BROADCAST_PASSWORD.getBytes(StandardCharsets.UTF_8));
+ mController.displayPreference(mScreen);
+ ShadowLooper.idleMainLooper();
+
+ assertThat(mPreference.isPassword()).isTrue();
+ assertThat(mPreference.getDialogLayoutResource())
+ .isEqualTo(R.layout.audio_sharing_password_dialog);
+ assertThat(mPreference.getText()).isEqualTo(BROADCAST_PASSWORD);
+ assertThat(mPreference.getSummary()).isEqualTo(HIDDEN_PASSWORD);
+ verify(mPreference).setValidator(any());
+ verify(mPreference).setOnDialogEventListener(any());
+ }
+
+ @Test
+ public void onBindDialogView_updatePreference_isBroadcasting_noPassword() {
+ when(mBroadcast.getBroadcastCode()).thenReturn(new byte[] {});
+ when(mBroadcast.isEnabled(any())).thenReturn(true);
+ mController.displayPreference(mScreen);
+ mController.onBindDialogView();
+ ShadowLooper.idleMainLooper();
+
+ verify(mPreference).setEditable(false);
+ verify(mPreference).setChecked(true);
+ }
+
+ @Test
+ public void onBindDialogView_updatePreference_isNotBroadcasting_hasPassword() {
+ when(mBroadcast.getBroadcastCode())
+ .thenReturn(BROADCAST_PASSWORD.getBytes(StandardCharsets.UTF_8));
+ mController.displayPreference(mScreen);
+ mController.onBindDialogView();
+ ShadowLooper.idleMainLooper();
+
+ verify(mPreference).setEditable(true);
+ verify(mPreference).setChecked(false);
+ }
+
+ @Test
+ public void onPreferenceDataChanged_isBroadcasting_doNothing() {
+ when(mBroadcast.isEnabled(any())).thenReturn(true);
+ mController.displayPreference(mScreen);
+ mController.onPreferenceDataChanged(BROADCAST_PASSWORD, /* isPublicBroadcast= */ false);
+ ShadowLooper.idleMainLooper();
+
+ verify(mBroadcast, never()).setBroadcastCode(any());
+ verify(mFeatureFactory.metricsFeatureProvider, never()).action(any(), anyInt(), anyInt());
+ }
+
+ @Test
+ public void onPreferenceDataChanged_noChange_doNothing() {
+ when(mSharedPreferences.getString(anyString(), anyString())).thenReturn(EDITTEXT_PASSWORD);
+ when(mBroadcast.getBroadcastCode()).thenReturn(new byte[] {});
+ mController.displayPreference(mScreen);
+ mController.onPreferenceDataChanged(EDITTEXT_PASSWORD, /* isPublicBroadcast= */ true);
+ ShadowLooper.idleMainLooper();
+
+ verify(mBroadcast, never()).setBroadcastCode(any());
+ verify(mFeatureFactory.metricsFeatureProvider, never()).action(any(), anyInt(), anyInt());
+ }
+
+ @Test
+ public void onPreferenceDataChanged_updateToNonPublicBroadcast() {
+ when(mSharedPreferences.getString(anyString(), anyString())).thenReturn(EDITTEXT_PASSWORD);
+ when(mBroadcast.getBroadcastCode()).thenReturn(new byte[] {});
+ mController.displayPreference(mScreen);
+ mController.onPreferenceDataChanged(BROADCAST_PASSWORD, /* isPublicBroadcast= */ false);
+ ShadowLooper.idleMainLooper();
+
+ verify(mBroadcast).setBroadcastCode(BROADCAST_PASSWORD.getBytes(StandardCharsets.UTF_8));
+ verify(mEditor).putString(anyString(), eq(BROADCAST_PASSWORD));
+ verify(mFeatureFactory.metricsFeatureProvider)
+ .action(mContext, SettingsEnums.ACTION_AUDIO_STREAM_PASSWORD_UPDATED, 0);
+ }
+
+ @Test
+ public void onPreferenceDataChanged_updateToPublicBroadcast() {
+ when(mSharedPreferences.getString(anyString(), anyString())).thenReturn(EDITTEXT_PASSWORD);
+ when(mBroadcast.getBroadcastCode())
+ .thenReturn(BROADCAST_PASSWORD.getBytes(StandardCharsets.UTF_8));
+ mController.displayPreference(mScreen);
+ mController.onPreferenceDataChanged(EDITTEXT_PASSWORD, /* isPublicBroadcast= */ true);
+ ShadowLooper.idleMainLooper();
+
+ verify(mBroadcast).setBroadcastCode("".getBytes(StandardCharsets.UTF_8));
+ verify(mEditor, never()).putString(anyString(), eq(EDITTEXT_PASSWORD));
+ verify(mFeatureFactory.metricsFeatureProvider)
+ .action(mContext, SettingsEnums.ACTION_AUDIO_STREAM_PASSWORD_UPDATED, 1);
+ }
+
+ @Test
+ public void idTextValid_emptyString() {
+ boolean valid = mController.isTextValid("");
+
+ assertThat(valid).isFalse();
+ }
+
+ @Test
+ public void idTextValid_validPassword() {
+ boolean valid = mController.isTextValid(BROADCAST_PASSWORD);
+
+ assertThat(valid).isTrue();
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingPasswordPreferenceTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingPasswordPreferenceTest.java
new file mode 100644
index 00000000000..0b87e8ca25d
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingPasswordPreferenceTest.java
@@ -0,0 +1,215 @@
+/*
+ * 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.connecteddevice.audiosharing;
+
+import static android.view.View.GONE;
+import static android.view.View.VISIBLE;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+
+import android.content.Context;
+import android.content.DialogInterface;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.CheckBox;
+import android.widget.EditText;
+
+import androidx.appcompat.app.AlertDialog;
+import androidx.test.core.app.ApplicationProvider;
+
+import com.android.settings.R;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.robolectric.RobolectricTestRunner;
+
+@RunWith(RobolectricTestRunner.class)
+public class AudioSharingPasswordPreferenceTest {
+ @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+ private static final String EDIT_TEXT_CONTENT = "text";
+ private Context mContext;
+ private AudioSharingPasswordPreference mPreference;
+
+ @Before
+ public void setup() {
+ mContext = ApplicationProvider.getApplicationContext();
+ mPreference = new AudioSharingPasswordPreference(mContext, null);
+ }
+
+ @Test
+ public void onBindDialogView_correctLayout() {
+ View view =
+ LayoutInflater.from(mContext).inflate(R.layout.audio_sharing_password_dialog, null);
+ mPreference.onBindDialogView(view);
+
+ var editText = view.findViewById(android.R.id.edit);
+ var checkBox = view.findViewById(R.id.audio_sharing_stream_password_checkbox);
+ var dialogMessage = view.findViewById(android.R.id.message);
+
+ assertThat(editText).isNotNull();
+ assertThat(checkBox).isNotNull();
+ assertThat(dialogMessage).isNotNull();
+ }
+
+ @Test
+ public void setEditable_true() {
+ View view =
+ LayoutInflater.from(mContext).inflate(R.layout.audio_sharing_password_dialog, null);
+ mPreference.onBindDialogView(view);
+
+ var editText = view.findViewById(android.R.id.edit);
+ var checkBox = view.findViewById(R.id.audio_sharing_stream_password_checkbox);
+ var dialogMessage = view.findViewById(android.R.id.message);
+
+ mPreference.setEditable(true);
+
+ assertThat(editText).isNotNull();
+ assertThat(editText.isEnabled()).isTrue();
+ assertThat(editText.getAlpha()).isEqualTo(1.0f);
+ assertThat(checkBox).isNotNull();
+ assertThat(checkBox.isEnabled()).isTrue();
+ assertThat(dialogMessage).isNotNull();
+ assertThat(dialogMessage.getVisibility()).isEqualTo(GONE);
+ }
+
+ @Test
+ public void setEditable_false() {
+ View view =
+ LayoutInflater.from(mContext).inflate(R.layout.audio_sharing_password_dialog, null);
+ mPreference.onBindDialogView(view);
+
+ var editText = view.findViewById(android.R.id.edit);
+ var checkBox = view.findViewById(R.id.audio_sharing_stream_password_checkbox);
+ var dialogMessage = view.findViewById(android.R.id.message);
+
+ mPreference.setEditable(false);
+
+ assertThat(editText).isNotNull();
+ assertThat(editText.isEnabled()).isFalse();
+ assertThat(editText.getAlpha()).isLessThan(1.0f);
+ assertThat(checkBox).isNotNull();
+ assertThat(checkBox.isEnabled()).isFalse();
+ assertThat(dialogMessage).isNotNull();
+ assertThat(dialogMessage.getVisibility()).isEqualTo(VISIBLE);
+ }
+
+ @Test
+ public void setChecked_true() {
+ View view =
+ LayoutInflater.from(mContext).inflate(R.layout.audio_sharing_password_dialog, null);
+ mPreference.onBindDialogView(view);
+
+ CheckBox checkBox = view.findViewById(R.id.audio_sharing_stream_password_checkbox);
+
+ mPreference.setChecked(true);
+
+ assertThat(checkBox).isNotNull();
+ assertThat(checkBox.isChecked()).isTrue();
+ }
+
+ @Test
+ public void setChecked_false() {
+ View view =
+ LayoutInflater.from(mContext).inflate(R.layout.audio_sharing_password_dialog, null);
+ mPreference.onBindDialogView(view);
+
+ CheckBox checkBox = view.findViewById(R.id.audio_sharing_stream_password_checkbox);
+
+ mPreference.setChecked(false);
+
+ assertThat(checkBox).isNotNull();
+ assertThat(checkBox.isChecked()).isFalse();
+ }
+
+ @Test
+ public void onDialogEventListener_onClick_positiveButton() {
+ AudioSharingPasswordPreference.OnDialogEventListener listener =
+ mock(AudioSharingPasswordPreference.OnDialogEventListener.class);
+ mPreference.setOnDialogEventListener(listener);
+ View view =
+ LayoutInflater.from(mContext).inflate(R.layout.audio_sharing_password_dialog, null);
+ mPreference.onBindDialogView(view);
+
+ EditText editText = view.findViewById(android.R.id.edit);
+ assertThat(editText).isNotNull();
+ editText.setText(EDIT_TEXT_CONTENT);
+
+ mPreference.onClick(mock(DialogInterface.class), DialogInterface.BUTTON_POSITIVE);
+
+ verify(listener).onBindDialogView();
+ verify(listener).onPreferenceDataChanged(eq(EDIT_TEXT_CONTENT), anyBoolean());
+ }
+
+ @Test
+ public void onDialogEventListener_onClick_negativeButton_doNothing() {
+ AudioSharingPasswordPreference.OnDialogEventListener listener =
+ mock(AudioSharingPasswordPreference.OnDialogEventListener.class);
+ mPreference.setOnDialogEventListener(listener);
+ View view =
+ LayoutInflater.from(mContext).inflate(R.layout.audio_sharing_password_dialog, null);
+ mPreference.onBindDialogView(view);
+
+ EditText editText = view.findViewById(android.R.id.edit);
+ assertThat(editText).isNotNull();
+ editText.setText(EDIT_TEXT_CONTENT);
+
+ mPreference.onClick(mock(DialogInterface.class), DialogInterface.BUTTON_NEGATIVE);
+
+ verify(listener).onBindDialogView();
+ verify(listener, never()).onPreferenceDataChanged(anyString(), anyBoolean());
+ }
+
+ @Test
+ public void onPrepareDialogBuilder_editable_doNothing() {
+ View view =
+ LayoutInflater.from(mContext).inflate(R.layout.audio_sharing_password_dialog, null);
+ mPreference.onBindDialogView(view);
+ mPreference.setEditable(true);
+
+ var dialogBuilder = mock(AlertDialog.Builder.class);
+ mPreference.onPrepareDialogBuilder(
+ dialogBuilder, mock(DialogInterface.OnClickListener.class));
+
+ verify(dialogBuilder, never()).setPositiveButton(any(), any());
+ }
+
+ @Test
+ public void onPrepareDialogBuilder_notEditable_disableButton() {
+ View view =
+ LayoutInflater.from(mContext).inflate(R.layout.audio_sharing_password_dialog, null);
+ mPreference.onBindDialogView(view);
+ mPreference.setEditable(false);
+
+ var dialogBuilder = mock(AlertDialog.Builder.class);
+ mPreference.onPrepareDialogBuilder(
+ dialogBuilder, mock(DialogInterface.OnClickListener.class));
+
+ verify(dialogBuilder).setPositiveButton(any(), any());
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingPasswordValidatorTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingPasswordValidatorTest.java
new file mode 100644
index 00000000000..5c96fe1b5bf
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingPasswordValidatorTest.java
@@ -0,0 +1,53 @@
+/*
+ * 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.connecteddevice.audiosharing;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+
+@RunWith(RobolectricTestRunner.class)
+public class AudioSharingPasswordValidatorTest {
+ private AudioSharingPasswordValidator mValidator;
+
+ @Before
+ public void setUp() {
+ mValidator = new AudioSharingPasswordValidator();
+ }
+
+ @Test
+ public void testValidPasswords() {
+ assertThat(mValidator.isTextValid("1234")).isTrue();
+ assertThat(mValidator.isTextValid("Password")).isTrue();
+ assertThat(mValidator.isTextValid("SecurePass123!")).isTrue();
+ assertThat(mValidator.isTextValid("ÄÖÜß")).isTrue();
+ assertThat(mValidator.isTextValid("1234567890abcdef")).isTrue();
+ }
+
+ @Test
+ public void testInvalidPasswords() {
+ assertThat(mValidator.isTextValid(null)).isFalse();
+ assertThat(mValidator.isTextValid("")).isFalse();
+ assertThat(mValidator.isTextValid("abc")).isFalse();
+ assertThat(mValidator.isTextValid("ThisIsAVeryLongPasswordThatExceedsSixteenOctets"))
+ .isFalse();
+ assertThat(mValidator.isTextValid("Invalid\uDC00")).isFalse();
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AddSourceBadCodeStateTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AddSourceBadCodeStateTest.java
index 2fddff52358..aba300e08bc 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AddSourceBadCodeStateTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AddSourceBadCodeStateTest.java
@@ -20,18 +20,40 @@ import static com.android.settings.connecteddevice.audiosharing.audiostreams.Add
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.settings.SettingsEnums;
+import android.content.Context;
+
+import androidx.test.core.app.ApplicationProvider;
+
+import com.android.settings.testutils.FakeFeatureFactory;
+
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
import org.robolectric.RobolectricTestRunner;
@RunWith(RobolectricTestRunner.class)
public class AddSourceBadCodeStateTest {
+ @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+ private final Context mContext = ApplicationProvider.getApplicationContext();
+ @Mock private AudioStreamPreference mPreference;
+ @Mock private AudioStreamsProgressCategoryController mController;
+ @Mock private AudioStreamsHelper mHelper;
+ private FakeFeatureFactory mFeatureFactory;
private AddSourceBadCodeState mInstance;
@Before
public void setUp() {
- mInstance = AddSourceBadCodeState.getInstance();
+ mFeatureFactory = FakeFeatureFactory.setupForTest();
+ mInstance = new AddSourceBadCodeState();
}
@Test
@@ -55,4 +77,19 @@ public class AddSourceBadCodeStateTest {
AudioStreamsProgressCategoryController.AudioStreamState
.ADD_SOURCE_BAD_CODE);
}
+
+ @Test
+ public void testPerformAction() {
+ when(mPreference.getContext()).thenReturn(mContext);
+ when(mPreference.getSourceOriginForLogging())
+ .thenReturn(SourceOriginForLogging.QR_CODE_SCAN_SETTINGS);
+
+ mInstance.performAction(mPreference, mController, mHelper);
+
+ verify(mFeatureFactory.metricsFeatureProvider)
+ .action(
+ eq(mContext),
+ eq(SettingsEnums.ACTION_AUDIO_STREAM_JOIN_FAILED_BAD_CODE),
+ eq(SourceOriginForLogging.QR_CODE_SCAN_SETTINGS.ordinal()));
+ }
}
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AddSourceFailedStateTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AddSourceFailedStateTest.java
index d8b1fcf9401..1bc9f9148f5 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AddSourceFailedStateTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AddSourceFailedStateTest.java
@@ -20,18 +20,40 @@ import static com.android.settings.connecteddevice.audiosharing.audiostreams.Add
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.settings.SettingsEnums;
+import android.content.Context;
+
+import androidx.test.core.app.ApplicationProvider;
+
+import com.android.settings.testutils.FakeFeatureFactory;
+
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
import org.robolectric.RobolectricTestRunner;
@RunWith(RobolectricTestRunner.class)
public class AddSourceFailedStateTest {
+ @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+ private final Context mContext = ApplicationProvider.getApplicationContext();
+ @Mock private AudioStreamPreference mPreference;
+ @Mock private AudioStreamsProgressCategoryController mController;
+ @Mock private AudioStreamsHelper mHelper;
+ private FakeFeatureFactory mFeatureFactory;
private AddSourceFailedState mInstance;
@Before
public void setUp() {
- mInstance = AddSourceFailedState.getInstance();
+ mFeatureFactory = FakeFeatureFactory.setupForTest();
+ mInstance = new AddSourceFailedState();
}
@Test
@@ -54,4 +76,19 @@ public class AddSourceFailedStateTest {
.isEqualTo(
AudioStreamsProgressCategoryController.AudioStreamState.ADD_SOURCE_FAILED);
}
+
+ @Test
+ public void testPerformAction() {
+ when(mPreference.getContext()).thenReturn(mContext);
+ when(mPreference.getSourceOriginForLogging())
+ .thenReturn(SourceOriginForLogging.QR_CODE_SCAN_SETTINGS);
+
+ mInstance.performAction(mPreference, mController, mHelper);
+
+ verify(mFeatureFactory.metricsFeatureProvider)
+ .action(
+ eq(mContext),
+ eq(SettingsEnums.ACTION_AUDIO_STREAM_JOIN_FAILED_OTHER),
+ eq(SourceOriginForLogging.QR_CODE_SCAN_SETTINGS.ordinal()));
+ }
}
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AddSourceWaitForResponseStateTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AddSourceWaitForResponseStateTest.java
index 6e5342bb3fe..950ad38a64a 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AddSourceWaitForResponseStateTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AddSourceWaitForResponseStateTest.java
@@ -22,11 +22,21 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.app.settings.SettingsEnums;
import android.bluetooth.BluetoothLeBroadcastMetadata;
+import android.content.Context;
+
+import androidx.test.core.app.ApplicationProvider;
+
+import com.android.settings.R;
+import com.android.settings.testutils.FakeFeatureFactory;
import org.junit.Before;
import org.junit.Rule;
@@ -36,23 +46,36 @@ import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowAlertDialog;
import org.robolectric.shadows.ShadowLooper;
import java.util.concurrent.TimeUnit;
@RunWith(RobolectricTestRunner.class)
+@Config(
+ shadows = {
+ ShadowAlertDialog.class,
+ })
public class AddSourceWaitForResponseStateTest {
- private static final int BROADCAST_ID = 1;
@Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+ private static final int BROADCAST_ID = 1;
+ private final Context mContext = spy(ApplicationProvider.getApplicationContext());
@Mock private AudioStreamPreference mMockPreference;
@Mock private AudioStreamsProgressCategoryController mMockController;
@Mock private AudioStreamsHelper mMockHelper;
@Mock private BluetoothLeBroadcastMetadata mMockMetadata;
+ @Mock private AudioStreamsRepository mMockRepository;
+ private FakeFeatureFactory mFeatureFactory;
private AddSourceWaitForResponseState mInstance;
@Before
public void setUp() {
- mInstance = AddSourceWaitForResponseState.getInstance();
+ mFeatureFactory = FakeFeatureFactory.setupForTest();
+ mInstance = new AddSourceWaitForResponseState();
+ when(mMockPreference.getContext()).thenReturn(mContext);
+ when(mMockPreference.getSourceOriginForLogging())
+ .thenReturn(SourceOriginForLogging.QR_CODE_SCAN_SETTINGS);
}
@Test
@@ -93,11 +116,18 @@ public class AddSourceWaitForResponseStateTest {
public void testPerformAction_metadataIsNotNull_addSource() {
when(mMockPreference.getAudioStreamMetadata()).thenReturn(mMockMetadata);
when(mMockPreference.getSourceOriginForLogging())
- .thenReturn(SourceOriginForLogging.UNKNOWN);
+ .thenReturn(SourceOriginForLogging.QR_CODE_SCAN_SETTINGS);
+ mInstance.setAudioStreamsRepositoryForTesting(mMockRepository);
mInstance.performAction(mMockPreference, mMockController, mMockHelper);
verify(mMockHelper).addSource(mMockMetadata);
+ verify(mFeatureFactory.metricsFeatureProvider)
+ .action(
+ eq(mContext),
+ eq(SettingsEnums.ACTION_AUDIO_STREAM_JOIN),
+ eq(SourceOriginForLogging.QR_CODE_SCAN_SETTINGS.ordinal()));
+ verify(mMockRepository).cacheMetadata(mMockMetadata);
verify(mMockController, never()).handleSourceFailedToConnect(anyInt());
}
@@ -108,12 +138,28 @@ public class AddSourceWaitForResponseStateTest {
when(mMockPreference.getAudioStreamState()).thenReturn(mInstance.getStateEnum());
when(mMockPreference.getAudioStreamBroadcastId()).thenReturn(BROADCAST_ID);
when(mMockPreference.getSourceOriginForLogging())
- .thenReturn(SourceOriginForLogging.UNKNOWN);
+ .thenReturn(SourceOriginForLogging.QR_CODE_SCAN_SETTINGS);
+ when(mMockController.getFragment()).thenReturn(mock(AudioStreamsDashboardFragment.class));
+ mInstance.setAudioStreamsRepositoryForTesting(mMockRepository);
mInstance.performAction(mMockPreference, mMockController, mMockHelper);
ShadowLooper.idleMainLooper(ADD_SOURCE_WAIT_FOR_RESPONSE_TIMEOUT_MILLIS, TimeUnit.SECONDS);
verify(mMockHelper).addSource(mMockMetadata);
verify(mMockController).handleSourceFailedToConnect(BROADCAST_ID);
+ verify(mFeatureFactory.metricsFeatureProvider)
+ .action(
+ eq(mContext),
+ eq(SettingsEnums.ACTION_AUDIO_STREAM_JOIN),
+ eq(SourceOriginForLogging.QR_CODE_SCAN_SETTINGS.ordinal()));
+ verify(mMockRepository).cacheMetadata(mMockMetadata);
+ verify(mFeatureFactory.metricsFeatureProvider)
+ .action(
+ eq(mContext),
+ eq(SettingsEnums.ACTION_AUDIO_STREAM_JOIN_FAILED_TIMEOUT),
+ eq(SourceOriginForLogging.QR_CODE_SCAN_SETTINGS.ordinal()));
+ verify(mContext).getString(R.string.audio_streams_dialog_stream_is_not_available);
+ verify(mContext).getString(R.string.audio_streams_is_not_playing);
+ verify(mContext).getString(R.string.audio_streams_dialog_close);
}
}
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamStateHandlerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamStateHandlerTest.java
new file mode 100644
index 00000000000..adc77a183f6
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamStateHandlerTest.java
@@ -0,0 +1,143 @@
+/*
+ * 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.connecteddevice.audiosharing.audiostreams;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+
+import androidx.preference.Preference;
+import androidx.test.core.app.ApplicationProvider;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.robolectric.RobolectricTestRunner;
+
+@RunWith(RobolectricTestRunner.class)
+public class AudioStreamStateHandlerTest {
+ @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+ private static final int SUMMARY_RES = 1;
+ private static final String SUMMARY = "summary";
+ private final Context mContext = spy(ApplicationProvider.getApplicationContext());
+ @Mock private AudioStreamsProgressCategoryController mController;
+ @Mock private AudioStreamsHelper mHelper;
+ @Mock private AudioStreamPreference mPreference;
+ private AudioStreamStateHandler mHandler;
+
+ @Before
+ public void setUp() {
+ mHandler = spy(new AudioStreamStateHandler());
+ }
+
+ @Test
+ public void testHandleStateChange_noChange_doNothing() {
+ when(mHandler.getStateEnum())
+ .thenReturn(
+ AudioStreamsProgressCategoryController.AudioStreamState
+ .ADD_SOURCE_BAD_CODE);
+ when(mPreference.getAudioStreamState())
+ .thenReturn(
+ AudioStreamsProgressCategoryController.AudioStreamState
+ .ADD_SOURCE_BAD_CODE);
+
+ mHandler.handleStateChange(mPreference, mController, mHelper);
+
+ verify(mPreference, never()).setAudioStreamState(any());
+ verify(mHandler, never()).performAction(any(), any(), any());
+ verify(mPreference, never()).setIsConnected(anyBoolean(), anyString(), any());
+ }
+
+ @Test
+ public void testHandleStateChange_setNewState() {
+ when(mHandler.getStateEnum())
+ .thenReturn(AudioStreamsProgressCategoryController.AudioStreamState.SOURCE_ADDED);
+ when(mPreference.getAudioStreamState())
+ .thenReturn(
+ AudioStreamsProgressCategoryController.AudioStreamState
+ .ADD_SOURCE_BAD_CODE);
+
+ mHandler.handleStateChange(mPreference, mController, mHelper);
+
+ verify(mPreference)
+ .setAudioStreamState(
+ AudioStreamsProgressCategoryController.AudioStreamState.SOURCE_ADDED);
+ verify(mHandler).performAction(any(), any(), any());
+ verify(mPreference).setIsConnected(eq(true), eq(""), eq(null));
+ }
+
+ @Test
+ public void testHandleStateChange_setNewState_newSummary_newListener() {
+ Preference.OnPreferenceClickListener listener =
+ mock(Preference.OnPreferenceClickListener.class);
+ when(mHandler.getStateEnum())
+ .thenReturn(
+ AudioStreamsProgressCategoryController.AudioStreamState
+ .ADD_SOURCE_BAD_CODE);
+ when(mHandler.getSummary()).thenReturn(SUMMARY_RES);
+ when(mHandler.getOnClickListener(any())).thenReturn(listener);
+ when(mPreference.getAudioStreamState())
+ .thenReturn(
+ AudioStreamsProgressCategoryController.AudioStreamState.ADD_SOURCE_FAILED);
+ when(mPreference.getContext()).thenReturn(mContext);
+ doReturn(SUMMARY).when(mContext).getString(anyInt());
+
+ mHandler.handleStateChange(mPreference, mController, mHelper);
+
+ verify(mPreference)
+ .setAudioStreamState(
+ AudioStreamsProgressCategoryController.AudioStreamState
+ .ADD_SOURCE_BAD_CODE);
+ verify(mHandler).performAction(any(), any(), any());
+ verify(mPreference).setIsConnected(eq(false), eq(SUMMARY), eq(listener));
+ }
+
+ @Test
+ public void testGetSummary() {
+ int res = mHandler.getSummary();
+ assertThat(res).isEqualTo(AudioStreamStateHandler.EMPTY_STRING_RES);
+ }
+
+ @Test
+ public void testGetOnClickListener() {
+ Preference.OnPreferenceClickListener listener = mHandler.getOnClickListener(mController);
+ assertThat(listener).isNull();
+ }
+
+ @Test
+ public void testGetStateEnum() {
+ var state = mHandler.getStateEnum();
+ assertThat(state)
+ .isEqualTo(AudioStreamsProgressCategoryController.AudioStreamState.UNKNOWN);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamsActiveDeviceSummaryUpdaterTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamsActiveDeviceSummaryUpdaterTest.java
index 4403528e2fb..d6b99a1d3e3 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamsActiveDeviceSummaryUpdaterTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamsActiveDeviceSummaryUpdaterTest.java
@@ -20,6 +20,7 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.when;
+import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
@@ -76,25 +77,46 @@ public class AudioStreamsActiveDeviceSummaryUpdaterTest {
}
@Test
- public void onActiveDeviceChanged_notLeProfile_doNothing() {
- mUpdater.onActiveDeviceChanged(mCachedBluetoothDevice, 0);
+ public void unregister_doNothing() {
+ mUpdater.register(false);
assertThat(mUpdatedSummary).isNull();
}
@Test
- public void onActiveDeviceChanged_leProfile_summaryUpdated() {
+ public void onProfileConnectionStateChanged_notLeAssistProfile_doNothing() {
+ mUpdater.onProfileConnectionStateChanged(mCachedBluetoothDevice, 0, 0);
+
+ assertThat(mUpdatedSummary).isNull();
+ }
+
+ @Test
+ public void onProfileConnectionStateChanged_leAssistantProfile_summaryUpdated() {
ShadowAudioStreamsHelper.setCachedBluetoothDeviceInSharingOrLeConnected(
mCachedBluetoothDevice);
when(mCachedBluetoothDevice.getName()).thenReturn(DEVICE_NAME);
- mUpdater.onActiveDeviceChanged(mCachedBluetoothDevice, BluetoothProfile.LE_AUDIO);
+ mUpdater.onProfileConnectionStateChanged(
+ mCachedBluetoothDevice,
+ BluetoothAdapter.STATE_CONNECTED,
+ BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT);
assertThat(mUpdatedSummary).isEqualTo(DEVICE_NAME);
}
@Test
- public void onActiveDeviceChanged_leProfile_noDevice_summaryUpdated() {
- mUpdater.onActiveDeviceChanged(mCachedBluetoothDevice, BluetoothProfile.LE_AUDIO);
+ public void onActiveDeviceChanged_leAssistantProfile_noDevice_summaryUpdated() {
+ mUpdater.onProfileConnectionStateChanged(
+ mCachedBluetoothDevice,
+ BluetoothAdapter.STATE_CONNECTED,
+ BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT);
+
+ assertThat(mUpdatedSummary)
+ .isEqualTo(mContext.getString(R.string.audio_streams_dialog_no_le_device_title));
+ }
+
+ @Test
+ public void onBluetoothStateOff_summaryUpdated() {
+ mUpdater.onBluetoothStateChanged(BluetoothAdapter.STATE_OFF);
assertThat(mUpdatedSummary)
.isEqualTo(mContext.getString(R.string.audio_streams_dialog_no_le_device_title));
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamsCategoryControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamsCategoryControllerTest.java
index e4b6903e800..0e003097a3f 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamsCategoryControllerTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamsCategoryControllerTest.java
@@ -23,11 +23,13 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.robolectric.Shadows.shadowOf;
import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothStatusCodes;
import android.content.Context;
import android.os.Looper;
@@ -42,6 +44,7 @@ import com.android.settings.bluetooth.Utils;
import com.android.settings.connecteddevice.audiosharing.audiostreams.testshadows.ShadowAudioStreamsHelper;
import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
import com.android.settings.testutils.shadow.ShadowBluetoothUtils;
+import com.android.settingslib.bluetooth.BluetoothCallback;
import com.android.settingslib.bluetooth.BluetoothEventManager;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast;
@@ -57,6 +60,7 @@ import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
@@ -116,7 +120,7 @@ public class AudioStreamsCategoryControllerTest {
when(mBroadcast.isProfileReady()).thenReturn(true);
when(mAssistant.isProfileReady()).thenReturn(true);
when(mVolumeControl.isProfileReady()).thenReturn(true);
- mController = new AudioStreamsCategoryController(mContext, KEY);
+ mController = spy(new AudioStreamsCategoryController(mContext, KEY));
mPreference = new Preference(mContext);
when(mScreen.findPreference(KEY)).thenReturn(mPreference);
mController.displayPreference(mScreen);
@@ -228,4 +232,21 @@ public class AudioStreamsCategoryControllerTest {
shadowOf(Looper.getMainLooper()).idle();
assertThat(mPreference.isVisible()).isTrue();
}
+
+ @Test
+ public void onProfileConnectionStateChanged_updateVisibility() {
+ mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_QR_CODE_PRIVATE_BROADCAST_SHARING);
+ ArgumentCaptor argumentCaptor =
+ ArgumentCaptor.forClass(BluetoothCallback.class);
+ mController.onStart(mLifecycleOwner);
+ verify(mBluetoothEventManager).registerCallback(argumentCaptor.capture());
+
+ BluetoothCallback callback = argumentCaptor.getValue();
+ callback.onProfileConnectionStateChanged(
+ mCachedBluetoothDevice,
+ BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT,
+ BluetoothAdapter.STATE_DISCONNECTED);
+
+ verify(mController).updateVisibility();
+ }
}
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamsDialogFragmentTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamsDialogFragmentTest.java
new file mode 100644
index 00000000000..e83dade16e9
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamsDialogFragmentTest.java
@@ -0,0 +1,85 @@
+/*
+ * 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.connecteddevice.audiosharing.audiostreams;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+import android.app.settings.SettingsEnums;
+import android.content.Context;
+import android.os.Bundle;
+
+import androidx.test.core.app.ApplicationProvider;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowAlertDialog;
+import org.robolectric.shadows.ShadowLooper;
+import org.robolectric.shadows.androidx.fragment.FragmentController;
+
+@RunWith(RobolectricTestRunner.class)
+@Config(
+ shadows = {
+ ShadowAlertDialog.class,
+ })
+public class AudioStreamsDialogFragmentTest {
+ private final Context mContext = ApplicationProvider.getApplicationContext();
+ private AudioStreamsDialogFragment.DialogBuilder mDialogBuilder;
+ private AudioStreamsDialogFragment mFragment;
+
+ @Before
+ public void setUp() {
+ mDialogBuilder = spy(new AudioStreamsDialogFragment.DialogBuilder(mContext));
+ mFragment = new AudioStreamsDialogFragment(mDialogBuilder, SettingsEnums.PAGE_UNKNOWN);
+ }
+
+ @After
+ public void tearDown() {
+ ShadowAlertDialog.reset();
+ }
+
+ @Test
+ public void testGetMetricsCategory() {
+ int dialogId = mFragment.getMetricsCategory();
+
+ assertThat(dialogId).isEqualTo(SettingsEnums.PAGE_UNKNOWN);
+ }
+
+ @Test
+ public void testOnCreateDialog() {
+ mFragment.onCreateDialog(Bundle.EMPTY);
+
+ verify(mDialogBuilder).build();
+ }
+
+ @Test
+ public void testShowDialog() {
+ FragmentController.setupFragment(mFragment);
+ AudioStreamsDialogFragment.show(mFragment, mDialogBuilder, SettingsEnums.PAGE_UNKNOWN);
+ ShadowLooper.idleMainLooper();
+
+ var dialog = ShadowAlertDialog.getLatestAlertDialog();
+ assertThat(dialog).isNotNull();
+ assertThat(dialog.isShowing()).isTrue();
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamsProgressCategoryCallbackTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamsProgressCategoryCallbackTest.java
new file mode 100644
index 00000000000..164c2f093e8
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamsProgressCategoryCallbackTest.java
@@ -0,0 +1,140 @@
+/*
+ * 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.connecteddevice.audiosharing.audiostreams;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothLeBroadcastMetadata;
+import android.bluetooth.BluetoothLeBroadcastReceiveState;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.robolectric.RobolectricTestRunner;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@RunWith(RobolectricTestRunner.class)
+public class AudioStreamsProgressCategoryCallbackTest {
+ @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+ @Mock private AudioStreamsProgressCategoryController mController;
+ @Mock private BluetoothDevice mDevice;
+ @Mock private BluetoothLeBroadcastReceiveState mState;
+ @Mock private BluetoothLeBroadcastMetadata mMetadata;
+ private AudioStreamsProgressCategoryCallback mCallback;
+
+ @Before
+ public void setUp() {
+ mCallback = new AudioStreamsProgressCategoryCallback(mController);
+ }
+
+ @Test
+ public void testOnReceiveStateChanged_connected() {
+ List bisSyncState = new ArrayList<>();
+ bisSyncState.add(1L);
+ when(mState.getBisSyncState()).thenReturn(bisSyncState);
+ mCallback.onReceiveStateChanged(mDevice, /* sourceId= */ 0, mState);
+
+ verify(mController).handleSourceConnected(any());
+ }
+
+ @Test
+ public void testOnReceiveStateChanged_badCode() {
+ when(mState.getPaSyncState())
+ .thenReturn(BluetoothLeBroadcastReceiveState.PA_SYNC_STATE_SYNCHRONIZED);
+ when(mState.getBigEncryptionState())
+ .thenReturn(BluetoothLeBroadcastReceiveState.BIG_ENCRYPTION_STATE_BAD_CODE);
+ mCallback.onReceiveStateChanged(mDevice, /* sourceId= */ 0, mState);
+
+ verify(mController).handleSourceConnectBadCode(any());
+ }
+
+ @Test
+ public void testOnSearchStartFailed() {
+ mCallback.onSearchStartFailed(/* reason= */ 0);
+
+ verify(mController).showToast(anyString());
+ verify(mController).setScanning(anyBoolean());
+ }
+
+ @Test
+ public void testOnSearchStarted() {
+ mCallback.onSearchStarted(/* reason= */ 0);
+
+ verify(mController).setScanning(anyBoolean());
+ }
+
+ @Test
+ public void testOnSearchStopFailed() {
+ mCallback.onSearchStopFailed(/* reason= */ 0);
+
+ verify(mController).showToast(anyString());
+ }
+
+ @Test
+ public void testOnSearchStopped() {
+ mCallback.onSearchStopped(/* reason= */ 0);
+
+ verify(mController).setScanning(anyBoolean());
+ }
+
+ @Test
+ public void testOnSourceAddFailed() {
+ when(mMetadata.getBroadcastId()).thenReturn(1);
+ mCallback.onSourceAddFailed(mDevice, mMetadata, /* reason= */ 0);
+
+ verify(mController).handleSourceFailedToConnect(1);
+ }
+
+ @Test
+ public void testOnSourceFound() {
+ mCallback.onSourceFound(mMetadata);
+
+ verify(mController).handleSourceFound(mMetadata);
+ }
+
+ @Test
+ public void testOnSourceLost() {
+ mCallback.onSourceLost(/* broadcastId= */ 1);
+
+ verify(mController).handleSourceLost(1);
+ }
+
+ @Test
+ public void testOnSourceRemoveFailed() {
+ mCallback.onSourceRemoveFailed(mDevice, /* sourceId= */ 0, /* reason= */ 0);
+
+ verify(mController).showToast(anyString());
+ }
+
+ @Test
+ public void testOnSourceRemoved() {
+ mCallback.onSourceRemoved(mDevice, /* sourceId= */ 0, /* reason= */ 0);
+
+ verify(mController).handleSourceRemoved();
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamsProgressCategoryControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamsProgressCategoryControllerTest.java
new file mode 100644
index 00000000000..d43ec81ddaf
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamsProgressCategoryControllerTest.java
@@ -0,0 +1,671 @@
+/*
+ * 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.connecteddevice.audiosharing.audiostreams;
+
+import static com.android.settings.connecteddevice.audiosharing.audiostreams.AudioStreamsProgressCategoryController.AudioStreamState.ADD_SOURCE_BAD_CODE;
+import static com.android.settings.connecteddevice.audiosharing.audiostreams.AudioStreamsProgressCategoryController.AudioStreamState.ADD_SOURCE_FAILED;
+import static com.android.settings.connecteddevice.audiosharing.audiostreams.AudioStreamsProgressCategoryController.AudioStreamState.ADD_SOURCE_WAIT_FOR_RESPONSE;
+import static com.android.settings.connecteddevice.audiosharing.audiostreams.AudioStreamsProgressCategoryController.AudioStreamState.SOURCE_ADDED;
+import static com.android.settings.connecteddevice.audiosharing.audiostreams.AudioStreamsProgressCategoryController.AudioStreamState.SYNCED;
+import static com.android.settings.connecteddevice.audiosharing.audiostreams.AudioStreamsProgressCategoryController.AudioStreamState.WAIT_FOR_SYNC;
+import static com.android.settings.connecteddevice.audiosharing.audiostreams.AudioStreamsProgressCategoryController.UNSET_BROADCAST_ID;
+import static com.android.settings.core.BasePreferenceController.AVAILABLE;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.robolectric.Shadows.shadowOf;
+
+import static java.util.Collections.emptyList;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothLeAudioContentMetadata;
+import android.bluetooth.BluetoothLeBroadcastMetadata;
+import android.bluetooth.BluetoothLeBroadcastReceiveState;
+import android.bluetooth.BluetoothProfile;
+import android.content.Context;
+import android.os.Looper;
+import android.view.View;
+import android.widget.Button;
+import android.widget.TextView;
+
+import androidx.fragment.app.Fragment;
+import androidx.lifecycle.LifecycleOwner;
+import androidx.preference.PreferenceScreen;
+import androidx.test.core.app.ApplicationProvider;
+
+import com.android.settings.R;
+import com.android.settings.connecteddevice.audiosharing.audiostreams.testshadows.ShadowAudioStreamsHelper;
+import com.android.settings.testutils.shadow.ShadowBluetoothUtils;
+import com.android.settings.testutils.shadow.ShadowThreadUtils;
+import com.android.settingslib.bluetooth.BluetoothEventManager;
+import com.android.settingslib.bluetooth.BluetoothLeBroadcastMetadataExt;
+import com.android.settingslib.bluetooth.CachedBluetoothDevice;
+import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant;
+import com.android.settingslib.bluetooth.LocalBluetoothManager;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+import com.google.common.collect.ImmutableList;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowAlertDialog;
+import org.robolectric.shadows.androidx.fragment.FragmentController;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@RunWith(RobolectricTestRunner.class)
+@Config(
+ shadows = {
+ ShadowBluetoothUtils.class,
+ ShadowAudioStreamsHelper.class,
+ ShadowThreadUtils.class,
+ ShadowAlertDialog.class,
+ })
+public class AudioStreamsProgressCategoryControllerTest {
+ @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+ private static final String VALID_METADATA =
+ "BLUETOOTH:UUID:184F;BN:VGVzdA==;AT:1;AD:00A1A1A1A1A1;BI:1E240;BC:VGVzdENvZGU=;"
+ + "MD:BgNwVGVzdA==;AS:1;PI:A0;NS:1;BS:3;NB:2;SM:BQNUZXN0BARlbmc=;;";
+ private static final String KEY = "audio_streams_nearby_category";
+ private static final int QR_CODE_BROADCAST_ID = 1;
+ private static final int ALREADY_CONNECTED_BROADCAST_ID = 2;
+ private static final int NEWLY_FOUND_BROADCAST_ID = 3;
+ private static final String BROADCAST_NAME_1 = "name_1";
+ private static final String BROADCAST_NAME_2 = "name_2";
+ private static final byte[] BROADCAST_CODE = new byte[] {1};
+ private final Context mContext = ApplicationProvider.getApplicationContext();
+ @Mock private LocalBluetoothManager mLocalBtManager;
+ @Mock private BluetoothEventManager mBluetoothEventManager;
+ @Mock private PreferenceScreen mScreen;
+ @Mock private AudioStreamsHelper mAudioStreamsHelper;
+ @Mock private LocalBluetoothLeBroadcastAssistant mLeBroadcastAssistant;
+ @Mock private BluetoothLeBroadcastMetadata mMetadata;
+ @Mock private CachedBluetoothDevice mDevice;
+ @Mock private AudioStreamsProgressCategoryPreference mPreference;
+ private Lifecycle mLifecycle;
+ private LifecycleOwner mLifecycleOwner;
+ private Fragment mFragment;
+ private TestController mController;
+
+ @Before
+ public void setUp() {
+ ShadowAudioStreamsHelper.setUseMock(mAudioStreamsHelper);
+ when(mAudioStreamsHelper.getLeBroadcastAssistant()).thenReturn(mLeBroadcastAssistant);
+ when(mAudioStreamsHelper.getAllConnectedSources()).thenReturn(emptyList());
+
+ ShadowBluetoothUtils.sLocalBluetoothManager = mLocalBtManager;
+ when(mLocalBtManager.getEventManager()).thenReturn(mBluetoothEventManager);
+ when(mLeBroadcastAssistant.isSearchInProgress()).thenReturn(false);
+
+ when(mScreen.findPreference(anyString())).thenReturn(mPreference);
+
+ mLifecycleOwner = () -> mLifecycle;
+ mLifecycle = new Lifecycle(mLifecycleOwner);
+
+ mFragment = new Fragment();
+ mController = spy(new TestController(mContext, KEY));
+ }
+
+ @After
+ public void tearDown() {
+ ShadowBluetoothUtils.reset();
+ ShadowAudioStreamsHelper.reset();
+ }
+
+ @Test
+ public void testGetAvailabilityStatus() {
+ int status = mController.getAvailabilityStatus();
+
+ assertThat(status).isEqualTo(AVAILABLE);
+ }
+
+ @Test
+ public void testDisplayPreference() {
+ mController.displayPreference(mScreen);
+
+ verify(mPreference).setVisible(true);
+ }
+
+ @Test
+ public void testSetScanning() {
+ mController.displayPreference(mScreen);
+ mController.setScanning(true);
+
+ verify(mPreference).setProgress(true);
+ }
+
+ @Test
+ public void testOnStart_initNoDevice_showDialog() {
+ when(mLeBroadcastAssistant.isSearchInProgress()).thenReturn(true);
+
+ FragmentController.setupFragment(mFragment);
+ mController.setFragment(mFragment);
+ mController.displayPreference(mScreen);
+ mController.onStart(mLifecycleOwner);
+ shadowOf(Looper.getMainLooper()).idle();
+
+ // Called twice, once in displayPreference, the other in init()
+ verify(mPreference, times(2)).setVisible(anyBoolean());
+ verify(mPreference).removeAudioStreamPreferences();
+ verify(mLeBroadcastAssistant).stopSearchingForSources();
+ verify(mLeBroadcastAssistant).unregisterServiceCallBack(any());
+
+ var dialog = ShadowAlertDialog.getLatestAlertDialog();
+ assertThat(dialog).isNotNull();
+ assertThat(dialog.isShowing()).isTrue();
+
+ TextView title = dialog.findViewById(R.id.dialog_title);
+ assertThat(title).isNotNull();
+ assertThat(title.getText())
+ .isEqualTo(mContext.getString(R.string.audio_streams_dialog_no_le_device_title));
+ TextView subtitle1 = dialog.findViewById(R.id.dialog_subtitle);
+ assertThat(subtitle1).isNotNull();
+ assertThat(subtitle1.getVisibility()).isEqualTo(View.GONE);
+ TextView subtitle2 = dialog.findViewById(R.id.dialog_subtitle_2);
+ assertThat(subtitle2).isNotNull();
+ assertThat(subtitle2.getText())
+ .isEqualTo(mContext.getString(R.string.audio_streams_dialog_no_le_device_subtitle));
+ View leftButton = dialog.findViewById(R.id.left_button);
+ assertThat(leftButton).isNotNull();
+ assertThat(leftButton.getVisibility()).isEqualTo(View.VISIBLE);
+ Button rightButton = dialog.findViewById(R.id.right_button);
+ assertThat(rightButton).isNotNull();
+ assertThat(rightButton.getText())
+ .isEqualTo(mContext.getString(R.string.audio_streams_dialog_no_le_device_button));
+ assertThat(rightButton.hasOnClickListeners()).isTrue();
+
+ dialog.cancel();
+ }
+
+ @Test
+ public void testBluetoothOff_triggerRunnable() {
+ mController.mBluetoothCallback.onBluetoothStateChanged(BluetoothAdapter.STATE_OFF);
+
+ verify(mController.mExecutor).execute(any());
+ }
+
+ @Test
+ public void testDeviceConnectionStateChanged_triggerRunnable() {
+ mController.mBluetoothCallback.onProfileConnectionStateChanged(
+ mDevice,
+ BluetoothAdapter.STATE_DISCONNECTED,
+ BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT);
+
+ verify(mController.mExecutor).execute(any());
+ }
+
+ @Test
+ public void testOnStart_initHasDevice_noPreference() {
+ // Setup a device
+ ShadowAudioStreamsHelper.setCachedBluetoothDeviceInSharingOrLeConnected(mDevice);
+
+ mController.onStart(mLifecycleOwner);
+ shadowOf(Looper.getMainLooper()).idle();
+
+ verify(mLeBroadcastAssistant).registerServiceCallBack(any(), any());
+ verify(mLeBroadcastAssistant).startSearchingForSources(any());
+
+ var dialog = ShadowAlertDialog.getLatestAlertDialog();
+ assertThat(dialog).isNull();
+
+ verify(mController, never()).moveToState(any(), any());
+ }
+
+ @Test
+ public void testOnStart_handleSourceFromQrCode() {
+ // Setup a device
+ ShadowAudioStreamsHelper.setCachedBluetoothDeviceInSharingOrLeConnected(mDevice);
+
+ // Setup a source from qr code
+ mController.setSourceFromQrCode(mMetadata, SourceOriginForLogging.UNKNOWN);
+ when(mMetadata.getBroadcastId()).thenReturn(QR_CODE_BROADCAST_ID);
+
+ // Handle the source from qr code in onStart
+ mController.displayPreference(mScreen);
+ mController.onStart(mLifecycleOwner);
+ shadowOf(Looper.getMainLooper()).idle();
+
+ // Verify the connected source is created and moved to WAIT_FOR_SYNC
+ ArgumentCaptor preference =
+ ArgumentCaptor.forClass(AudioStreamPreference.class);
+ ArgumentCaptor state =
+ ArgumentCaptor.forClass(
+ AudioStreamsProgressCategoryController.AudioStreamState.class);
+
+ verify(mController).moveToState(preference.capture(), state.capture());
+ assertThat(preference.getValue()).isNotNull();
+ assertThat(preference.getValue().getAudioStreamBroadcastId())
+ .isEqualTo(QR_CODE_BROADCAST_ID);
+ assertThat(state.getValue()).isEqualTo(WAIT_FOR_SYNC);
+ }
+
+ @Test
+ public void testOnStart_handleSourceAlreadyConnected() {
+ // Setup a device
+ ShadowAudioStreamsHelper.setCachedBluetoothDeviceInSharingOrLeConnected(mDevice);
+
+ // Setup a connected source
+ BluetoothLeBroadcastReceiveState connected =
+ createConnectedMock(ALREADY_CONNECTED_BROADCAST_ID);
+ List list = new ArrayList<>();
+ list.add(connected);
+ when(mAudioStreamsHelper.getAllConnectedSources()).thenReturn(list);
+
+ // Handle already connected source in onStart
+ mController.displayPreference(mScreen);
+ mController.onStart(mLifecycleOwner);
+ shadowOf(Looper.getMainLooper()).idle();
+
+ ArgumentCaptor preference =
+ ArgumentCaptor.forClass(AudioStreamPreference.class);
+ ArgumentCaptor state =
+ ArgumentCaptor.forClass(
+ AudioStreamsProgressCategoryController.AudioStreamState.class);
+
+ // Verify the connected source is created and moved to SOURCE_ADDED
+ verify(mController).moveToState(preference.capture(), state.capture());
+ assertThat(preference.getValue()).isNotNull();
+ assertThat(preference.getValue().getAudioStreamBroadcastId())
+ .isEqualTo(ALREADY_CONNECTED_BROADCAST_ID);
+ assertThat(state.getValue()).isEqualTo(SOURCE_ADDED);
+ }
+
+ @Test
+ public void testOnStart_sourceFromQrCodeNoId_sourceAlreadyConnected_sameName_updateId() {
+ // Setup a device
+ ShadowAudioStreamsHelper.setCachedBluetoothDeviceInSharingOrLeConnected(mDevice);
+
+ // Setup source from qr code with unset id and BROADCAST_NAME_1. Creating a real metadata
+ // for properly update its id.
+ var metadata =
+ BluetoothLeBroadcastMetadataExt.INSTANCE.convertToBroadcastMetadata(VALID_METADATA);
+ assertThat(metadata).isNotNull();
+ var metadataWithNoIdAndSameName =
+ new BluetoothLeBroadcastMetadata.Builder(metadata)
+ .setBroadcastId(UNSET_BROADCAST_ID)
+ .setBroadcastName(BROADCAST_NAME_1)
+ .build();
+ mController.setSourceFromQrCode(
+ metadataWithNoIdAndSameName, SourceOriginForLogging.UNKNOWN);
+
+ // Setup a connected source with name BROADCAST_NAME_1 and id
+ BluetoothLeBroadcastReceiveState connected =
+ createConnectedMock(ALREADY_CONNECTED_BROADCAST_ID);
+ var data = mock(BluetoothLeAudioContentMetadata.class);
+ when(connected.getSubgroupMetadata()).thenReturn(ImmutableList.of(data));
+ when(data.getProgramInfo()).thenReturn(BROADCAST_NAME_1);
+ when(mAudioStreamsHelper.getAllConnectedSources()).thenReturn(ImmutableList.of(connected));
+
+ // Handle both source from qr code and already connected source in onStart
+ mController.displayPreference(mScreen);
+ mController.onStart(mLifecycleOwner);
+ shadowOf(Looper.getMainLooper()).idle();
+
+ // Verify two preferences created, one moved to state WAIT_FOR_SYNC, one to SOURCE_ADDED.
+ // Both has ALREADY_CONNECTED_BROADCAST_ID as the UNSET_ID is updated to match.
+ ArgumentCaptor preference =
+ ArgumentCaptor.forClass(AudioStreamPreference.class);
+ ArgumentCaptor state =
+ ArgumentCaptor.forClass(
+ AudioStreamsProgressCategoryController.AudioStreamState.class);
+ verify(mController, times(2)).moveToState(preference.capture(), state.capture());
+
+ List preferences = preference.getAllValues();
+ assertThat(preferences.size()).isEqualTo(2);
+ List states = state.getAllValues();
+ assertThat(states.size()).isEqualTo(2);
+
+ // The preference contains source from qr code
+ assertThat(preferences.get(0).getAudioStreamBroadcastId())
+ .isEqualTo(ALREADY_CONNECTED_BROADCAST_ID);
+ assertThat(states.get(0)).isEqualTo(WAIT_FOR_SYNC);
+
+ // The preference contains already connected source
+ assertThat(preferences.get(1).getAudioStreamBroadcastId())
+ .isEqualTo(ALREADY_CONNECTED_BROADCAST_ID);
+ assertThat(states.get(1)).isEqualTo(SOURCE_ADDED);
+ }
+
+ @Test
+ public void testHandleSourceFound_addNew() {
+ // Setup a device
+ ShadowAudioStreamsHelper.setCachedBluetoothDeviceInSharingOrLeConnected(mDevice);
+
+ when(mMetadata.getBroadcastId()).thenReturn(NEWLY_FOUND_BROADCAST_ID);
+ // A new source is found
+ mController.handleSourceFound(mMetadata);
+
+ // Verify a preference is created with state SYNCED.
+ ArgumentCaptor preference =
+ ArgumentCaptor.forClass(AudioStreamPreference.class);
+ ArgumentCaptor state =
+ ArgumentCaptor.forClass(
+ AudioStreamsProgressCategoryController.AudioStreamState.class);
+
+ verify(mController).moveToState(preference.capture(), state.capture());
+ assertThat(preference.getValue()).isNotNull();
+ assertThat(preference.getValue().getAudioStreamBroadcastId())
+ .isEqualTo(NEWLY_FOUND_BROADCAST_ID);
+ assertThat(state.getValue()).isEqualTo(SYNCED);
+ }
+
+ @Test
+ public void testHandleSourceFound_sameIdWithSourceFromQrCode_updateMetadataAndState() {
+ // Setup a device
+ ShadowAudioStreamsHelper.setCachedBluetoothDeviceInSharingOrLeConnected(mDevice);
+
+ // Setup source from qr code with QR_CODE_BROADCAST_ID, BROADCAST_NAME_1 and BROADCAST_CODE.
+ var metadata =
+ BluetoothLeBroadcastMetadataExt.INSTANCE.convertToBroadcastMetadata(VALID_METADATA);
+ assertThat(metadata).isNotNull();
+ var metadataFromQrCode =
+ new BluetoothLeBroadcastMetadata.Builder(metadata)
+ .setBroadcastId(QR_CODE_BROADCAST_ID)
+ .setBroadcastName(BROADCAST_NAME_1)
+ .setBroadcastCode(BROADCAST_CODE)
+ .build();
+ mController.setSourceFromQrCode(metadataFromQrCode, SourceOriginForLogging.UNKNOWN);
+
+ // Handle the source from qr code in onStart
+ mController.displayPreference(mScreen);
+ mController.onStart(mLifecycleOwner);
+ shadowOf(Looper.getMainLooper()).idle();
+
+ // A new source is found
+ mController.handleSourceFound(
+ new BluetoothLeBroadcastMetadata.Builder(metadata)
+ .setBroadcastId(QR_CODE_BROADCAST_ID)
+ .setBroadcastName(BROADCAST_NAME_2)
+ .build());
+ shadowOf(Looper.getMainLooper()).idle();
+
+ ArgumentCaptor preference =
+ ArgumentCaptor.forClass(AudioStreamPreference.class);
+ ArgumentCaptor state =
+ ArgumentCaptor.forClass(
+ AudioStreamsProgressCategoryController.AudioStreamState.class);
+
+ verify(mController, times(2)).moveToState(preference.capture(), state.capture());
+ List preferences = preference.getAllValues();
+ List states = state.getAllValues();
+
+ // Verify the qr code source is created with WAIT_FOR_SYNC, broadcast name got updated to
+ // BROADCAST_NAME_2
+ var sourceFromQrCode = preferences.get(0);
+ assertThat(sourceFromQrCode.getAudioStreamBroadcastId()).isEqualTo(QR_CODE_BROADCAST_ID);
+ assertThat(sourceFromQrCode.getAudioStreamMetadata()).isNotNull();
+ assertThat(sourceFromQrCode.getAudioStreamMetadata().getBroadcastName())
+ .isEqualTo(BROADCAST_NAME_2);
+ assertThat(sourceFromQrCode.getAudioStreamMetadata().getBroadcastCode())
+ .isEqualTo(BROADCAST_CODE);
+ assertThat(states.get(0)).isEqualTo(WAIT_FOR_SYNC);
+
+ // Verify the newly found source is created, broadcast code is retrieved from the source
+ // from qr code, and state updated to ADD_SOURCE_WAIT_FOR_RESPONSE
+ var newlyFoundSource = preferences.get(1);
+ assertThat(newlyFoundSource.getAudioStreamBroadcastId()).isEqualTo(QR_CODE_BROADCAST_ID);
+ assertThat(newlyFoundSource.getAudioStreamMetadata()).isNotNull();
+ assertThat(newlyFoundSource.getAudioStreamMetadata().getBroadcastName())
+ .isEqualTo(BROADCAST_NAME_2);
+ assertThat(newlyFoundSource.getAudioStreamMetadata().getBroadcastCode())
+ .isEqualTo(BROADCAST_CODE);
+ assertThat(states.get(1)).isEqualTo(ADD_SOURCE_WAIT_FOR_RESPONSE);
+ }
+
+ @Test
+ public void testHandleSourceFound_sameIdWithOtherState_doNothing() {
+ // Setup a device
+ ShadowAudioStreamsHelper.setCachedBluetoothDeviceInSharingOrLeConnected(mDevice);
+
+ // Setup source already connected
+ BluetoothLeBroadcastReceiveState connected =
+ createConnectedMock(ALREADY_CONNECTED_BROADCAST_ID);
+ when(mAudioStreamsHelper.getAllConnectedSources()).thenReturn(ImmutableList.of(connected));
+
+ // Handle source already connected in onStart
+ mController.displayPreference(mScreen);
+ mController.onStart(mLifecycleOwner);
+ shadowOf(Looper.getMainLooper()).idle();
+
+ // A new source found
+ when(mMetadata.getBroadcastId()).thenReturn(ALREADY_CONNECTED_BROADCAST_ID);
+ mController.handleSourceFound(mMetadata);
+ shadowOf(Looper.getMainLooper()).idle();
+
+ // Verify only the connected source has created a preference, and its state remains as
+ // SOURCE_ADDED
+ ArgumentCaptor preference =
+ ArgumentCaptor.forClass(AudioStreamPreference.class);
+ ArgumentCaptor state =
+ ArgumentCaptor.forClass(
+ AudioStreamsProgressCategoryController.AudioStreamState.class);
+
+ verify(mController).moveToState(preference.capture(), state.capture());
+ assertThat(preference.getValue()).isNotNull();
+ assertThat(preference.getValue().getAudioStreamBroadcastId())
+ .isEqualTo(ALREADY_CONNECTED_BROADCAST_ID);
+ assertThat(preference.getValue().getAudioStreamState()).isEqualTo(SOURCE_ADDED);
+ }
+
+ @Test
+ public void testHandleSourceLost_removed() {
+ // Setup a device
+ ShadowAudioStreamsHelper.setCachedBluetoothDeviceInSharingOrLeConnected(mDevice);
+
+ // Setup mPreference so it's not null
+ mController.displayPreference(mScreen);
+
+ // A new source found
+ when(mMetadata.getBroadcastId()).thenReturn(NEWLY_FOUND_BROADCAST_ID);
+ mController.handleSourceFound(mMetadata);
+ shadowOf(Looper.getMainLooper()).idle();
+
+ // A new source found is lost
+ mController.handleSourceLost(NEWLY_FOUND_BROADCAST_ID);
+ shadowOf(Looper.getMainLooper()).idle();
+
+ ArgumentCaptor preferenceToAdd =
+ ArgumentCaptor.forClass(AudioStreamPreference.class);
+ ArgumentCaptor preferenceToRemove =
+ ArgumentCaptor.forClass(AudioStreamPreference.class);
+ ArgumentCaptor state =
+ ArgumentCaptor.forClass(
+ AudioStreamsProgressCategoryController.AudioStreamState.class);
+
+ // Verify a new preference is created with state SYNCED.
+ verify(mController).moveToState(preferenceToAdd.capture(), state.capture());
+ assertThat(preferenceToAdd.getValue()).isNotNull();
+ assertThat(preferenceToAdd.getValue().getAudioStreamBroadcastId())
+ .isEqualTo(NEWLY_FOUND_BROADCAST_ID);
+ assertThat(state.getValue()).isEqualTo(SYNCED);
+
+ // Verify the preference with NEWLY_FOUND_BROADCAST_ID is removed.
+ verify(mPreference).removePreference(preferenceToRemove.capture());
+ assertThat(preferenceToRemove.getValue().getAudioStreamBroadcastId())
+ .isEqualTo(NEWLY_FOUND_BROADCAST_ID);
+ }
+
+ @Test
+ public void testHandleSourceRemoved_removed() {
+ // Setup a device
+ ShadowAudioStreamsHelper.setCachedBluetoothDeviceInSharingOrLeConnected(mDevice);
+
+ // Setup already connected source
+ BluetoothLeBroadcastReceiveState connected =
+ createConnectedMock(ALREADY_CONNECTED_BROADCAST_ID);
+ when(mAudioStreamsHelper.getAllConnectedSources()).thenReturn(ImmutableList.of(connected));
+
+ // Handle connected source in onStart
+ mController.displayPreference(mScreen);
+ mController.onStart(mLifecycleOwner);
+ shadowOf(Looper.getMainLooper()).idle();
+
+ // The connect source is no longer connected
+ when(mAudioStreamsHelper.getAllConnectedSources()).thenReturn(emptyList());
+ mController.handleSourceRemoved();
+ shadowOf(Looper.getMainLooper()).idle();
+
+ ArgumentCaptor preferenceToAdd =
+ ArgumentCaptor.forClass(AudioStreamPreference.class);
+ ArgumentCaptor preferenceToRemove =
+ ArgumentCaptor.forClass(AudioStreamPreference.class);
+ ArgumentCaptor state =
+ ArgumentCaptor.forClass(
+ AudioStreamsProgressCategoryController.AudioStreamState.class);
+
+ // Verify a new preference is created with state SOURCE_ADDED.
+ verify(mController).moveToState(preferenceToAdd.capture(), state.capture());
+ assertThat(preferenceToAdd.getValue()).isNotNull();
+ assertThat(preferenceToAdd.getValue().getAudioStreamBroadcastId())
+ .isEqualTo(ALREADY_CONNECTED_BROADCAST_ID);
+ assertThat(state.getValue()).isEqualTo(SOURCE_ADDED);
+
+ // Verify the preference with ALREADY_CONNECTED_BROADCAST_ID is removed.
+ verify(mPreference).removePreference(preferenceToRemove.capture());
+ assertThat(preferenceToRemove.getValue().getAudioStreamBroadcastId())
+ .isEqualTo(ALREADY_CONNECTED_BROADCAST_ID);
+ }
+
+ @Test
+ public void testHandleSourceRemoved_updateState() {
+ // Setup a device
+ ShadowAudioStreamsHelper.setCachedBluetoothDeviceInSharingOrLeConnected(mDevice);
+
+ // Setup a connected source
+ BluetoothLeBroadcastReceiveState connected =
+ createConnectedMock(ALREADY_CONNECTED_BROADCAST_ID);
+ when(mAudioStreamsHelper.getAllConnectedSources()).thenReturn(ImmutableList.of(connected));
+
+ // Handle connected source in onStart
+ mController.displayPreference(mScreen);
+ mController.onStart(mLifecycleOwner);
+ shadowOf(Looper.getMainLooper()).idle();
+
+ // The connected source is identified as having a bad code
+ BluetoothLeBroadcastReceiveState badCode = mock(BluetoothLeBroadcastReceiveState.class);
+ when(badCode.getBroadcastId()).thenReturn(ALREADY_CONNECTED_BROADCAST_ID);
+ when(badCode.getPaSyncState())
+ .thenReturn(BluetoothLeBroadcastReceiveState.PA_SYNC_STATE_SYNCHRONIZED);
+ when(badCode.getBigEncryptionState())
+ .thenReturn(BluetoothLeBroadcastReceiveState.BIG_ENCRYPTION_STATE_BAD_CODE);
+ mController.handleSourceConnectBadCode(badCode);
+ shadowOf(Looper.getMainLooper()).idle();
+
+ ArgumentCaptor preference =
+ ArgumentCaptor.forClass(AudioStreamPreference.class);
+ ArgumentCaptor state =
+ ArgumentCaptor.forClass(
+ AudioStreamsProgressCategoryController.AudioStreamState.class);
+
+ verify(mController, times(2)).moveToState(preference.capture(), state.capture());
+ List preferences = preference.getAllValues();
+ assertThat(preferences.size()).isEqualTo(2);
+ List states = state.getAllValues();
+ assertThat(states.size()).isEqualTo(2);
+
+ // Verify the connected source is created state SOURCE_ADDED
+ assertThat(preferences.get(0).getAudioStreamBroadcastId())
+ .isEqualTo(ALREADY_CONNECTED_BROADCAST_ID);
+ assertThat(states.get(0)).isEqualTo(SOURCE_ADDED);
+
+ // Verify the connected source is updated to state ADD_SOURCE_BAD_CODE
+ assertThat(preferences.get(1).getAudioStreamBroadcastId())
+ .isEqualTo(ALREADY_CONNECTED_BROADCAST_ID);
+ assertThat(states.get(1)).isEqualTo(ADD_SOURCE_BAD_CODE);
+ }
+
+ @Test
+ public void testHandleSourceFailedToConnect_updateState() {
+ // Setup a device
+ ShadowAudioStreamsHelper.setCachedBluetoothDeviceInSharingOrLeConnected(mDevice);
+
+ // Setup mPreference so it's not null
+ mController.displayPreference(mScreen);
+
+ // A new source found
+ when(mMetadata.getBroadcastId()).thenReturn(NEWLY_FOUND_BROADCAST_ID);
+ mController.handleSourceFound(mMetadata);
+ shadowOf(Looper.getMainLooper()).idle();
+
+ // The new found source is identified as failed to connect
+ mController.handleSourceFailedToConnect(NEWLY_FOUND_BROADCAST_ID);
+ shadowOf(Looper.getMainLooper()).idle();
+
+ ArgumentCaptor preference =
+ ArgumentCaptor.forClass(AudioStreamPreference.class);
+ ArgumentCaptor state =
+ ArgumentCaptor.forClass(
+ AudioStreamsProgressCategoryController.AudioStreamState.class);
+
+ verify(mController, times(2)).moveToState(preference.capture(), state.capture());
+ List preferences = preference.getAllValues();
+ assertThat(preferences.size()).isEqualTo(2);
+ List states = state.getAllValues();
+ assertThat(states.size()).isEqualTo(2);
+
+ // Verify one preference is created with SYNCED
+ assertThat(preferences.get(0).getAudioStreamBroadcastId())
+ .isEqualTo(NEWLY_FOUND_BROADCAST_ID);
+ assertThat(states.get(0)).isEqualTo(SYNCED);
+
+ // Verify the preference is updated to state ADD_SOURCE_FAILED
+ assertThat(preferences.get(1).getAudioStreamBroadcastId())
+ .isEqualTo(NEWLY_FOUND_BROADCAST_ID);
+ assertThat(states.get(1)).isEqualTo(ADD_SOURCE_FAILED);
+ }
+
+ private static BluetoothLeBroadcastReceiveState createConnectedMock(int id) {
+ var connected = mock(BluetoothLeBroadcastReceiveState.class);
+ List bisSyncState = new ArrayList<>();
+ bisSyncState.add(1L);
+ when(connected.getBroadcastId()).thenReturn(id);
+ when(connected.getBisSyncState()).thenReturn(bisSyncState);
+ return connected;
+ }
+
+ static class TestController extends AudioStreamsProgressCategoryController {
+ TestController(Context context, String preferenceKey) {
+ super(context, preferenceKey);
+ mExecutor = spy(mContext.getMainExecutor());
+ }
+
+ @Override
+ void moveToState(AudioStreamPreference preference, AudioStreamState state) {
+ preference.setAudioStreamState(state);
+ // Do nothing else to avoid side effect from AudioStreamStateHandler#performAction
+ }
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamsScanQrCodeControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamsScanQrCodeControllerTest.java
index 4990f26ac22..a83cbf03379 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamsScanQrCodeControllerTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamsScanQrCodeControllerTest.java
@@ -16,29 +16,38 @@
package com.android.settings.connecteddevice.audiosharing.audiostreams;
+import static android.app.settings.SettingsEnums.AUDIO_STREAM_MAIN;
+
+import static com.android.settings.connecteddevice.audiosharing.audiostreams.AudioStreamsScanQrCodeController.REQUEST_SCAN_BT_BROADCAST_QR_CODE;
import static com.android.settings.core.BasePreferenceController.AVAILABLE;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
+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.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
+import android.content.Intent;
import androidx.lifecycle.LifecycleOwner;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import androidx.test.core.app.ApplicationProvider;
+import com.android.settings.R;
+import com.android.settings.SettingsActivity;
import com.android.settings.connecteddevice.audiosharing.audiostreams.testshadows.ShadowAudioStreamsHelper;
import com.android.settings.testutils.shadow.ShadowBluetoothUtils;
import com.android.settingslib.bluetooth.BluetoothEventManager;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
+import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
import com.android.settingslib.core.lifecycle.Lifecycle;
import org.junit.After;
@@ -46,6 +55,7 @@ import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
@@ -139,17 +149,46 @@ public class AudioStreamsScanQrCodeControllerTest {
public void onPreferenceClick_hasFragment_launchSubSetting() {
mController.displayPreference(mScreen);
mController.setFragment(mFragment);
+ when(mFragment.getMetricsCategory()).thenReturn(AUDIO_STREAM_MAIN);
var listener = mPreference.getOnPreferenceClickListener();
assertThat(listener).isNotNull();
+
+ // mContext is not an Activity context, calling startActivity() from outside of an Activity
+ // context requires the FLAG_ACTIVITY_NEW_TASK flag, create a mock to avoid this
+ // AndroidRuntimeException.
+ Context activityContext = mock(Context.class);
+ when(mPreference.getContext()).thenReturn(activityContext);
+ when(mPreference.getKey()).thenReturn(AudioStreamsScanQrCodeController.KEY);
+
var clicked = listener.onPreferenceClick(mPreference);
+
+ ArgumentCaptor intentCaptor = ArgumentCaptor.forClass(Intent.class);
+ ArgumentCaptor requestCodeCaptor = ArgumentCaptor.forClass(Integer.class);
+ verify(mFragment)
+ .startActivityForResult(intentCaptor.capture(), requestCodeCaptor.capture());
+
+ Intent intent = intentCaptor.getValue();
+ assertThat(intent.getStringExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT))
+ .isEqualTo(AudioStreamsQrCodeScanFragment.class.getName());
+ assertThat(intent.getIntExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT_TITLE_RESID, 0))
+ .isEqualTo(R.string.audio_streams_main_page_scan_qr_code_title);
+ assertThat(intent.getIntExtra(MetricsFeatureProvider.EXTRA_SOURCE_METRICS_CATEGORY, 0))
+ .isEqualTo(AUDIO_STREAM_MAIN);
+
+ int requestCode = requestCodeCaptor.getValue();
+ assertThat(requestCode).isEqualTo(REQUEST_SCAN_BT_BROADCAST_QR_CODE);
+
assertThat(clicked).isTrue();
}
@Test
public void updateVisibility_noConnected_invisible() {
mController.displayPreference(mScreen);
- mController.mBluetoothCallback.onActiveDeviceChanged(mDevice, BluetoothProfile.LE_AUDIO);
+ mController.mBluetoothCallback.onProfileConnectionStateChanged(
+ mDevice,
+ BluetoothAdapter.STATE_DISCONNECTED,
+ BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT);
assertThat(mPreference.isVisible()).isFalse();
}
@@ -158,7 +197,10 @@ public class AudioStreamsScanQrCodeControllerTest {
public void updateVisibility_hasConnected_visible() {
mController.displayPreference(mScreen);
ShadowAudioStreamsHelper.setCachedBluetoothDeviceInSharingOrLeConnected(mDevice);
- mController.mBluetoothCallback.onActiveDeviceChanged(mDevice, BluetoothProfile.LE_AUDIO);
+ mController.mBluetoothCallback.onProfileConnectionStateChanged(
+ mDevice,
+ BluetoothAdapter.STATE_CONNECTED,
+ BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT);
assertThat(mPreference.isVisible()).isTrue();
}
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/audiostreams/SourceAddedStateTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/audiostreams/SourceAddedStateTest.java
index 0f0bafe217a..082735a31fc 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/audiostreams/SourceAddedStateTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/audiostreams/SourceAddedStateTest.java
@@ -16,27 +16,71 @@
package com.android.settings.connecteddevice.audiosharing.audiostreams;
+import static android.app.settings.SettingsEnums.AUDIO_STREAM_MAIN;
+
import static com.android.settings.connecteddevice.audiosharing.audiostreams.SourceAddedState.AUDIO_STREAM_SOURCE_ADDED_STATE_SUMMARY;
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.settings.SettingsEnums;
+import android.bluetooth.BluetoothLeBroadcastMetadata;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+
+import androidx.fragment.app.FragmentActivity;
+import androidx.preference.Preference;
+import androidx.test.core.app.ApplicationProvider;
+
+import com.android.settings.R;
+import com.android.settings.SettingsActivity;
+import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settings.testutils.shadow.ShadowFragment;
+import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
+
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
@RunWith(RobolectricTestRunner.class)
+@Config(
+ shadows = {
+ ShadowFragment.class,
+ })
public class SourceAddedStateTest {
-
@Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+ private static final int BROADCAST_ID = 1;
+ private static final String BROADCAST_TITLE = "title";
+ private final Context mContext = ApplicationProvider.getApplicationContext();
+ @Mock private AudioStreamPreference mPreference;
+ @Mock private AudioStreamsProgressCategoryController mController;
+ @Mock private AudioStreamsHelper mHelper;
+ @Mock private AudioStreamsRepository mRepository;
+ @Mock private AudioStreamsDashboardFragment mFragment;
+ @Mock private FragmentActivity mActivity;
+ private FakeFeatureFactory mFeatureFactory;
private SourceAddedState mInstance;
@Before
public void setUp() {
- mInstance = SourceAddedState.getInstance();
+ when(mFragment.getActivity()).thenReturn(mActivity);
+ mFeatureFactory = FakeFeatureFactory.setupForTest();
+ mInstance = new SourceAddedState();
+ when(mPreference.getAudioStreamBroadcastId()).thenReturn(BROADCAST_ID);
+ when(mPreference.getTitle()).thenReturn(BROADCAST_TITLE);
}
@Test
@@ -58,4 +102,59 @@ public class SourceAddedStateTest {
assertThat(stateEnum)
.isEqualTo(AudioStreamsProgressCategoryController.AudioStreamState.SOURCE_ADDED);
}
+
+ @Test
+ public void testPerformAction() {
+ mInstance.setAudioStreamsRepositoryForTesting(mRepository);
+ BluetoothLeBroadcastMetadata mockMetadata = mock(BluetoothLeBroadcastMetadata.class);
+ when(mRepository.getCachedMetadata(anyInt())).thenReturn(mockMetadata);
+ when(mPreference.getContext()).thenReturn(mContext);
+ when(mPreference.getSourceOriginForLogging())
+ .thenReturn(SourceOriginForLogging.QR_CODE_SCAN_SETTINGS);
+
+ mInstance.performAction(mPreference, mController, mHelper);
+
+ verify(mRepository).saveMetadata(eq(mContext), eq(mockMetadata));
+ verify(mFeatureFactory.metricsFeatureProvider)
+ .action(
+ eq(mContext),
+ eq(SettingsEnums.ACTION_AUDIO_STREAM_JOIN_SUCCEED),
+ eq(SourceOriginForLogging.QR_CODE_SCAN_SETTINGS.ordinal()));
+ verify(mHelper).startMediaService(eq(mContext), eq(BROADCAST_ID), eq(BROADCAST_TITLE));
+ }
+
+ @Test
+ public void testGetOnClickListener_startSubSettings() {
+ when(mController.getFragment()).thenReturn(mFragment);
+ when(mFragment.getMetricsCategory()).thenReturn(AUDIO_STREAM_MAIN);
+
+ Preference.OnPreferenceClickListener listener = mInstance.getOnClickListener(mController);
+ assertThat(listener).isNotNull();
+
+ // mContext is not an Activity context, calling startActivity() from outside of an Activity
+ // context requires the FLAG_ACTIVITY_NEW_TASK flag, create a mock to avoid this
+ // AndroidRuntimeException.
+ Context activityContext = mock(Context.class);
+ when(mPreference.getContext()).thenReturn(activityContext);
+
+ listener.onPreferenceClick(mPreference);
+
+ ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(Intent.class);
+ verify(activityContext).startActivity(argumentCaptor.capture());
+
+ Intent intent = argumentCaptor.getValue();
+ assertThat(intent.getStringExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT))
+ .isEqualTo(AudioStreamDetailsFragment.class.getName());
+ assertThat(intent.getIntExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT_TITLE_RESID, 0))
+ .isEqualTo(R.string.audio_streams_detail_page_title);
+ assertThat(intent.getIntExtra(MetricsFeatureProvider.EXTRA_SOURCE_METRICS_CATEGORY, 0))
+ .isEqualTo(AUDIO_STREAM_MAIN);
+
+ Bundle bundle = intent.getBundleExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT_ARGUMENTS);
+ assertThat(bundle).isNotNull();
+ assertThat(bundle.getString(AudioStreamDetailsFragment.BROADCAST_NAME_ARG))
+ .isEqualTo(BROADCAST_TITLE);
+ assertThat(bundle.getInt(AudioStreamDetailsFragment.BROADCAST_ID_ARG))
+ .isEqualTo(BROADCAST_ID);
+ }
}
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/audiostreams/SyncedStateTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/audiostreams/SyncedStateTest.java
index e9eab5066ac..2b19e2058b3 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/audiostreams/SyncedStateTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/audiostreams/SyncedStateTest.java
@@ -20,7 +20,7 @@ import static com.android.settings.connecteddevice.audiosharing.audiostreams.Aud
import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Mockito.never;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.robolectric.shadows.ShadowLooper.shadowMainLooper;
@@ -28,10 +28,16 @@ import static org.robolectric.shadows.ShadowLooper.shadowMainLooper;
import android.app.AlertDialog;
import android.bluetooth.BluetoothLeBroadcastMetadata;
import android.content.Context;
+import android.content.DialogInterface;
+import android.widget.Button;
+import android.widget.TextView;
import androidx.preference.Preference;
import androidx.test.core.app.ApplicationProvider;
+import com.android.settings.R;
+import com.android.settingslib.bluetooth.BluetoothLeBroadcastMetadataExt;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
@@ -42,7 +48,9 @@ import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
+import org.robolectric.shadow.api.Shadow;
import org.robolectric.shadows.ShadowAlertDialog;
+import org.robolectric.shadows.ShadowLooper;
@RunWith(RobolectricTestRunner.class)
@Config(
@@ -51,6 +59,10 @@ import org.robolectric.shadows.ShadowAlertDialog;
})
public class SyncedStateTest {
@Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+ private static final String ENCRYPTED_METADATA =
+ "BLUETOOTH:UUID:184F;BN:VGVzdA==;AT:1;AD:00A1A1A1A1A1;BI:1E240;BC:VGVzdENvZGU=;"
+ + "MD:BgNwVGVzdA==;AS:1;PI:A0;NS:1;BS:3;NB:2;SM:BQNUZXN0BARlbmc=;;";
+ private static final String BROADCAST_TITLE = "title";
@Mock private AudioStreamsProgressCategoryController mMockController;
@Mock private AudioStreamPreference mMockPreference;
@Mock private BluetoothLeBroadcastMetadata mMockMetadata;
@@ -105,18 +117,47 @@ public class SyncedStateTest {
@Test
public void testGetOnClickListener_isEncrypted_passwordDialogShowing() {
+ when(mMockPreference.getAudioStreamMetadata())
+ .thenReturn(
+ BluetoothLeBroadcastMetadataExt.INSTANCE.convertToBroadcastMetadata(
+ ENCRYPTED_METADATA));
+ when(mMockPreference.getContext()).thenReturn(mMockContext);
+ when(mMockPreference.getTitle()).thenReturn(BROADCAST_TITLE);
+
Preference.OnPreferenceClickListener listener =
mInstance.getOnClickListener(mMockController);
- when(mMockPreference.getAudioStreamMetadata()).thenReturn(mMockMetadata);
- when(mMockPreference.getContext()).thenReturn(mMockContext);
- when(mMockMetadata.isEncrypted()).thenReturn(true);
+ assertThat(listener).isNotNull();
listener.onPreferenceClick(mMockPreference);
shadowMainLooper().idle();
AlertDialog dialog = ShadowAlertDialog.getLatestAlertDialog();
+
assertThat(dialog).isNotNull();
assertThat(dialog.isShowing()).isTrue();
- verify(mMockController, never()).handleSourceAddRequest(mMockPreference, mMockMetadata);
+
+ Button neutralButton = dialog.getButton(DialogInterface.BUTTON_NEUTRAL);
+ assertThat(neutralButton).isNotNull();
+ assertThat(neutralButton.getText().toString())
+ .isEqualTo(mMockContext.getString(android.R.string.cancel));
+
+ Button positiveButton = dialog.getButton(DialogInterface.BUTTON_POSITIVE);
+ assertThat(positiveButton).isNotNull();
+ assertThat(positiveButton.getText().toString())
+ .isEqualTo(
+ mMockContext.getString(R.string.bluetooth_connect_access_dialog_positive));
+
+ positiveButton.callOnClick();
+ ShadowLooper.idleMainLooper();
+ verify(mMockController).handleSourceAddRequest(any(), any());
+
+ ShadowAlertDialog shadowDialog = Shadow.extract(dialog);
+ TextView title = shadowDialog.getView().findViewById(R.id.broadcast_name_text);
+ assertThat(title).isNotNull();
+ assertThat(title.getText().toString()).isEqualTo(BROADCAST_TITLE);
+ assertThat(shadowDialog.getTitle().toString())
+ .isEqualTo(mMockContext.getString(R.string.find_broadcast_password_dialog_title));
+
+ dialog.cancel();
}
}
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/audiostreams/WaitForSyncStateTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/audiostreams/WaitForSyncStateTest.java
index 3eb07a46f74..d97bf8fe58e 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/audiostreams/WaitForSyncStateTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/audiostreams/WaitForSyncStateTest.java
@@ -16,22 +16,39 @@
package com.android.settings.connecteddevice.audiosharing.audiostreams;
+import static android.app.settings.SettingsEnums.DIALOG_AUDIO_STREAM_MAIN_WAIT_FOR_SYNC_TIMEOUT;
+
+import static com.android.settings.connecteddevice.audiosharing.audiostreams.AudioStreamsScanQrCodeController.REQUEST_SCAN_BT_BROADCAST_QR_CODE;
import static com.android.settings.connecteddevice.audiosharing.audiostreams.WaitForSyncState.AUDIO_STREAM_WAIT_FOR_SYNC_STATE_SUMMARY;
import static com.android.settings.connecteddevice.audiosharing.audiostreams.WaitForSyncState.WAIT_FOR_SYNC_TIMEOUT_MILLIS;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.app.settings.SettingsEnums;
import android.bluetooth.BluetoothLeBroadcastMetadata;
+import android.content.Context;
+import android.content.Intent;
+
+import androidx.test.core.app.ApplicationProvider;
+
+import com.android.settings.R;
+import com.android.settings.SettingsActivity;
+import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
@@ -43,15 +60,18 @@ import java.util.concurrent.TimeUnit;
@RunWith(RobolectricTestRunner.class)
public class WaitForSyncStateTest {
@Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+ private final Context mContext = spy(ApplicationProvider.getApplicationContext());
@Mock private AudioStreamPreference mMockPreference;
@Mock private AudioStreamsProgressCategoryController mMockController;
@Mock private AudioStreamsHelper mMockHelper;
@Mock private BluetoothLeBroadcastMetadata mMockMetadata;
+ private FakeFeatureFactory mFeatureFactory;
private WaitForSyncState mInstance;
@Before
public void setUp() {
- mInstance = WaitForSyncState.getInstance();
+ mFeatureFactory = FakeFeatureFactory.setupForTest();
+ mInstance = new WaitForSyncState();
}
@Test
@@ -93,12 +113,49 @@ public class WaitForSyncStateTest {
.thenReturn(AudioStreamsProgressCategoryController.AudioStreamState.WAIT_FOR_SYNC);
when(mMockPreference.getAudioStreamBroadcastId()).thenReturn(1);
when(mMockPreference.getAudioStreamMetadata()).thenReturn(mMockMetadata);
+ when(mMockPreference.getContext()).thenReturn(mContext);
when(mMockPreference.getSourceOriginForLogging())
- .thenReturn(SourceOriginForLogging.UNKNOWN);
+ .thenReturn(SourceOriginForLogging.BROADCAST_SEARCH);
+ when(mMockController.getFragment()).thenReturn(mock(AudioStreamsDashboardFragment.class));
mInstance.performAction(mMockPreference, mMockController, mMockHelper);
ShadowLooper.idleMainLooper(WAIT_FOR_SYNC_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
verify(mMockController).handleSourceLost(1);
+ verify(mFeatureFactory.metricsFeatureProvider)
+ .action(
+ eq(mContext),
+ eq(SettingsEnums.ACTION_AUDIO_STREAM_JOIN_FAILED_WAIT_FOR_SYNC_TIMEOUT),
+ eq(SourceOriginForLogging.BROADCAST_SEARCH.ordinal()));
+ verify(mContext).getString(R.string.audio_streams_dialog_stream_is_not_available);
+ verify(mContext).getString(R.string.audio_streams_is_not_playing);
+ verify(mContext).getString(R.string.audio_streams_dialog_close);
+ verify(mContext).getString(R.string.audio_streams_dialog_retry);
+ }
+
+ @Test
+ public void testLaunchQrCodeScanFragment() {
+ // mContext is not an Activity context, calling startActivity() from outside of an Activity
+ // context requires the FLAG_ACTIVITY_NEW_TASK flag, create a mock to avoid this
+ // AndroidRuntimeException.
+ Context activityContext = mock(Context.class);
+ AudioStreamsDashboardFragment fragment = mock(AudioStreamsDashboardFragment.class);
+ mInstance.launchQrCodeScanFragment(activityContext, fragment);
+
+ ArgumentCaptor intentCaptor = ArgumentCaptor.forClass(Intent.class);
+ ArgumentCaptor requestCodeCaptor = ArgumentCaptor.forClass(Integer.class);
+ verify(fragment)
+ .startActivityForResult(intentCaptor.capture(), requestCodeCaptor.capture());
+
+ Intent intent = intentCaptor.getValue();
+ assertThat(intent.getStringExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT))
+ .isEqualTo(AudioStreamsQrCodeScanFragment.class.getName());
+ assertThat(intent.getIntExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT_TITLE_RESID, 0))
+ .isEqualTo(R.string.audio_streams_main_page_scan_qr_code_title);
+ assertThat(intent.getIntExtra(MetricsFeatureProvider.EXTRA_SOURCE_METRICS_CATEGORY, 0))
+ .isEqualTo(DIALOG_AUDIO_STREAM_MAIN_WAIT_FOR_SYNC_TIMEOUT);
+
+ int requestCode = requestCodeCaptor.getValue();
+ assertThat(requestCode).isEqualTo(REQUEST_SCAN_BT_BROADCAST_QR_CODE);
}
}
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/audiostreams/testshadows/ShadowAudioStreamsHelper.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/audiostreams/testshadows/ShadowAudioStreamsHelper.java
index 3a0a6c4b757..13c19cae872 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/audiostreams/testshadows/ShadowAudioStreamsHelper.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/audiostreams/testshadows/ShadowAudioStreamsHelper.java
@@ -32,7 +32,7 @@ import org.robolectric.annotation.Resetter;
import java.util.List;
import java.util.Optional;
-@Implements(value = AudioStreamsHelper.class, callThroughByDefault = false)
+@Implements(value = AudioStreamsHelper.class, callThroughByDefault = true)
public class ShadowAudioStreamsHelper {
private static AudioStreamsHelper sMockHelper;
@Nullable private static CachedBluetoothDevice sCachedBluetoothDevice;
diff --git a/tests/robotests/src/com/android/settings/notification/modes/InterruptionFilterPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/InterruptionFilterPreferenceControllerTest.java
index 0aef136d5f6..ff253222ac2 100644
--- a/tests/robotests/src/com/android/settings/notification/modes/InterruptionFilterPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/modes/InterruptionFilterPreferenceControllerTest.java
@@ -25,10 +25,8 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
-import android.app.AutomaticZenRule;
import android.app.Flags;
import android.content.Context;
-import android.net.Uri;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
import android.service.notification.ZenPolicy;
@@ -71,12 +69,9 @@ public final class InterruptionFilterPreferenceControllerTest {
@Test
public void testUpdateState_all() {
TwoStatePreference preference = mock(TwoStatePreference.class);
- ZenMode zenMode = new ZenMode("id",
- new AutomaticZenRule.Builder("Driving", Uri.parse("drive"))
- .setType(AutomaticZenRule.TYPE_DRIVING)
- .setInterruptionFilter(INTERRUPTION_FILTER_ALL)
- .setZenPolicy(new ZenPolicy.Builder().allowAlarms(true).build())
- .build(), true);
+ ZenMode zenMode = new TestModeBuilder()
+ .setInterruptionFilter(INTERRUPTION_FILTER_ALL)
+ .build();
mController.updateZenMode(preference, zenMode);
verify(preference).setChecked(false);
@@ -85,12 +80,9 @@ public final class InterruptionFilterPreferenceControllerTest {
@Test
public void testOnPreferenceChange_fromAll() {
TwoStatePreference preference = mock(TwoStatePreference.class);
- ZenMode zenMode = new ZenMode("id",
- new AutomaticZenRule.Builder("Driving", Uri.parse("drive"))
- .setType(AutomaticZenRule.TYPE_DRIVING)
- .setInterruptionFilter(INTERRUPTION_FILTER_ALL)
- .setZenPolicy(new ZenPolicy.Builder().allowAlarms(false).build())
- .build(), true);
+ ZenMode zenMode = new TestModeBuilder()
+ .setInterruptionFilter(INTERRUPTION_FILTER_ALL)
+ .build();
mController.updateZenMode(preference, zenMode);
@@ -107,12 +99,10 @@ public final class InterruptionFilterPreferenceControllerTest {
@Test
public void testUpdateState_priority() {
TwoStatePreference preference = mock(TwoStatePreference.class);
- ZenMode zenMode = new ZenMode("id",
- new AutomaticZenRule.Builder("Driving", Uri.parse("drive"))
- .setType(AutomaticZenRule.TYPE_DRIVING)
- .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
- .setZenPolicy(new ZenPolicy.Builder().allowAlarms(true).build())
- .build(), true);
+ ZenMode zenMode = new TestModeBuilder()
+ .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
+ .setZenPolicy(new ZenPolicy.Builder().allowAlarms(true).build())
+ .build();
mController.updateZenMode(preference, zenMode);
verify(preference).setChecked(true);
@@ -121,12 +111,10 @@ public final class InterruptionFilterPreferenceControllerTest {
@Test
public void testOnPreferenceChange_fromPriority() {
TwoStatePreference preference = mock(TwoStatePreference.class);
- ZenMode zenMode = new ZenMode("id",
- new AutomaticZenRule.Builder("Driving", Uri.parse("drive"))
- .setType(AutomaticZenRule.TYPE_DRIVING)
- .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
- .setZenPolicy(new ZenPolicy.Builder().allowAlarms(false).build())
- .build(), true);
+ ZenMode zenMode = new TestModeBuilder()
+ .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
+ .setZenPolicy(new ZenPolicy.Builder().allowAlarms(false).build())
+ .build();
mController.updateZenMode(preference, zenMode);
diff --git a/tests/robotests/src/com/android/settings/notification/modes/TestModeBuilder.java b/tests/robotests/src/com/android/settings/notification/modes/TestModeBuilder.java
new file mode 100644
index 00000000000..fa12b30590c
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/notification/modes/TestModeBuilder.java
@@ -0,0 +1,149 @@
+/*
+ * 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.notification.modes;
+
+import android.app.AutomaticZenRule;
+import android.app.NotificationManager;
+import android.net.Uri;
+import android.service.notification.Condition;
+import android.service.notification.ZenDeviceEffects;
+import android.service.notification.ZenModeConfig;
+import android.service.notification.ZenPolicy;
+
+import androidx.annotation.Nullable;
+
+import com.android.settingslib.notification.modes.ZenMode;
+
+import java.util.Random;
+
+class TestModeBuilder {
+
+ private String mId;
+ private AutomaticZenRule mRule;
+ private ZenModeConfig.ZenRule mConfigZenRule;
+
+ public static final ZenMode EXAMPLE = new TestModeBuilder().build();
+
+ TestModeBuilder() {
+ // Reasonable defaults
+ int id = new Random().nextInt(1000);
+ mId = "rule_" + id;
+ mRule = new AutomaticZenRule.Builder("Test Rule #" + id, Uri.parse("rule://" + id))
+ .setPackage("some_package")
+ .setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_PRIORITY)
+ .setZenPolicy(new ZenPolicy.Builder().disallowAllSounds().build())
+ .build();
+ mConfigZenRule = new ZenModeConfig.ZenRule();
+ mConfigZenRule.enabled = true;
+ mConfigZenRule.pkg = "some_package";
+ }
+
+ TestModeBuilder setId(String id) {
+ mId = id;
+ return this;
+ }
+
+ TestModeBuilder setAzr(AutomaticZenRule rule) {
+ mRule = rule;
+ mConfigZenRule.pkg = rule.getPackageName();
+ mConfigZenRule.conditionId = rule.getConditionId();
+ mConfigZenRule.enabled = rule.isEnabled();
+ return this;
+ }
+
+ TestModeBuilder setConfigZenRule(ZenModeConfig.ZenRule configZenRule) {
+ mConfigZenRule = configZenRule;
+ return this;
+ }
+
+ public TestModeBuilder setName(String name) {
+ mRule.setName(name);
+ mConfigZenRule.name = name;
+ return this;
+ }
+
+ public TestModeBuilder setPackage(String pkg) {
+ mRule.setPackageName(pkg);
+ mConfigZenRule.pkg = pkg;
+ return this;
+ }
+
+ TestModeBuilder setConditionId(Uri conditionId) {
+ mRule.setConditionId(conditionId);
+ mConfigZenRule.conditionId = conditionId;
+ return this;
+ }
+
+ TestModeBuilder setType(@AutomaticZenRule.Type int type) {
+ mRule.setType(type);
+ mConfigZenRule.type = type;
+ return this;
+ }
+
+ TestModeBuilder setInterruptionFilter(
+ @NotificationManager.InterruptionFilter int interruptionFilter) {
+ mRule.setInterruptionFilter(interruptionFilter);
+ mConfigZenRule.zenMode = NotificationManager.zenModeFromInterruptionFilter(
+ interruptionFilter, NotificationManager.INTERRUPTION_FILTER_PRIORITY);
+ return this;
+ }
+
+ TestModeBuilder setZenPolicy(@Nullable ZenPolicy policy) {
+ mRule.setZenPolicy(policy);
+ mConfigZenRule.zenPolicy = policy;
+ return this;
+ }
+
+ TestModeBuilder setDeviceEffects(@Nullable ZenDeviceEffects deviceEffects) {
+ mRule.setDeviceEffects(deviceEffects);
+ mConfigZenRule.zenDeviceEffects = deviceEffects;
+ return this;
+ }
+
+ public TestModeBuilder setEnabled(boolean enabled) {
+ mRule.setEnabled(enabled);
+ mConfigZenRule.enabled = enabled;
+ return this;
+ }
+
+ TestModeBuilder setManualInvocationAllowed(boolean allowed) {
+ mRule.setManualInvocationAllowed(allowed);
+ mConfigZenRule.allowManualInvocation = allowed;
+ return this;
+ }
+
+ public TestModeBuilder setTriggerDescription(@Nullable String triggerDescription) {
+ mRule.setTriggerDescription(triggerDescription);
+ mConfigZenRule.triggerDescription = triggerDescription;
+ return this;
+ }
+
+ TestModeBuilder setActive(boolean active) {
+ if (active) {
+ mConfigZenRule.enabled = true;
+ mConfigZenRule.condition = new Condition(mRule.getConditionId(), "...",
+ Condition.STATE_TRUE);
+ } else {
+ mConfigZenRule.condition = null;
+ }
+ return this;
+ }
+
+ ZenMode build() {
+ return new ZenMode(mId, mRule, mConfigZenRule);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModeAppsLinkPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModeAppsLinkPreferenceControllerTest.java
index 066a215e61f..83f8de0e70c 100644
--- a/tests/robotests/src/com/android/settings/notification/modes/ZenModeAppsLinkPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModeAppsLinkPreferenceControllerTest.java
@@ -28,12 +28,10 @@ import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import android.app.AutomaticZenRule;
import android.app.Flags;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
-import android.net.Uri;
import android.os.Bundle;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
@@ -103,14 +101,13 @@ public final class ZenModeAppsLinkPreferenceControllerTest {
}
private ZenMode createPriorityChannelsZenMode() {
- return new ZenMode("id", new AutomaticZenRule.Builder("Bedtime",
- Uri.parse("bed"))
- .setType(AutomaticZenRule.TYPE_BEDTIME)
+ return new TestModeBuilder()
+ .setId("id")
.setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
.setZenPolicy(new ZenPolicy.Builder()
.allowChannels(ZenPolicy.CHANNEL_POLICY_PRIORITY)
.build())
- .build(), true);
+ .build();
}
@Test
diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModeAppsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModeAppsPreferenceControllerTest.java
index d89e187c7da..c96dbb6566f 100644
--- a/tests/robotests/src/com/android/settings/notification/modes/ZenModeAppsPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModeAppsPreferenceControllerTest.java
@@ -26,10 +26,8 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
-import android.app.AutomaticZenRule;
import android.app.Flags;
import android.content.Context;
-import android.net.Uri;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
import android.service.notification.ZenPolicy;
@@ -107,13 +105,12 @@ public final class ZenModeAppsPreferenceControllerTest {
@Test
public void testUpdateState_None() {
TwoStatePreference preference = mock(TwoStatePreference.class);
- ZenMode zenMode = new ZenMode("id",
- new AutomaticZenRule.Builder("Driving", Uri.parse("drive"))
- .setType(AutomaticZenRule.TYPE_DRIVING)
- .setZenPolicy(new ZenPolicy.Builder()
- .allowChannels(ZenPolicy.CHANNEL_POLICY_NONE)
- .build())
- .build(), true);
+ ZenMode zenMode = new TestModeBuilder()
+ .setZenPolicy(new ZenPolicy.Builder()
+ .allowChannels(ZenPolicy.CHANNEL_POLICY_NONE)
+ .build())
+ .build();
+
mNoneController.updateZenMode(preference, zenMode);
verify(preference).setChecked(true);
@@ -122,13 +119,12 @@ public final class ZenModeAppsPreferenceControllerTest {
@Test
public void testUpdateState_None_Unchecked() {
TwoStatePreference preference = mock(TwoStatePreference.class);
- ZenMode zenMode = new ZenMode("id",
- new AutomaticZenRule.Builder("Driving", Uri.parse("drive"))
- .setType(AutomaticZenRule.TYPE_DRIVING)
- .setZenPolicy(new ZenPolicy.Builder()
- .allowChannels(ZenPolicy.CHANNEL_POLICY_PRIORITY)
- .build())
- .build(), true);
+ ZenMode zenMode = new TestModeBuilder()
+ .setZenPolicy(new ZenPolicy.Builder()
+ .allowChannels(ZenPolicy.CHANNEL_POLICY_PRIORITY)
+ .build())
+ .build();
+
mNoneController.updateZenMode(preference, zenMode);
verify(preference).setChecked(false);
@@ -137,13 +133,12 @@ public final class ZenModeAppsPreferenceControllerTest {
@Test
public void testUpdateState_Priority() {
TwoStatePreference preference = mock(TwoStatePreference.class);
- ZenMode zenMode = new ZenMode("id",
- new AutomaticZenRule.Builder("Driving", Uri.parse("drive"))
- .setType(AutomaticZenRule.TYPE_DRIVING)
- .setZenPolicy(new ZenPolicy.Builder()
- .allowChannels(ZenPolicy.CHANNEL_POLICY_PRIORITY)
- .build())
- .build(), true);
+ ZenMode zenMode = new TestModeBuilder()
+ .setZenPolicy(new ZenPolicy.Builder()
+ .allowChannels(ZenPolicy.CHANNEL_POLICY_PRIORITY)
+ .build())
+ .build();
+
mPriorityController.updateZenMode(preference, zenMode);
verify(preference).setChecked(true);
@@ -152,13 +147,12 @@ public final class ZenModeAppsPreferenceControllerTest {
@Test
public void testUpdateState_Priority_Unchecked() {
TwoStatePreference preference = mock(TwoStatePreference.class);
- ZenMode zenMode = new ZenMode("id",
- new AutomaticZenRule.Builder("Driving", Uri.parse("drive"))
- .setType(AutomaticZenRule.TYPE_DRIVING)
- .setZenPolicy(new ZenPolicy.Builder()
- .allowChannels(ZenPolicy.CHANNEL_POLICY_NONE)
- .build())
- .build(), true);
+ ZenMode zenMode = new TestModeBuilder()
+ .setZenPolicy(new ZenPolicy.Builder()
+ .allowChannels(ZenPolicy.CHANNEL_POLICY_NONE)
+ .build())
+ .build();
+
mPriorityController.updateZenMode(preference, zenMode);
verify(preference).setChecked(false);
@@ -166,21 +160,19 @@ public final class ZenModeAppsPreferenceControllerTest {
@Test
public void testPreferenceClick_passesCorrectCheckedState_None() {
- ZenMode zenMode = new ZenMode("id",
- new AutomaticZenRule.Builder("Driving", Uri.parse("drive"))
- .setType(AutomaticZenRule.TYPE_DRIVING)
- .setZenPolicy(new ZenPolicy.Builder()
- .allowChannels(ZenPolicy.CHANNEL_POLICY_PRIORITY)
- .build())
- .build(), true);
+ ZenMode zenMode = new TestModeBuilder()
+ .setZenPolicy(new ZenPolicy.Builder()
+ .allowChannels(ZenPolicy.CHANNEL_POLICY_PRIORITY)
+ .build())
+ .build();
mNoneController.updateZenMode(mNonePref, zenMode);
mPriorityController.updateZenMode(mPriorityPref, zenMode);
- assertThat(!((SelectorWithWidgetPreference) mPrefCategory.findPreference(KEY_NONE))
- .isChecked());
- assertThat(!((SelectorWithWidgetPreference) mPrefCategory.findPreference(KEY_PRIORITY))
- .isChecked());
+ assertThat(((SelectorWithWidgetPreference) mPrefCategory.findPreference(KEY_NONE))
+ .isChecked()).isFalse();
+ assertThat(((SelectorWithWidgetPreference) mPrefCategory.findPreference(KEY_PRIORITY))
+ .isChecked()).isTrue();
// Click on NONE
mPrefCategory.findPreference(KEY_NONE).performClick();
@@ -192,30 +184,31 @@ public final class ZenModeAppsPreferenceControllerTest {
// See AbstractZenModePreferenceController.
assertThat(captor.getValue().getRule().getInterruptionFilter())
.isEqualTo(INTERRUPTION_FILTER_PRIORITY);
- // NONE is now checked; others are unchecked.
+
+ // After screen is refreshed, NONE is now checked; others are unchecked.
+ mNoneController.updateZenMode(mNonePref, captor.getValue());
+ mPriorityController.updateZenMode(mPriorityPref, captor.getValue());
assertThat(((SelectorWithWidgetPreference) mPrefCategory.findPreference(KEY_NONE))
- .isChecked());
- assertThat(!((SelectorWithWidgetPreference) mPrefCategory.findPreference(KEY_PRIORITY))
- .isChecked());
+ .isChecked()).isTrue();
+ assertThat(((SelectorWithWidgetPreference) mPrefCategory.findPreference(KEY_PRIORITY))
+ .isChecked()).isFalse();
}
@Test
public void testPreferenceClick_passesCorrectCheckedState_Priority() {
- ZenMode zenMode = new ZenMode("id",
- new AutomaticZenRule.Builder("Driving", Uri.parse("drive"))
- .setType(AutomaticZenRule.TYPE_DRIVING)
- .setZenPolicy(new ZenPolicy.Builder()
- .allowChannels(ZenPolicy.CHANNEL_POLICY_NONE)
- .build())
- .build(), true);
+ ZenMode zenMode = new TestModeBuilder()
+ .setZenPolicy(new ZenPolicy.Builder()
+ .allowChannels(ZenPolicy.CHANNEL_POLICY_NONE)
+ .build())
+ .build();
mNoneController.updateZenMode(mNonePref, zenMode);
mPriorityController.updateZenMode(mPriorityPref, zenMode);
assertThat(((SelectorWithWidgetPreference) mPrefCategory.findPreference(KEY_NONE))
- .isChecked());
- assertThat(!((SelectorWithWidgetPreference) mPrefCategory.findPreference(KEY_PRIORITY))
- .isChecked());
+ .isChecked()).isTrue();
+ assertThat(((SelectorWithWidgetPreference) mPrefCategory.findPreference(KEY_PRIORITY))
+ .isChecked()).isFalse();
// Click on PRIORITY
mPrefCategory.findPreference(KEY_PRIORITY).performClick();
@@ -225,11 +218,13 @@ public final class ZenModeAppsPreferenceControllerTest {
// Checks the policy value for PRIORITY is propagated to the backend.
assertThat(captor.getValue().getRule().getInterruptionFilter())
.isEqualTo(INTERRUPTION_FILTER_PRIORITY);
- // PRIORITY is now checked; others are unchecked.
- assertThat(((SelectorWithWidgetPreference) mPrefCategory.findPreference(KEY_PRIORITY))
- .isChecked());
- assertThat(!((SelectorWithWidgetPreference) mPrefCategory.findPreference(KEY_NONE))
- .isChecked());
- }
+ // After screen is refreshed, PRIORITY is now checked; others are unchecked.
+ mNoneController.updateZenMode(mNonePref, captor.getValue());
+ mPriorityController.updateZenMode(mPriorityPref, captor.getValue());
+ assertThat(((SelectorWithWidgetPreference) mPrefCategory.findPreference(KEY_PRIORITY))
+ .isChecked()).isTrue();
+ assertThat(((SelectorWithWidgetPreference) mPrefCategory.findPreference(KEY_NONE))
+ .isChecked()).isFalse();
+ }
}
diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModeButtonPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModeButtonPreferenceControllerTest.java
index 98099aa1a20..625f2311d21 100644
--- a/tests/robotests/src/com/android/settings/notification/modes/ZenModeButtonPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModeButtonPreferenceControllerTest.java
@@ -16,8 +16,6 @@
package com.android.settings.notification.modes;
-import static android.app.NotificationManager.INTERRUPTION_FILTER_PRIORITY;
-
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -25,13 +23,10 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import android.app.AutomaticZenRule;
import android.app.Flags;
import android.content.Context;
-import android.net.Uri;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
-import android.service.notification.ZenPolicy;
import android.widget.Button;
import com.android.settingslib.notification.modes.ZenMode;
@@ -73,43 +68,34 @@ public final class ZenModeButtonPreferenceControllerTest {
@Test
public void isAvailable_notIfAppOptsOut() {
- ZenMode zenMode = new ZenMode("id",
- new AutomaticZenRule.Builder("Driving", Uri.parse("drive"))
- .setType(AutomaticZenRule.TYPE_DRIVING)
- .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
- .setZenPolicy(new ZenPolicy.Builder().allowAllSounds().build())
+ ZenMode zenMode = new TestModeBuilder()
.setManualInvocationAllowed(false)
- .setEnabled(true)
- .build(), false);
+ .build();
mController.setZenMode(zenMode);
assertThat(mController.isAvailable()).isFalse();
}
@Test
public void isAvailable_notIfModeDisabled() {
- ZenMode zenMode = new ZenMode("id",
- new AutomaticZenRule.Builder("Driving", Uri.parse("drive"))
- .setType(AutomaticZenRule.TYPE_DRIVING)
- .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
- .setZenPolicy(new ZenPolicy.Builder().allowAllSounds().build())
- .setManualInvocationAllowed(true)
- .setEnabled(false)
- .build(), false);
+ ZenMode zenMode = new TestModeBuilder()
+ .setManualInvocationAllowed(true)
+ .setEnabled(false)
+ .build();
+
mController.setZenMode(zenMode);
+
assertThat(mController.isAvailable()).isFalse();
}
@Test
public void isAvailable_appOptedIn_modeEnabled() {
- ZenMode zenMode = new ZenMode("id",
- new AutomaticZenRule.Builder("Driving", Uri.parse("drive"))
- .setType(AutomaticZenRule.TYPE_DRIVING)
- .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
- .setZenPolicy(new ZenPolicy.Builder().allowAllSounds().build())
- .setManualInvocationAllowed(true)
- .setEnabled(true)
- .build(), false);
+ ZenMode zenMode = new TestModeBuilder()
+ .setManualInvocationAllowed(true)
+ .setEnabled(true)
+ .build();
+
mController.setZenMode(zenMode);
+
assertThat(mController.isAvailable()).isTrue();
}
@@ -118,15 +104,13 @@ public final class ZenModeButtonPreferenceControllerTest {
Button button = new Button(mContext);
LayoutPreference pref = mock(LayoutPreference.class);
when(pref.findViewById(anyInt())).thenReturn(button);
- ZenMode zenMode = new ZenMode("id",
- new AutomaticZenRule.Builder("Driving", Uri.parse("drive"))
- .setType(AutomaticZenRule.TYPE_DRIVING)
- .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
- .setZenPolicy(new ZenPolicy.Builder().allowAllSounds().build())
- .setManualInvocationAllowed(true)
- .setEnabled(true)
- .build(), true);
+ ZenMode zenMode = new TestModeBuilder()
+ .setManualInvocationAllowed(true)
+ .setActive(true)
+ .build();
+
mController.updateZenMode(pref, zenMode);
+
assertThat(button.getText().toString()).contains("off");
assertThat(button.hasOnClickListeners()).isTrue();
}
@@ -136,15 +120,13 @@ public final class ZenModeButtonPreferenceControllerTest {
Button button = new Button(mContext);
LayoutPreference pref = mock(LayoutPreference.class);
when(pref.findViewById(anyInt())).thenReturn(button);
- ZenMode zenMode = new ZenMode("id",
- new AutomaticZenRule.Builder("Driving", Uri.parse("drive"))
- .setType(AutomaticZenRule.TYPE_DRIVING)
- .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
- .setZenPolicy(new ZenPolicy.Builder().allowAllSounds().build())
- .setManualInvocationAllowed(true)
- .setEnabled(true)
- .build(), false);
+ ZenMode zenMode = new TestModeBuilder()
+ .setManualInvocationAllowed(true)
+ .setActive(false)
+ .build();
+
mController.updateZenMode(pref, zenMode);
+
assertThat(button.getText().toString()).contains("on");
assertThat(button.hasOnClickListeners()).isTrue();
}
@@ -154,14 +136,11 @@ public final class ZenModeButtonPreferenceControllerTest {
Button button = new Button(mContext);
LayoutPreference pref = mock(LayoutPreference.class);
when(pref.findViewById(anyInt())).thenReturn(button);
- ZenMode zenMode = new ZenMode("id",
- new AutomaticZenRule.Builder("Driving", Uri.parse("drive"))
- .setType(AutomaticZenRule.TYPE_DRIVING)
- .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
- .setZenPolicy(new ZenPolicy.Builder().allowAllSounds().build())
- .setManualInvocationAllowed(true)
- .setEnabled(true)
- .build(), true);
+ ZenMode zenMode = new TestModeBuilder()
+ .setManualInvocationAllowed(true)
+ .setActive(true)
+ .build();
+
mController.updateZenMode(pref, zenMode);
button.callOnClick();
@@ -173,14 +152,11 @@ public final class ZenModeButtonPreferenceControllerTest {
Button button = new Button(mContext);
LayoutPreference pref = mock(LayoutPreference.class);
when(pref.findViewById(anyInt())).thenReturn(button);
- ZenMode zenMode = new ZenMode("id",
- new AutomaticZenRule.Builder("Driving", Uri.parse("drive"))
- .setType(AutomaticZenRule.TYPE_DRIVING)
- .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
- .setZenPolicy(new ZenPolicy.Builder().allowAllSounds().build())
- .setManualInvocationAllowed(true)
- .setEnabled(true)
- .build(), false);
+ ZenMode zenMode = new TestModeBuilder()
+ .setManualInvocationAllowed(true)
+ .setActive(false)
+ .build();
+
mController.updateZenMode(pref, zenMode);
button.callOnClick();
diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModeCallsLinkPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModeCallsLinkPreferenceControllerTest.java
index c8e654d5af8..058b2d7d566 100644
--- a/tests/robotests/src/com/android/settings/notification/modes/ZenModeCallsLinkPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModeCallsLinkPreferenceControllerTest.java
@@ -16,23 +16,17 @@
package com.android.settings.notification.modes;
-import static android.app.NotificationManager.INTERRUPTION_FILTER_PRIORITY;
-
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
-import android.app.AutomaticZenRule;
import android.app.Flags;
import android.content.Context;
-import android.net.Uri;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
-import android.service.notification.ZenPolicy;
import androidx.preference.Preference;
-import com.android.settingslib.notification.modes.ZenMode;
import com.android.settingslib.notification.modes.ZenModesBackend;
import org.junit.Before;
@@ -70,13 +64,7 @@ public final class ZenModeCallsLinkPreferenceControllerTest {
@EnableFlags(Flags.FLAG_MODES_UI)
public void testHasSummary() {
Preference pref = mock(Preference.class);
- ZenMode zenMode = new ZenMode("id",
- new AutomaticZenRule.Builder("Driving", Uri.parse("drive"))
- .setType(AutomaticZenRule.TYPE_DRIVING)
- .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
- .setZenPolicy(new ZenPolicy.Builder().allowAllSounds().build())
- .build(), true);
- mController.updateZenMode(pref, zenMode);
+ mController.updateZenMode(pref, TestModeBuilder.EXAMPLE);
verify(pref).setSummary(any());
}
}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModeDisplayEffectPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModeDisplayEffectPreferenceControllerTest.java
index 1052c0d831e..a735cd928f3 100644
--- a/tests/robotests/src/com/android/settings/notification/modes/ZenModeDisplayEffectPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModeDisplayEffectPreferenceControllerTest.java
@@ -16,21 +16,16 @@
package com.android.settings.notification.modes;
-import static android.app.NotificationManager.INTERRUPTION_FILTER_PRIORITY;
-
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
-import android.app.AutomaticZenRule;
import android.app.Flags;
import android.content.Context;
-import android.net.Uri;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
import android.service.notification.ZenDeviceEffects;
-import android.service.notification.ZenPolicy;
import androidx.preference.TwoStatePreference;
@@ -67,15 +62,11 @@ public final class ZenModeDisplayEffectPreferenceControllerTest {
@Test
public void testUpdateState_grayscale() {
TwoStatePreference preference = mock(TwoStatePreference.class);
- ZenMode zenMode = new ZenMode("id",
- new AutomaticZenRule.Builder("Driving", Uri.parse("drive"))
- .setType(AutomaticZenRule.TYPE_DRIVING)
- .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
- .setZenPolicy(new ZenPolicy.Builder().allowAlarms(true).build())
- .setDeviceEffects(new ZenDeviceEffects.Builder()
- .setShouldDisplayGrayscale(true)
- .build())
- .build(), true);
+ ZenMode zenMode = new TestModeBuilder()
+ .setDeviceEffects(new ZenDeviceEffects.Builder()
+ .setShouldDisplayGrayscale(true)
+ .build())
+ .build();
ZenModeDisplayEffectPreferenceController controller =
new ZenModeDisplayEffectPreferenceController(
@@ -89,15 +80,11 @@ public final class ZenModeDisplayEffectPreferenceControllerTest {
@Test
public void testOnPreferenceChange_grayscale() {
TwoStatePreference preference = mock(TwoStatePreference.class);
- ZenMode zenMode = new ZenMode("id",
- new AutomaticZenRule.Builder("Driving", Uri.parse("drive"))
- .setType(AutomaticZenRule.TYPE_DRIVING)
- .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
- .setZenPolicy(new ZenPolicy.Builder().allowAlarms(false).build())
- .setDeviceEffects(new ZenDeviceEffects.Builder()
- .setShouldDisplayGrayscale(true)
- .build())
- .build(), true);
+ ZenMode zenMode = new TestModeBuilder()
+ .setDeviceEffects(new ZenDeviceEffects.Builder()
+ .setShouldDisplayGrayscale(true)
+ .build())
+ .build();
ZenModeDisplayEffectPreferenceController controller =
new ZenModeDisplayEffectPreferenceController(mContext, "effect_greyscale", mBackend);
@@ -108,22 +95,18 @@ public final class ZenModeDisplayEffectPreferenceControllerTest {
ArgumentCaptor captor = ArgumentCaptor.forClass(ZenMode.class);
verify(mBackend).updateMode(captor.capture());
- assertThat(captor.getValue().getRule().getDeviceEffects().shouldDisplayGrayscale())
+ assertThat(captor.getValue().getDeviceEffects().shouldDisplayGrayscale())
.isFalse();
}
@Test
public void testUpdateState_aod() {
TwoStatePreference preference = mock(TwoStatePreference.class);
- ZenMode zenMode = new ZenMode("id",
- new AutomaticZenRule.Builder("Driving", Uri.parse("drive"))
- .setType(AutomaticZenRule.TYPE_DRIVING)
- .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
- .setZenPolicy(new ZenPolicy.Builder().allowMedia(true).build())
- .setDeviceEffects(new ZenDeviceEffects.Builder()
- .setShouldSuppressAmbientDisplay(true)
- .build())
- .build(), true);
+ ZenMode zenMode = new TestModeBuilder()
+ .setDeviceEffects(new ZenDeviceEffects.Builder()
+ .setShouldSuppressAmbientDisplay(true)
+ .build())
+ .build();
ZenModeDisplayEffectPreferenceController controller =
new ZenModeDisplayEffectPreferenceController(mContext, "effect_aod", mBackend);
@@ -136,15 +119,11 @@ public final class ZenModeDisplayEffectPreferenceControllerTest {
@Test
public void testOnPreferenceChange_aod() {
TwoStatePreference preference = mock(TwoStatePreference.class);
- ZenMode zenMode = new ZenMode("id",
- new AutomaticZenRule.Builder("Driving", Uri.parse("drive"))
- .setType(AutomaticZenRule.TYPE_DRIVING)
- .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
- .setZenPolicy(new ZenPolicy.Builder().allowMedia(false).build())
- .setDeviceEffects(new ZenDeviceEffects.Builder()
- .setShouldSuppressAmbientDisplay(true)
- .build())
- .build(), true);
+ ZenMode zenMode = new TestModeBuilder()
+ .setDeviceEffects(new ZenDeviceEffects.Builder()
+ .setShouldSuppressAmbientDisplay(true)
+ .build())
+ .build();
ZenModeDisplayEffectPreferenceController controller =
new ZenModeDisplayEffectPreferenceController(mContext, "effect_aod", mBackend);
@@ -155,22 +134,18 @@ public final class ZenModeDisplayEffectPreferenceControllerTest {
ArgumentCaptor captor = ArgumentCaptor.forClass(ZenMode.class);
verify(mBackend).updateMode(captor.capture());
- assertThat(captor.getValue().getRule().getDeviceEffects().shouldSuppressAmbientDisplay())
+ assertThat(captor.getValue().getDeviceEffects().shouldSuppressAmbientDisplay())
.isFalse();
}
@Test
public void testUpdateState_wallpaper() {
TwoStatePreference preference = mock(TwoStatePreference.class);
- ZenMode zenMode = new ZenMode("id",
- new AutomaticZenRule.Builder("Driving", Uri.parse("drive"))
- .setType(AutomaticZenRule.TYPE_DRIVING)
- .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
- .setZenPolicy(new ZenPolicy.Builder().allowSystem(true).build())
- .setDeviceEffects(new ZenDeviceEffects.Builder()
- .setShouldDimWallpaper(true)
- .build())
- .build(), true);
+ ZenMode zenMode = new TestModeBuilder()
+ .setDeviceEffects(new ZenDeviceEffects.Builder()
+ .setShouldDimWallpaper(true)
+ .build())
+ .build();
ZenModeDisplayEffectPreferenceController controller =
new ZenModeDisplayEffectPreferenceController(
@@ -184,15 +159,11 @@ public final class ZenModeDisplayEffectPreferenceControllerTest {
@Test
public void testOnPreferenceChange_wallpaper() {
TwoStatePreference preference = mock(TwoStatePreference.class);
- ZenMode zenMode = new ZenMode("id",
- new AutomaticZenRule.Builder("Driving", Uri.parse("drive"))
- .setType(AutomaticZenRule.TYPE_DRIVING)
- .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
- .setZenPolicy(new ZenPolicy.Builder().allowSystem(false).build())
- .setDeviceEffects(new ZenDeviceEffects.Builder()
- .setShouldDimWallpaper(true)
- .build())
- .build(), true);
+ ZenMode zenMode = new TestModeBuilder()
+ .setDeviceEffects(new ZenDeviceEffects.Builder()
+ .setShouldDimWallpaper(true)
+ .build())
+ .build();
ZenModeDisplayEffectPreferenceController controller =
new ZenModeDisplayEffectPreferenceController(
@@ -204,21 +175,17 @@ public final class ZenModeDisplayEffectPreferenceControllerTest {
ArgumentCaptor captor = ArgumentCaptor.forClass(ZenMode.class);
verify(mBackend).updateMode(captor.capture());
- assertThat(captor.getValue().getRule().getDeviceEffects().shouldDimWallpaper()).isFalse();
+ assertThat(captor.getValue().getDeviceEffects().shouldDimWallpaper()).isFalse();
}
@Test
public void testUpdateState_darkTheme() {
TwoStatePreference preference = mock(TwoStatePreference.class);
- ZenMode zenMode = new ZenMode("id",
- new AutomaticZenRule.Builder("Driving", Uri.parse("drive"))
- .setType(AutomaticZenRule.TYPE_DRIVING)
- .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
- .setZenPolicy(new ZenPolicy.Builder().allowReminders(true).build())
- .setDeviceEffects(new ZenDeviceEffects.Builder()
- .setShouldUseNightMode(true)
- .build())
- .build(), true);
+ ZenMode zenMode = new TestModeBuilder()
+ .setDeviceEffects(new ZenDeviceEffects.Builder()
+ .setShouldUseNightMode(true)
+ .build())
+ .build();
ZenModeDisplayEffectPreferenceController controller =
new ZenModeDisplayEffectPreferenceController(mContext, "effect_dark_theme",
@@ -232,15 +199,11 @@ public final class ZenModeDisplayEffectPreferenceControllerTest {
@Test
public void testOnPreferenceChange_darkTheme() {
TwoStatePreference preference = mock(TwoStatePreference.class);
- ZenMode zenMode = new ZenMode("id",
- new AutomaticZenRule.Builder("Driving", Uri.parse("drive"))
- .setType(AutomaticZenRule.TYPE_DRIVING)
- .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
- .setZenPolicy(new ZenPolicy.Builder().allowReminders(false).build())
- .setDeviceEffects(new ZenDeviceEffects.Builder()
- .setShouldUseNightMode(true)
- .build())
- .build(), true);
+ ZenMode zenMode = new TestModeBuilder()
+ .setDeviceEffects(new ZenDeviceEffects.Builder()
+ .setShouldUseNightMode(true)
+ .build())
+ .build();
ZenModeDisplayEffectPreferenceController controller =
new ZenModeDisplayEffectPreferenceController(mContext, "effect_dark_theme",
@@ -252,6 +215,6 @@ public final class ZenModeDisplayEffectPreferenceControllerTest {
ArgumentCaptor captor = ArgumentCaptor.forClass(ZenMode.class);
verify(mBackend).updateMode(captor.capture());
- assertThat(captor.getValue().getRule().getDeviceEffects().shouldUseNightMode()).isFalse();
+ assertThat(captor.getValue().getDeviceEffects().shouldUseNightMode()).isFalse();
}
}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModeDisplayLinkPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModeDisplayLinkPreferenceControllerTest.java
index c78883b0b68..3ccfb9f10dd 100644
--- a/tests/robotests/src/com/android/settings/notification/modes/ZenModeDisplayLinkPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModeDisplayLinkPreferenceControllerTest.java
@@ -16,23 +16,17 @@
package com.android.settings.notification.modes;
-import static android.app.NotificationManager.INTERRUPTION_FILTER_PRIORITY;
-
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
-import android.app.AutomaticZenRule;
import android.app.Flags;
import android.content.Context;
-import android.net.Uri;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
-import android.service.notification.ZenPolicy;
import androidx.preference.Preference;
-import com.android.settingslib.notification.modes.ZenMode;
import com.android.settingslib.notification.modes.ZenModesBackend;
import org.junit.Before;
@@ -70,13 +64,7 @@ public final class ZenModeDisplayLinkPreferenceControllerTest {
@EnableFlags(Flags.FLAG_MODES_UI)
public void testHasSummary() {
Preference pref = mock(Preference.class);
- ZenMode zenMode = new ZenMode("id",
- new AutomaticZenRule.Builder("Driving", Uri.parse("drive"))
- .setType(AutomaticZenRule.TYPE_DRIVING)
- .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
- .setZenPolicy(new ZenPolicy.Builder().allowAllSounds().build())
- .build(), true);
- mController.updateZenMode(pref, zenMode);
+ mController.updateZenMode(pref, TestModeBuilder.EXAMPLE);
verify(pref).setSummary(any());
}
}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModeExitAtAlarmPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModeExitAtAlarmPreferenceControllerTest.java
index f95fc85ec5f..03c75fb12c1 100644
--- a/tests/robotests/src/com/android/settings/notification/modes/ZenModeExitAtAlarmPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModeExitAtAlarmPreferenceControllerTest.java
@@ -21,7 +21,6 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
-import android.app.AutomaticZenRule;
import android.content.Context;
import android.service.notification.ZenModeConfig;
@@ -68,10 +67,9 @@ public class ZenModeExitAtAlarmPreferenceControllerTest {
scheduleInfo.endHour = 2;
scheduleInfo.exitAtAlarm = false;
- ZenMode mode = new ZenMode("id",
- new AutomaticZenRule.Builder("name",
- ZenModeConfig.toScheduleConditionId(scheduleInfo)).build(),
- true); // is active
+ ZenMode mode = new TestModeBuilder()
+ .setConditionId(ZenModeConfig.toScheduleConditionId(scheduleInfo))
+ .build();
// need to call updateZenMode for the first call
mPrefController.updateZenMode(preference, mode);
@@ -97,10 +95,9 @@ public class ZenModeExitAtAlarmPreferenceControllerTest {
scheduleInfo.endHour = 2;
scheduleInfo.exitAtAlarm = true;
- ZenMode mode = new ZenMode("id",
- new AutomaticZenRule.Builder("name",
- ZenModeConfig.toScheduleConditionId(scheduleInfo)).build(),
- true); // is active
+ ZenMode mode = new TestModeBuilder()
+ .setConditionId(ZenModeConfig.toScheduleConditionId(scheduleInfo))
+ .build();
mPrefController.updateZenMode(preference, mode);
// turn off exit at alarm
diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModeIconPickerListPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModeIconPickerListPreferenceControllerTest.java
index 31324604bd0..5db7e925eef 100644
--- a/tests/robotests/src/com/android/settings/notification/modes/ZenModeIconPickerListPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModeIconPickerListPreferenceControllerTest.java
@@ -23,9 +23,7 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import android.app.AutomaticZenRule;
import android.content.Context;
-import android.net.Uri;
import androidx.annotation.NonNull;
import androidx.preference.PreferenceScreen;
@@ -49,10 +47,7 @@ import org.robolectric.RuntimeEnvironment;
@RunWith(RobolectricTestRunner.class)
public class ZenModeIconPickerListPreferenceControllerTest {
- private static final ZenMode ZEN_MODE = new ZenMode(
- "mode_id",
- new AutomaticZenRule.Builder("mode name", Uri.parse("mode")).build(),
- /* isActive= */ false);
+ private static final ZenMode ZEN_MODE = TestModeBuilder.EXAMPLE;
private ZenModesBackend mBackend;
private ZenModeIconPickerListPreferenceController mController;
diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModeMessagesLinkPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModeMessagesLinkPreferenceControllerTest.java
index 6d70ec542b7..288359aeb57 100644
--- a/tests/robotests/src/com/android/settings/notification/modes/ZenModeMessagesLinkPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModeMessagesLinkPreferenceControllerTest.java
@@ -16,23 +16,17 @@
package com.android.settings.notification.modes;
-import static android.app.NotificationManager.INTERRUPTION_FILTER_PRIORITY;
-
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
-import android.app.AutomaticZenRule;
import android.app.Flags;
import android.content.Context;
-import android.net.Uri;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
-import android.service.notification.ZenPolicy;
import androidx.preference.Preference;
-import com.android.settingslib.notification.modes.ZenMode;
import com.android.settingslib.notification.modes.ZenModesBackend;
import org.junit.Before;
@@ -70,13 +64,7 @@ public final class ZenModeMessagesLinkPreferenceControllerTest {
@EnableFlags(Flags.FLAG_MODES_UI)
public void testHasSummary() {
Preference pref = mock(Preference.class);
- ZenMode zenMode = new ZenMode("id",
- new AutomaticZenRule.Builder("Driving", Uri.parse("drive"))
- .setType(AutomaticZenRule.TYPE_DRIVING)
- .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
- .setZenPolicy(new ZenPolicy.Builder().allowAllSounds().build())
- .build(), true);
- mController.updateZenMode(pref, zenMode);
+ mController.updateZenMode(pref, TestModeBuilder.EXAMPLE);
verify(pref).setSummary(any());
}
}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModeNotifVisLinkPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModeNotifVisLinkPreferenceControllerTest.java
index bf5171a8726..ee7340bd526 100644
--- a/tests/robotests/src/com/android/settings/notification/modes/ZenModeNotifVisLinkPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModeNotifVisLinkPreferenceControllerTest.java
@@ -16,23 +16,17 @@
package com.android.settings.notification.modes;
-import static android.app.NotificationManager.INTERRUPTION_FILTER_PRIORITY;
-
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
-import android.app.AutomaticZenRule;
import android.app.Flags;
import android.content.Context;
-import android.net.Uri;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
-import android.service.notification.ZenPolicy;
import androidx.preference.Preference;
-import com.android.settingslib.notification.modes.ZenMode;
import com.android.settingslib.notification.modes.ZenModesBackend;
import org.junit.Before;
@@ -70,13 +64,7 @@ public final class ZenModeNotifVisLinkPreferenceControllerTest {
@EnableFlags(Flags.FLAG_MODES_UI)
public void testHasSummary() {
Preference pref = mock(Preference.class);
- ZenMode zenMode = new ZenMode("id",
- new AutomaticZenRule.Builder("Driving", Uri.parse("drive"))
- .setType(AutomaticZenRule.TYPE_DRIVING)
- .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
- .setZenPolicy(new ZenPolicy.Builder().allowAllSounds().build())
- .build(), true);
- mController.updateZenMode(pref, zenMode);
+ mController.updateZenMode(pref, TestModeBuilder.EXAMPLE);
verify(pref).setSummary(any());
}
}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModeNotifVisPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModeNotifVisPreferenceControllerTest.java
index 137806771da..b23d946058f 100644
--- a/tests/robotests/src/com/android/settings/notification/modes/ZenModeNotifVisPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModeNotifVisPreferenceControllerTest.java
@@ -16,7 +16,6 @@
package com.android.settings.notification.modes;
-import static android.app.NotificationManager.INTERRUPTION_FILTER_PRIORITY;
import static android.service.notification.ZenPolicy.STATE_ALLOW;
import static android.service.notification.ZenPolicy.STATE_DISALLOW;
import static android.service.notification.ZenPolicy.VISUAL_EFFECT_LIGHTS;
@@ -32,11 +31,9 @@ import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import android.app.AutomaticZenRule;
import android.app.Flags;
import android.content.Context;
import android.content.res.Resources;
-import android.net.Uri;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
import android.service.notification.ZenPolicy;
@@ -99,15 +96,12 @@ public final class ZenModeNotifVisPreferenceControllerTest {
@Test
public void updateState_notChecked() {
TwoStatePreference preference = mock(TwoStatePreference.class);
- ZenMode zenMode = new ZenMode("id",
- new AutomaticZenRule.Builder("Driving", Uri.parse("drive"))
- .setType(AutomaticZenRule.TYPE_DRIVING)
- .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
- .setZenPolicy(new ZenPolicy.Builder()
- .allowAlarms(true)
- .showAllVisualEffects()
- .build())
- .build(), true);
+ ZenMode zenMode = new TestModeBuilder()
+ .setZenPolicy(new ZenPolicy.Builder()
+ .allowAlarms(true)
+ .showAllVisualEffects()
+ .build())
+ .build();
mController.updateZenMode(preference, zenMode);
@@ -118,15 +112,12 @@ public final class ZenModeNotifVisPreferenceControllerTest {
@Test
public void updateState_checked() {
TwoStatePreference preference = mock(TwoStatePreference.class);
- ZenMode zenMode = new ZenMode("id",
- new AutomaticZenRule.Builder("Driving", Uri.parse("drive"))
- .setType(AutomaticZenRule.TYPE_DRIVING)
- .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
- .setZenPolicy(new ZenPolicy.Builder()
- .allowAlarms(true)
- .showVisualEffect(VISUAL_EFFECT_PEEK, false)
- .build())
- .build(), true);
+ ZenMode zenMode = new TestModeBuilder()
+ .setZenPolicy(new ZenPolicy.Builder()
+ .allowAlarms(true)
+ .showVisualEffect(VISUAL_EFFECT_PEEK, false)
+ .build())
+ .build();
mController.updateZenMode(preference, zenMode);
@@ -141,16 +132,13 @@ public final class ZenModeNotifVisPreferenceControllerTest {
"zen_effect_status", VISUAL_EFFECT_STATUS_BAR,
new int[]{VISUAL_EFFECT_NOTIFICATION_LIST}, mBackend);
- ZenMode zenMode = new ZenMode("id",
- new AutomaticZenRule.Builder("Driving", Uri.parse("drive"))
- .setType(AutomaticZenRule.TYPE_DRIVING)
- .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
- .setZenPolicy(new ZenPolicy.Builder()
- .allowAlarms(true)
- .showVisualEffect(VISUAL_EFFECT_NOTIFICATION_LIST, false)
- .showVisualEffect(VISUAL_EFFECT_STATUS_BAR, true)
- .build())
- .build(), true);
+ ZenMode zenMode = new TestModeBuilder()
+ .setZenPolicy(new ZenPolicy.Builder()
+ .allowAlarms(true)
+ .showVisualEffect(VISUAL_EFFECT_NOTIFICATION_LIST, false)
+ .showVisualEffect(VISUAL_EFFECT_STATUS_BAR, true)
+ .build())
+ .build();
mController.updateZenMode(preference, zenMode);
@@ -171,15 +159,12 @@ public final class ZenModeNotifVisPreferenceControllerTest {
"zen_effect_status", VISUAL_EFFECT_STATUS_BAR,
new int[]{VISUAL_EFFECT_NOTIFICATION_LIST}, mBackend);
- ZenMode zenMode = new ZenMode("id",
- new AutomaticZenRule.Builder("Driving", Uri.parse("drive"))
- .setType(AutomaticZenRule.TYPE_DRIVING)
- .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
- .setZenPolicy(new ZenPolicy.Builder()
- .allowAlarms(true)
- .showAllVisualEffects()
- .build())
- .build(), true);
+ ZenMode zenMode = new TestModeBuilder()
+ .setZenPolicy(new ZenPolicy.Builder()
+ .allowAlarms(true)
+ .showAllVisualEffects()
+ .build())
+ .build();
mController.updateZenMode(preference, zenMode);
@@ -191,15 +176,12 @@ public final class ZenModeNotifVisPreferenceControllerTest {
@Test
public void onPreferenceChanged_checkedFalse() {
TwoStatePreference preference = mock(TwoStatePreference.class);
- ZenMode zenMode = new ZenMode("id",
- new AutomaticZenRule.Builder("Driving", Uri.parse("drive"))
- .setType(AutomaticZenRule.TYPE_DRIVING)
- .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
- .setZenPolicy(new ZenPolicy.Builder()
- .allowAlarms(true)
- .hideAllVisualEffects()
- .build())
- .build(), true);
+ ZenMode zenMode = new TestModeBuilder()
+ .setZenPolicy(new ZenPolicy.Builder()
+ .allowAlarms(true)
+ .hideAllVisualEffects()
+ .build())
+ .build();
mController.updateZenMode(preference, zenMode);
@@ -216,15 +198,12 @@ public final class ZenModeNotifVisPreferenceControllerTest {
@Test
public void onPreferenceChanged_checkedTrue() {
TwoStatePreference preference = mock(TwoStatePreference.class);
- ZenMode zenMode = new ZenMode("id",
- new AutomaticZenRule.Builder("Driving", Uri.parse("drive"))
- .setType(AutomaticZenRule.TYPE_DRIVING)
- .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
- .setZenPolicy(new ZenPolicy.Builder()
- .allowAlarms(true)
- .showAllVisualEffects()
- .build())
- .build(), true);
+ ZenMode zenMode = new TestModeBuilder()
+ .setZenPolicy(new ZenPolicy.Builder()
+ .allowAlarms(true)
+ .showAllVisualEffects()
+ .build())
+ .build();
mController.updateZenMode(preference, zenMode);
diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModeOtherLinkPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModeOtherLinkPreferenceControllerTest.java
index f272b80d427..c4d03fe3360 100644
--- a/tests/robotests/src/com/android/settings/notification/modes/ZenModeOtherLinkPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModeOtherLinkPreferenceControllerTest.java
@@ -16,23 +16,17 @@
package com.android.settings.notification.modes;
-import static android.app.NotificationManager.INTERRUPTION_FILTER_PRIORITY;
-
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
-import android.app.AutomaticZenRule;
import android.app.Flags;
import android.content.Context;
-import android.net.Uri;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
-import android.service.notification.ZenPolicy;
import androidx.preference.Preference;
-import com.android.settingslib.notification.modes.ZenMode;
import com.android.settingslib.notification.modes.ZenModesBackend;
import org.junit.Before;
@@ -71,13 +65,7 @@ public final class ZenModeOtherLinkPreferenceControllerTest {
@EnableFlags(Flags.FLAG_MODES_UI)
public void testHasSummary() {
Preference pref = mock(Preference.class);
- ZenMode zenMode = new ZenMode("id",
- new AutomaticZenRule.Builder("Driving", Uri.parse("drive"))
- .setType(AutomaticZenRule.TYPE_DRIVING)
- .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
- .setZenPolicy(new ZenPolicy.Builder().allowAllSounds().build())
- .build(), true);
- mController.updateZenMode(pref, zenMode);
+ mController.updateZenMode(pref, TestModeBuilder.EXAMPLE);
verify(pref).setSummary(any());
}
}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModeOtherPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModeOtherPreferenceControllerTest.java
index 66ac7fa1a41..c69a8a0ebd6 100644
--- a/tests/robotests/src/com/android/settings/notification/modes/ZenModeOtherPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModeOtherPreferenceControllerTest.java
@@ -16,7 +16,6 @@
package com.android.settings.notification.modes;
-import static android.app.NotificationManager.INTERRUPTION_FILTER_PRIORITY;
import static android.service.notification.ZenPolicy.STATE_ALLOW;
import static android.service.notification.ZenPolicy.STATE_UNSET;
@@ -25,10 +24,8 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
-import android.app.AutomaticZenRule;
import android.app.Flags;
import android.content.Context;
-import android.net.Uri;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
import android.service.notification.ZenPolicy;
@@ -68,12 +65,9 @@ public final class ZenModeOtherPreferenceControllerTest {
@Test
public void testUpdateState_alarms() {
TwoStatePreference preference = mock(TwoStatePreference.class);
- ZenMode zenMode = new ZenMode("id",
- new AutomaticZenRule.Builder("Driving", Uri.parse("drive"))
- .setType(AutomaticZenRule.TYPE_DRIVING)
- .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
- .setZenPolicy(new ZenPolicy.Builder().allowAlarms(true).build())
- .build(), true);
+ ZenMode zenMode = new TestModeBuilder()
+ .setZenPolicy(new ZenPolicy.Builder().allowAlarms(true).build())
+ .build();
ZenModeOtherPreferenceController controller =
new ZenModeOtherPreferenceController(mContext, "modes_category_alarm", mBackend);
@@ -86,12 +80,9 @@ public final class ZenModeOtherPreferenceControllerTest {
@Test
public void testOnPreferenceChange_alarms() {
TwoStatePreference preference = mock(TwoStatePreference.class);
- ZenMode zenMode = new ZenMode("id",
- new AutomaticZenRule.Builder("Driving", Uri.parse("drive"))
- .setType(AutomaticZenRule.TYPE_DRIVING)
- .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
- .setZenPolicy(new ZenPolicy.Builder().allowAlarms(false).build())
- .build(), true);
+ ZenMode zenMode = new TestModeBuilder()
+ .setZenPolicy(new ZenPolicy.Builder().allowAlarms(false).build())
+ .build();
ZenModeOtherPreferenceController controller =
new ZenModeOtherPreferenceController(mContext, "modes_category_alarm", mBackend);
@@ -111,12 +102,9 @@ public final class ZenModeOtherPreferenceControllerTest {
@Test
public void testUpdateState_media() {
TwoStatePreference preference = mock(TwoStatePreference.class);
- ZenMode zenMode = new ZenMode("id",
- new AutomaticZenRule.Builder("Driving", Uri.parse("drive"))
- .setType(AutomaticZenRule.TYPE_DRIVING)
- .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
- .setZenPolicy(new ZenPolicy.Builder().allowMedia(true).build())
- .build(), true);
+ ZenMode zenMode = new TestModeBuilder()
+ .setZenPolicy(new ZenPolicy.Builder().allowMedia(true).build())
+ .build();
ZenModeOtherPreferenceController controller =
new ZenModeOtherPreferenceController(mContext, "modes_category_media", mBackend);
@@ -129,12 +117,9 @@ public final class ZenModeOtherPreferenceControllerTest {
@Test
public void testOnPreferenceChange_media() {
TwoStatePreference preference = mock(TwoStatePreference.class);
- ZenMode zenMode = new ZenMode("id",
- new AutomaticZenRule.Builder("Driving", Uri.parse("drive"))
- .setType(AutomaticZenRule.TYPE_DRIVING)
- .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
- .setZenPolicy(new ZenPolicy.Builder().allowMedia(false).build())
- .build(), true);
+ ZenMode zenMode = new TestModeBuilder()
+ .setZenPolicy(new ZenPolicy.Builder().allowMedia(false).build())
+ .build();
ZenModeOtherPreferenceController controller =
new ZenModeOtherPreferenceController(mContext, "modes_category_media", mBackend);
@@ -154,12 +139,9 @@ public final class ZenModeOtherPreferenceControllerTest {
@Test
public void testUpdateState_system() {
TwoStatePreference preference = mock(TwoStatePreference.class);
- ZenMode zenMode = new ZenMode("id",
- new AutomaticZenRule.Builder("Driving", Uri.parse("drive"))
- .setType(AutomaticZenRule.TYPE_DRIVING)
- .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
- .setZenPolicy(new ZenPolicy.Builder().allowSystem(true).build())
- .build(), true);
+ ZenMode zenMode = new TestModeBuilder()
+ .setZenPolicy(new ZenPolicy.Builder().allowSystem(true).build())
+ .build();
ZenModeOtherPreferenceController controller =
new ZenModeOtherPreferenceController(mContext, "modes_category_system", mBackend);
@@ -172,12 +154,9 @@ public final class ZenModeOtherPreferenceControllerTest {
@Test
public void testOnPreferenceChange_system() {
TwoStatePreference preference = mock(TwoStatePreference.class);
- ZenMode zenMode = new ZenMode("id",
- new AutomaticZenRule.Builder("Driving", Uri.parse("drive"))
- .setType(AutomaticZenRule.TYPE_DRIVING)
- .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
- .setZenPolicy(new ZenPolicy.Builder().allowSystem(false).build())
- .build(), true);
+ ZenMode zenMode = new TestModeBuilder()
+ .setZenPolicy(new ZenPolicy.Builder().allowSystem(false).build())
+ .build();
ZenModeOtherPreferenceController controller =
new ZenModeOtherPreferenceController(mContext, "modes_category_system", mBackend);
@@ -197,12 +176,9 @@ public final class ZenModeOtherPreferenceControllerTest {
@Test
public void testUpdateState_reminders() {
TwoStatePreference preference = mock(TwoStatePreference.class);
- ZenMode zenMode = new ZenMode("id",
- new AutomaticZenRule.Builder("Driving", Uri.parse("drive"))
- .setType(AutomaticZenRule.TYPE_DRIVING)
- .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
- .setZenPolicy(new ZenPolicy.Builder().allowReminders(true).build())
- .build(), true);
+ ZenMode zenMode = new TestModeBuilder()
+ .setZenPolicy(new ZenPolicy.Builder().allowReminders(true).build())
+ .build();
ZenModeOtherPreferenceController controller =
new ZenModeOtherPreferenceController(mContext, "modes_category_reminders",
@@ -216,12 +192,9 @@ public final class ZenModeOtherPreferenceControllerTest {
@Test
public void testOnPreferenceChange_reminders() {
TwoStatePreference preference = mock(TwoStatePreference.class);
- ZenMode zenMode = new ZenMode("id",
- new AutomaticZenRule.Builder("Driving", Uri.parse("drive"))
- .setType(AutomaticZenRule.TYPE_DRIVING)
- .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
- .setZenPolicy(new ZenPolicy.Builder().allowReminders(false).build())
- .build(), true);
+ ZenMode zenMode = new TestModeBuilder()
+ .setZenPolicy(new ZenPolicy.Builder().allowReminders(false).build())
+ .build();
ZenModeOtherPreferenceController controller =
new ZenModeOtherPreferenceController(mContext, "modes_category_reminders",
@@ -242,12 +215,9 @@ public final class ZenModeOtherPreferenceControllerTest {
@Test
public void testUpdateState_events() {
TwoStatePreference preference = mock(TwoStatePreference.class);
- ZenMode zenMode = new ZenMode("id",
- new AutomaticZenRule.Builder("Driving", Uri.parse("drive"))
- .setType(AutomaticZenRule.TYPE_DRIVING)
- .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
- .setZenPolicy(new ZenPolicy.Builder().allowEvents(true).build())
- .build(), true);
+ ZenMode zenMode = new TestModeBuilder()
+ .setZenPolicy(new ZenPolicy.Builder().allowEvents(true).build())
+ .build();
ZenModeOtherPreferenceController controller =
new ZenModeOtherPreferenceController(mContext, "modes_category_events", mBackend);
@@ -260,12 +230,9 @@ public final class ZenModeOtherPreferenceControllerTest {
@Test
public void testOnPreferenceChange_events() {
TwoStatePreference preference = mock(TwoStatePreference.class);
- ZenMode zenMode = new ZenMode("id",
- new AutomaticZenRule.Builder("Driving", Uri.parse("drive"))
- .setType(AutomaticZenRule.TYPE_DRIVING)
- .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
- .setZenPolicy(new ZenPolicy.Builder().allowEvents(false).build())
- .build(), true);
+ ZenMode zenMode = new TestModeBuilder()
+ .setZenPolicy(new ZenPolicy.Builder().allowEvents(false).build())
+ .build();
ZenModeOtherPreferenceController controller =
new ZenModeOtherPreferenceController(mContext, "modes_category_events", mBackend);
diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModePeopleLinkPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModePeopleLinkPreferenceControllerTest.java
index ceb8dbc7e88..6591b724c58 100644
--- a/tests/robotests/src/com/android/settings/notification/modes/ZenModePeopleLinkPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModePeopleLinkPreferenceControllerTest.java
@@ -16,23 +16,17 @@
package com.android.settings.notification.modes;
-import static android.app.NotificationManager.INTERRUPTION_FILTER_PRIORITY;
-
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
-import android.app.AutomaticZenRule;
import android.app.Flags;
import android.content.Context;
-import android.net.Uri;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
-import android.service.notification.ZenPolicy;
import androidx.preference.Preference;
-import com.android.settingslib.notification.modes.ZenMode;
import com.android.settingslib.notification.modes.ZenModesBackend;
import org.junit.Before;
@@ -72,13 +66,7 @@ public final class ZenModePeopleLinkPreferenceControllerTest {
@EnableFlags(Flags.FLAG_MODES_UI)
public void testHasSummary() {
Preference pref = mock(Preference.class);
- ZenMode zenMode = new ZenMode("id",
- new AutomaticZenRule.Builder("Driving", Uri.parse("drive"))
- .setType(AutomaticZenRule.TYPE_DRIVING)
- .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
- .setZenPolicy(new ZenPolicy.Builder().allowAllSounds().build())
- .build(), true);
- mController.updateZenMode(pref, zenMode);
+ mController.updateZenMode(pref, TestModeBuilder.EXAMPLE);
verify(pref).setSummary(any());
}
}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModePrioritySendersPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModePrioritySendersPreferenceControllerTest.java
index 8317a143ead..04df27ec229 100644
--- a/tests/robotests/src/com/android/settings/notification/modes/ZenModePrioritySendersPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModePrioritySendersPreferenceControllerTest.java
@@ -16,7 +16,6 @@
package com.android.settings.notification.modes;
-import static android.app.NotificationManager.INTERRUPTION_FILTER_PRIORITY;
import static android.service.notification.ZenPolicy.CONVERSATION_SENDERS_ANYONE;
import static android.service.notification.ZenPolicy.CONVERSATION_SENDERS_IMPORTANT;
import static android.service.notification.ZenPolicy.CONVERSATION_SENDERS_NONE;
@@ -40,11 +39,9 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import android.app.AutomaticZenRule;
import android.app.Flags;
import android.content.Context;
import android.database.Cursor;
-import android.net.Uri;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
import android.service.notification.ZenPolicy;
@@ -441,20 +438,17 @@ public final class ZenModePrioritySendersPreferenceControllerTest {
@Test
public void testPreferenceClick_passesCorrectCheckedState_startingUnchecked_messages() {
- ZenMode zenMode = new ZenMode("id",
- new AutomaticZenRule.Builder("Driving", Uri.parse("drive"))
- .setType(AutomaticZenRule.TYPE_DRIVING)
- .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
- .setZenPolicy(new ZenPolicy.Builder()
- .disallowAllSounds()
- .build())
- .build(), true);
+ ZenMode zenMode = new TestModeBuilder()
+ .setZenPolicy(new ZenPolicy.Builder()
+ .disallowAllSounds()
+ .build())
+ .build();
mMessagesController.displayPreference(mPreferenceScreen);
mMessagesController.updateZenMode(mMessagesPrefCategory, zenMode);
assertThat(((SelectorWithWidgetPreference) mMessagesPrefCategory.findPreference(KEY_NONE))
- .isChecked());
+ .isChecked()).isTrue();
mMessagesPrefCategory.findPreference(KEY_STARRED).performClick();
@@ -466,14 +460,11 @@ public final class ZenModePrioritySendersPreferenceControllerTest {
@Test
public void testPreferenceClick_passesCorrectCheckedState_startingChecked_messages() {
- ZenMode zenMode = new ZenMode("id",
- new AutomaticZenRule.Builder("Driving", Uri.parse("drive"))
- .setType(AutomaticZenRule.TYPE_DRIVING)
- .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
- .setZenPolicy(new ZenPolicy.Builder()
- .allowAllSounds()
- .build())
- .build(), true);
+ ZenMode zenMode = new TestModeBuilder()
+ .setZenPolicy(new ZenPolicy.Builder()
+ .allowAllSounds()
+ .build())
+ .build();
mMessagesController.displayPreference(mPreferenceScreen);
mMessagesController.updateZenMode(mMessagesPrefCategory, zenMode);
@@ -492,14 +483,11 @@ public final class ZenModePrioritySendersPreferenceControllerTest {
@Test
public void testPreferenceClick_passesCorrectCheckedState_startingUnchecked_calls() {
- ZenMode zenMode = new ZenMode("id",
- new AutomaticZenRule.Builder("Driving", Uri.parse("drive"))
- .setType(AutomaticZenRule.TYPE_DRIVING)
- .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
- .setZenPolicy(new ZenPolicy.Builder()
- .disallowAllSounds()
- .build())
- .build(), true);
+ ZenMode zenMode = new TestModeBuilder()
+ .setZenPolicy(new ZenPolicy.Builder()
+ .disallowAllSounds()
+ .build())
+ .build();
mCallsController.displayPreference(mPreferenceScreen);
mCallsController.updateZenMode(mCallsPrefCategory, zenMode);
@@ -517,14 +505,11 @@ public final class ZenModePrioritySendersPreferenceControllerTest {
@Test
public void testPreferenceClick_passesCorrectCheckedState_startingChecked_calls() {
- ZenMode zenMode = new ZenMode("id",
- new AutomaticZenRule.Builder("Driving", Uri.parse("drive"))
- .setType(AutomaticZenRule.TYPE_DRIVING)
- .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
- .setZenPolicy(new ZenPolicy.Builder()
- .disallowAllSounds()
- .build())
- .build(), true);
+ ZenMode zenMode = new TestModeBuilder()
+ .setZenPolicy(new ZenPolicy.Builder()
+ .disallowAllSounds()
+ .build())
+ .build();
mCallsController.displayPreference(mPreferenceScreen);
mCallsController.updateZenMode(mCallsPrefCategory, zenMode);
diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModeRepeatCallersPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModeRepeatCallersPreferenceControllerTest.java
index c86b57bbeba..c1b99e5ee19 100644
--- a/tests/robotests/src/com/android/settings/notification/modes/ZenModeRepeatCallersPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModeRepeatCallersPreferenceControllerTest.java
@@ -16,7 +16,6 @@
package com.android.settings.notification.modes;
-import static android.app.NotificationManager.INTERRUPTION_FILTER_PRIORITY;
import static android.service.notification.ZenPolicy.PEOPLE_TYPE_ANYONE;
import static android.service.notification.ZenPolicy.PEOPLE_TYPE_STARRED;
import static android.service.notification.ZenPolicy.STATE_DISALLOW;
@@ -27,10 +26,8 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
-import android.app.AutomaticZenRule;
import android.app.Flags;
import android.content.Context;
-import android.net.Uri;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
import android.service.notification.ZenPolicy;
@@ -70,14 +67,11 @@ public final class ZenModeRepeatCallersPreferenceControllerTest {
@Test
public void testUpdateState_allCalls() {
TwoStatePreference preference = mock(TwoStatePreference.class);
- ZenMode zenMode = new ZenMode("id",
- new AutomaticZenRule.Builder("Driving", Uri.parse("drive"))
- .setType(AutomaticZenRule.TYPE_DRIVING)
- .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
- .setZenPolicy(new ZenPolicy.Builder()
- .allowCalls(PEOPLE_TYPE_ANYONE)
- .build())
- .build(), true);
+ ZenMode zenMode = new TestModeBuilder()
+ .setZenPolicy(new ZenPolicy.Builder()
+ .allowCalls(PEOPLE_TYPE_ANYONE)
+ .build())
+ .build();
ZenModeRepeatCallersPreferenceController controller =
new ZenModeRepeatCallersPreferenceController(mContext, "repeat", mBackend, 1);
@@ -91,15 +85,12 @@ public final class ZenModeRepeatCallersPreferenceControllerTest {
@Test
public void testUpdateState_someCalls() {
TwoStatePreference preference = mock(TwoStatePreference.class);
- ZenMode zenMode = new ZenMode("id",
- new AutomaticZenRule.Builder("Driving", Uri.parse("drive"))
- .setType(AutomaticZenRule.TYPE_DRIVING)
- .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
- .setZenPolicy(new ZenPolicy.Builder()
- .allowCalls(PEOPLE_TYPE_STARRED)
- .allowRepeatCallers(true)
- .build())
- .build(), true);
+ ZenMode zenMode = new TestModeBuilder()
+ .setZenPolicy(new ZenPolicy.Builder()
+ .allowCalls(PEOPLE_TYPE_STARRED)
+ .allowRepeatCallers(true)
+ .build())
+ .build();
ZenModeRepeatCallersPreferenceController controller =
new ZenModeRepeatCallersPreferenceController(mContext, "repeat", mBackend, 1);
@@ -113,12 +104,9 @@ public final class ZenModeRepeatCallersPreferenceControllerTest {
@Test
public void testOnPreferenceChange() {
TwoStatePreference preference = mock(TwoStatePreference.class);
- ZenMode zenMode = new ZenMode("id",
- new AutomaticZenRule.Builder("Driving", Uri.parse("drive"))
- .setType(AutomaticZenRule.TYPE_DRIVING)
- .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
- .setZenPolicy(new ZenPolicy.Builder().allowRepeatCallers(true).build())
- .build(), true);
+ ZenMode zenMode = new TestModeBuilder()
+ .setZenPolicy(new ZenPolicy.Builder().allowRepeatCallers(true).build())
+ .build();
ZenModeRepeatCallersPreferenceController controller =
new ZenModeRepeatCallersPreferenceController(mContext, "repeat", mBackend, 1);
@@ -136,4 +124,4 @@ public final class ZenModeRepeatCallersPreferenceControllerTest {
assertThat(captor.getValue().getPolicy().getPriorityCallSenders())
.isEqualTo(STATE_UNSET);
}
-}
\ No newline at end of file
+}
diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModeSetCalendarPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModeSetCalendarPreferenceControllerTest.java
index 9e1d94af09e..cc6a49791cd 100644
--- a/tests/robotests/src/com/android/settings/notification/modes/ZenModeSetCalendarPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModeSetCalendarPreferenceControllerTest.java
@@ -28,10 +28,8 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.when;
-import android.app.AutomaticZenRule;
import android.app.Flags;
import android.content.Context;
-import android.net.Uri;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
import android.service.notification.SystemZenRules;
@@ -88,11 +86,9 @@ public class ZenModeSetCalendarPreferenceControllerTest {
@Test
@EnableFlags({Flags.FLAG_MODES_API, Flags.FLAG_MODES_UI})
public void updateEventMode_updatesConditionAndTriggerDescription() {
- ZenMode mode = new ZenMode("id",
- new AutomaticZenRule.Builder("name", Uri.parse("condition"))
- .setPackage(SystemZenRules.PACKAGE_ANDROID)
- .build(),
- true); // is active
+ ZenMode mode = new TestModeBuilder()
+ .setPackage(SystemZenRules.PACKAGE_ANDROID)
+ .build();
// Explicitly update preference controller with mode info first, which will also call
// updateState()
@@ -118,10 +114,9 @@ public class ZenModeSetCalendarPreferenceControllerTest {
eventInfo.calName = "Definitely A Calendar";
eventInfo.reply = REPLY_YES;
- ZenMode mode = new ZenMode("id",
- new AutomaticZenRule.Builder("name",
- ZenModeConfig.toEventConditionId(eventInfo)).build(),
- true); // is active
+ ZenMode mode = new TestModeBuilder()
+ .setConditionId(ZenModeConfig.toEventConditionId(eventInfo))
+ .build();
mPrefController.updateZenMode(mPrefCategory, mode);
// We should see mCalendar, mReply have their values set
diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModeSetSchedulePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModeSetSchedulePreferenceControllerTest.java
index 519bb433ffe..7dbc80262de 100644
--- a/tests/robotests/src/com/android/settings/notification/modes/ZenModeSetSchedulePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModeSetSchedulePreferenceControllerTest.java
@@ -23,10 +23,8 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import android.app.AutomaticZenRule;
import android.app.Flags;
import android.content.Context;
-import android.net.Uri;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
import android.service.notification.SystemZenRules;
@@ -83,11 +81,9 @@ public class ZenModeSetSchedulePreferenceControllerTest {
@Test
@EnableFlags({Flags.FLAG_MODES_API, Flags.FLAG_MODES_UI})
public void updateScheduleRule_updatesConditionAndTriggerDescription() {
- ZenMode mode = new ZenMode("id",
- new AutomaticZenRule.Builder("name", Uri.parse("condition"))
- .setPackage(SystemZenRules.PACKAGE_ANDROID)
- .build(),
- true); // is active
+ ZenMode mode = new TestModeBuilder()
+ .setPackage(SystemZenRules.PACKAGE_ANDROID)
+ .build();
ZenModeConfig.ScheduleInfo scheduleInfo = new ZenModeConfig.ScheduleInfo();
scheduleInfo.days = new int[] { Calendar.MONDAY };
diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModeSetTriggerLinkPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModeSetTriggerLinkPreferenceControllerTest.java
index 7782a9b2cf2..31959e5d699 100644
--- a/tests/robotests/src/com/android/settings/notification/modes/ZenModeSetTriggerLinkPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModeSetTriggerLinkPreferenceControllerTest.java
@@ -37,7 +37,6 @@ import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
import android.service.notification.SystemZenRules;
import android.service.notification.ZenModeConfig;
-import android.service.notification.ZenPolicy;
import androidx.preference.PreferenceCategory;
import androidx.test.core.app.ApplicationProvider;
@@ -102,26 +101,13 @@ public class ZenModeSetTriggerLinkPreferenceControllerTest {
assertThat(mPrefController.isAvailable()).isFalse();
// should be available for other modes
- ZenMode zenMode = new ZenMode("id",
- new AutomaticZenRule.Builder("Driving", Uri.parse("drive"))
- .setType(AutomaticZenRule.TYPE_DRIVING)
- .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
- .setZenPolicy(new ZenPolicy.Builder().allowAlarms(true).build())
- .setEnabled(false)
- .build(), false);
- mPrefController.updateZenMode(mPrefCategory, zenMode);
+ mPrefController.updateZenMode(mPrefCategory, TestModeBuilder.EXAMPLE);
assertThat(mPrefController.isAvailable()).isTrue();
}
@Test
public void testUpdateState() {
- ZenMode zenMode = new ZenMode("id",
- new AutomaticZenRule.Builder("Driving", Uri.parse("drive"))
- .setType(AutomaticZenRule.TYPE_DRIVING)
- .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
- .setZenPolicy(new ZenPolicy.Builder().allowAlarms(true).build())
- .setEnabled(false)
- .build(), false);
+ ZenMode zenMode = new TestModeBuilder().setEnabled(false).build();
// Update preference controller with a zen mode that is not enabled
mPrefController.updateZenMode(mPrefCategory, zenMode);
@@ -135,13 +121,7 @@ public class ZenModeSetTriggerLinkPreferenceControllerTest {
@Test
public void testOnPreferenceChange() {
- ZenMode zenMode = new ZenMode("id",
- new AutomaticZenRule.Builder("Driving", Uri.parse("drive"))
- .setType(AutomaticZenRule.TYPE_DRIVING)
- .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
- .setZenPolicy(new ZenPolicy.Builder().allowAlarms(true).build())
- .setEnabled(false)
- .build(), false);
+ ZenMode zenMode = new TestModeBuilder().setEnabled(false).build();
// start with disabled rule
mPrefController.updateZenMode(mPrefCategory, zenMode);
@@ -160,13 +140,12 @@ public class ZenModeSetTriggerLinkPreferenceControllerTest {
ZenModeConfig.EventInfo eventInfo = new ZenModeConfig.EventInfo();
eventInfo.calendarId = 1L;
eventInfo.calName = "My events";
- ZenMode mode = new ZenMode("id", new AutomaticZenRule.Builder("name",
- ZenModeConfig.toEventConditionId(eventInfo))
+ ZenMode mode = new TestModeBuilder()
.setPackage(SystemZenRules.PACKAGE_ANDROID)
+ .setConditionId(ZenModeConfig.toEventConditionId(eventInfo))
.setType(TYPE_SCHEDULE_CALENDAR)
.setTriggerDescription("My events")
- .build(),
- true); // is active
+ .build();
mPrefController.updateZenMode(mPrefCategory, mode);
assertThat(mPreference.getTitle()).isNotNull();
@@ -188,13 +167,12 @@ public class ZenModeSetTriggerLinkPreferenceControllerTest {
scheduleInfo.days = new int[] { Calendar.MONDAY, Calendar.TUESDAY, Calendar.THURSDAY };
scheduleInfo.startHour = 1;
scheduleInfo.endHour = 15;
- ZenMode mode = new ZenMode("id", new AutomaticZenRule.Builder("name",
- ZenModeConfig.toScheduleConditionId(scheduleInfo))
+ ZenMode mode = new TestModeBuilder()
+ .setConditionId(ZenModeConfig.toScheduleConditionId(scheduleInfo))
.setPackage(SystemZenRules.PACKAGE_ANDROID)
.setType(TYPE_SCHEDULE_TIME)
.setTriggerDescription("some schedule")
- .build(),
- true); // is active
+ .build();
mPrefController.updateZenMode(mPrefCategory, mode);
assertThat(mPreference.getTitle()).isNotNull();
@@ -212,13 +190,12 @@ public class ZenModeSetTriggerLinkPreferenceControllerTest {
@Test
public void testRuleLink_manual() {
- ZenMode mode = new ZenMode("id", new AutomaticZenRule.Builder("name",
- ZenModeConfig.toCustomManualConditionId())
+ ZenMode mode = new TestModeBuilder()
+ .setConditionId(ZenModeConfig.toCustomManualConditionId())
.setPackage(SystemZenRules.PACKAGE_ANDROID)
.setType(TYPE_OTHER)
.setTriggerDescription("Will not be shown")
- .build(),
- true); // is active
+ .build();
mPrefController.updateZenMode(mPrefCategory, mode);
assertThat(mPreference.getTitle()).isNotNull();
@@ -234,13 +211,12 @@ public class ZenModeSetTriggerLinkPreferenceControllerTest {
@Test
public void onScheduleChosen_updatesMode() {
- ZenMode originalMode = new ZenMode("id",
- new AutomaticZenRule.Builder("name", ZenModeConfig.toCustomManualConditionId())
- .setPackage(SystemZenRules.PACKAGE_ANDROID)
- .setType(TYPE_OTHER)
- .setTriggerDescription("")
- .build(),
- false);
+ ZenMode originalMode = new TestModeBuilder()
+ .setConditionId(ZenModeConfig.toCustomManualConditionId())
+ .setPackage(SystemZenRules.PACKAGE_ANDROID)
+ .setType(TYPE_OTHER)
+ .setTriggerDescription("")
+ .build();
mPrefController.updateZenMode(mPrefCategory, originalMode);
ZenModeConfig.ScheduleInfo scheduleInfo = new ZenModeConfig.ScheduleInfo();
diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModesListItemPreferenceTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModesListItemPreferenceTest.java
new file mode 100644
index 00000000000..495a24c8c34
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModesListItemPreferenceTest.java
@@ -0,0 +1,126 @@
+/*
+ * 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.notification.modes;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.service.notification.ZenModeConfig;
+
+import com.android.settingslib.notification.modes.ZenMode;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.shadows.ShadowLooper;
+
+@RunWith(RobolectricTestRunner.class)
+public class ZenModesListItemPreferenceTest {
+
+ private Context mContext;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ mContext = RuntimeEnvironment.application;
+ }
+
+ @Test
+ public void constructor_setsMode() {
+ ZenModesListItemPreference preference = new ZenModesListItemPreference(mContext,
+ TestModeBuilder.EXAMPLE);
+
+ assertThat(preference.getKey()).isEqualTo(TestModeBuilder.EXAMPLE.getId());
+ assertThat(preference.getZenMode()).isEqualTo(TestModeBuilder.EXAMPLE);
+ }
+
+ @Test
+ public void setZenMode_modeEnabled() {
+ ZenMode mode = new TestModeBuilder()
+ .setName("Enabled mode")
+ .setTriggerDescription("When the thrush knocks")
+ .setEnabled(true)
+ .build();
+
+ ZenModesListItemPreference preference = new ZenModesListItemPreference(mContext, mode);
+ ShadowLooper.idleMainLooper(); // To load icon.
+
+ assertThat(preference.getTitle()).isEqualTo("Enabled mode");
+ assertThat(preference.getSummary()).isEqualTo("When the thrush knocks");
+ assertThat(preference.getIcon()).isNotNull();
+ }
+
+ @Test
+ public void setZenMode_modeActive() {
+ ZenMode mode = new TestModeBuilder()
+ .setName("Active mode")
+ .setTriggerDescription("When Birnam forest comes to Dunsinane")
+ .setEnabled(true)
+ .setActive(true)
+ .build();
+
+ ZenModesListItemPreference preference = new ZenModesListItemPreference(mContext, mode);
+ ShadowLooper.idleMainLooper();
+
+ assertThat(preference.getTitle()).isEqualTo("Active mode");
+ assertThat(preference.getSummary()).isEqualTo("ON • When Birnam forest comes to Dunsinane");
+ assertThat(preference.getIcon()).isNotNull();
+ }
+
+ @Test
+ public void setZenMode_modeDisabledByApp() {
+ ZenModeConfig.ZenRule configRule = new ZenModeConfig.ZenRule();
+ configRule.enabled = false;
+ configRule.disabledOrigin = ZenModeConfig.UPDATE_ORIGIN_APP;
+ ZenMode mode = new TestModeBuilder()
+ .setName("Mode disabled by app")
+ .setTriggerDescription("When the cat's away")
+ .setEnabled(false)
+ .setConfigZenRule(configRule)
+ .build();
+
+ ZenModesListItemPreference preference = new ZenModesListItemPreference(mContext, mode);
+ ShadowLooper.idleMainLooper();
+
+ assertThat(preference.getTitle()).isEqualTo("Mode disabled by app");
+ assertThat(preference.getSummary()).isEqualTo("Tap to set up");
+ assertThat(preference.getIcon()).isNotNull();
+ }
+
+ @Test
+ public void setZenMode_modeDisabledByUser() {
+ ZenModeConfig.ZenRule configRule = new ZenModeConfig.ZenRule();
+ configRule.enabled = false;
+ configRule.disabledOrigin = ZenModeConfig.UPDATE_ORIGIN_USER;
+ ZenMode mode = new TestModeBuilder()
+ .setName("Mode disabled by user")
+ .setTriggerDescription("When the Levee Breaks")
+ .setEnabled(false)
+ .setConfigZenRule(configRule)
+ .build();
+
+ ZenModesListItemPreference preference = new ZenModesListItemPreference(mContext, mode);
+ ShadowLooper.idleMainLooper();
+
+ assertThat(preference.getTitle()).isEqualTo("Mode disabled by user");
+ assertThat(preference.getSummary()).isEqualTo("Paused");
+ assertThat(preference.getIcon()).isNotNull();
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModesListPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModesListPreferenceControllerTest.java
index 04d5f0ae22c..f2624acd9e9 100644
--- a/tests/robotests/src/com/android/settings/notification/modes/ZenModesListPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModesListPreferenceControllerTest.java
@@ -60,14 +60,15 @@ import java.util.List;
public class ZenModesListPreferenceControllerTest {
private static final String TEST_MODE_ID = "test_mode";
private static final String TEST_MODE_NAME = "Test Mode";
- private static final ZenMode TEST_MODE = new ZenMode(
- TEST_MODE_ID,
- new AutomaticZenRule.Builder(TEST_MODE_NAME, Uri.parse("test_uri"))
+
+ private static final ZenMode TEST_MODE = new TestModeBuilder()
+ .setId(TEST_MODE_ID)
+ .setAzr(new AutomaticZenRule.Builder(TEST_MODE_NAME, Uri.parse("test_uri"))
.setType(AutomaticZenRule.TYPE_BEDTIME)
.setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
.setZenPolicy(new ZenPolicy.Builder().allowAllSounds().build())
- .build(),
- false);
+ .build())
+ .build();
private static final ZenMode TEST_MANUAL_MODE = ZenMode.manualDndMode(
new AutomaticZenRule.Builder("Do Not Disturb", Uri.EMPTY)
@@ -112,14 +113,9 @@ public class ZenModesListPreferenceControllerTest {
assertThat(mPreference.getPreferenceCount()).isEqualTo(5);
List itemPreferences = getModeListItems(mPreference);
- assertThat(itemPreferences.stream().map(pref -> pref.mZenMode).toList())
+ assertThat(itemPreferences.stream().map(ZenModesListItemPreference::getZenMode).toList())
.containsExactlyElementsIn(modes)
.inOrder();
-
- for (int i = 0; i < modes.size(); i++) {
- assertThat(((ZenModesListItemPreference) (mPreference.getPreference(i))).mZenMode)
- .isEqualTo(modes.get(i));
- }
}
@Test
@@ -140,7 +136,7 @@ public class ZenModesListPreferenceControllerTest {
mPrefController.updateState(mPreference);
List newPreferences = getModeListItems(mPreference);
- assertThat(newPreferences.stream().map(pref -> pref.mZenMode).toList())
+ assertThat(newPreferences.stream().map(ZenModesListItemPreference::getZenMode).toList())
.containsExactlyElementsIn(updatedModes)
.inOrder();
@@ -196,7 +192,7 @@ public class ZenModesListPreferenceControllerTest {
assertThat(newData).hasSize(1);
SearchIndexableRaw newItem = newData.get(0);
- assertThat(newItem.key).isEqualTo(ZenMode.MANUAL_DND_MODE_ID);
+ assertThat(newItem.key).isEqualTo(TEST_MANUAL_MODE.getId());
assertThat(newItem.title).isEqualTo("Do Not Disturb"); // set above
}
@@ -211,7 +207,7 @@ public class ZenModesListPreferenceControllerTest {
// Should keep the order presented by getModes()
SearchIndexableRaw item0 = data.get(0);
- assertThat(item0.key).isEqualTo(ZenMode.MANUAL_DND_MODE_ID);
+ assertThat(item0.key).isEqualTo(TEST_MANUAL_MODE.getId());
assertThat(item0.title).isEqualTo("Do Not Disturb"); // set above
SearchIndexableRaw item1 = data.get(1);
@@ -220,13 +216,7 @@ public class ZenModesListPreferenceControllerTest {
}
private static ZenMode newMode(String id) {
- return new ZenMode(
- id,
- new AutomaticZenRule.Builder("Mode " + id, Uri.parse("test_uri"))
- .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
- .setZenPolicy(new ZenPolicy.Builder().allowAllSounds().build())
- .build(),
- false);
+ return new TestModeBuilder().setId(id).setName("Mode " + id).build();
}
/**
diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModesSummaryHelperTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModesSummaryHelperTest.java
index 2822e003ee7..62b5ee02ee6 100644
--- a/tests/robotests/src/com/android/settings/notification/modes/ZenModesSummaryHelperTest.java
+++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModesSummaryHelperTest.java
@@ -16,7 +16,6 @@
package com.android.settings.notification.modes;
-import static android.app.NotificationManager.INTERRUPTION_FILTER_PRIORITY;
import static android.service.notification.ZenPolicy.CONVERSATION_SENDERS_ANYONE;
import static android.service.notification.ZenPolicy.PEOPLE_TYPE_ANYONE;
import static android.service.notification.ZenPolicy.PEOPLE_TYPE_CONTACTS;
@@ -25,9 +24,7 @@ import static android.service.notification.ZenPolicy.VISUAL_EFFECT_LIGHTS;
import static com.google.common.truth.Truth.assertThat;
-import android.app.AutomaticZenRule;
import android.content.Context;
-import android.net.Uri;
import android.service.notification.ZenDeviceEffects;
import android.service.notification.ZenPolicy;
@@ -59,50 +56,38 @@ public class ZenModesSummaryHelperTest {
@Test
public void getPeopleSummary_noOne() {
- AutomaticZenRule rule = new AutomaticZenRule.Builder("Bedtime", Uri.parse("bed"))
- .setType(AutomaticZenRule.TYPE_BEDTIME)
- .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
+ ZenMode zenMode = new TestModeBuilder()
.setZenPolicy(new ZenPolicy.Builder().disallowAllSounds().build())
.build();
- ZenMode zenMode = new ZenMode("id", rule, true);
assertThat(mSummaryHelper.getPeopleSummary(zenMode)).isEqualTo("No one can interrupt");
}
@Test
public void getPeopleSummary_some() {
- AutomaticZenRule rule = new AutomaticZenRule.Builder("Bedtime", Uri.parse("bed"))
- .setType(AutomaticZenRule.TYPE_BEDTIME)
- .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
+ ZenMode zenMode = new TestModeBuilder()
.setZenPolicy(new ZenPolicy.Builder().allowCalls(PEOPLE_TYPE_CONTACTS).build())
.build();
- ZenMode zenMode = new ZenMode("id", rule, true);
assertThat(mSummaryHelper.getPeopleSummary(zenMode)).isEqualTo("Some people can interrupt");
}
@Test
public void getPeopleSummary_all() {
- AutomaticZenRule rule = new AutomaticZenRule.Builder("Bedtime", Uri.parse("bed"))
- .setType(AutomaticZenRule.TYPE_BEDTIME)
- .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
+ ZenMode zenMode = new TestModeBuilder()
.setZenPolicy(new ZenPolicy.Builder().allowCalls(PEOPLE_TYPE_ANYONE).
allowConversations(CONVERSATION_SENDERS_ANYONE)
.allowMessages(PEOPLE_TYPE_ANYONE).build())
.build();
- ZenMode zenMode = new ZenMode("id", rule, true);
assertThat(mSummaryHelper.getPeopleSummary(zenMode)).isEqualTo("All people can interrupt");
}
@Test
public void getOtherSoundCategoriesSummary_single() {
- AutomaticZenRule rule = new AutomaticZenRule.Builder("Bedtime", Uri.parse("bed"))
- .setType(AutomaticZenRule.TYPE_BEDTIME)
- .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
+ ZenMode zenMode = new TestModeBuilder()
.setZenPolicy(new ZenPolicy.Builder().allowAlarms(true).build())
.build();
- ZenMode zenMode = new ZenMode("id", rule, true);
assertThat(mSummaryHelper.getOtherSoundCategoriesSummary(zenMode)).isEqualTo(
"Alarms can interrupt");
@@ -110,12 +95,9 @@ public class ZenModesSummaryHelperTest {
@Test
public void getOtherSoundCategoriesSummary_duo() {
- AutomaticZenRule rule = new AutomaticZenRule.Builder("Bedtime", Uri.parse("bed"))
- .setType(AutomaticZenRule.TYPE_BEDTIME)
- .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
+ ZenMode zenMode = new TestModeBuilder()
.setZenPolicy(new ZenPolicy.Builder().allowAlarms(true).allowMedia(true).build())
.build();
- ZenMode zenMode = new ZenMode("id", rule, true);
assertThat(mSummaryHelper.getOtherSoundCategoriesSummary(zenMode)).isEqualTo(
"Alarms and media can interrupt");
@@ -123,16 +105,13 @@ public class ZenModesSummaryHelperTest {
@Test
public void getOtherSoundCategoriesSummary_trio() {
- AutomaticZenRule rule = new AutomaticZenRule.Builder("Bedtime", Uri.parse("bed"))
- .setType(AutomaticZenRule.TYPE_BEDTIME)
- .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
+ ZenMode zenMode = new TestModeBuilder()
.setZenPolicy(new ZenPolicy.Builder()
.allowAlarms(true)
.allowMedia(true)
.allowSystem(true)
.build())
.build();
- ZenMode zenMode = new ZenMode("id", rule, true);
assertThat(mSummaryHelper.getOtherSoundCategoriesSummary(zenMode)).isEqualTo(
"Alarms, media, and touch sounds can interrupt");
@@ -140,9 +119,7 @@ public class ZenModesSummaryHelperTest {
@Test
public void getOtherSoundCategoriesSummary_quad() {
- AutomaticZenRule rule = new AutomaticZenRule.Builder("Bedtime", Uri.parse("bed"))
- .setType(AutomaticZenRule.TYPE_BEDTIME)
- .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
+ ZenMode zenMode = new TestModeBuilder()
.setZenPolicy(new ZenPolicy.Builder()
.allowAlarms(true)
.allowMedia(true)
@@ -150,7 +127,6 @@ public class ZenModesSummaryHelperTest {
.allowReminders(true)
.build())
.build();
- ZenMode zenMode = new ZenMode("id", rule, true);
assertThat(mSummaryHelper.getOtherSoundCategoriesSummary(zenMode)).isEqualTo(
"Alarms, media, and 2 more can interrupt");
@@ -158,9 +134,7 @@ public class ZenModesSummaryHelperTest {
@Test
public void getOtherSoundCategoriesSummary_all() {
- AutomaticZenRule rule = new AutomaticZenRule.Builder("Bedtime", Uri.parse("bed"))
- .setType(AutomaticZenRule.TYPE_BEDTIME)
- .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
+ ZenMode zenMode = new TestModeBuilder()
.setZenPolicy(new ZenPolicy.Builder()
.allowAlarms(true)
.allowMedia(true)
@@ -169,7 +143,6 @@ public class ZenModesSummaryHelperTest {
.allowEvents(true)
.build())
.build();
- ZenMode zenMode = new ZenMode("id", rule, true);
assertThat(mSummaryHelper.getOtherSoundCategoriesSummary(zenMode)).isEqualTo(
"Alarms, media, and 3 more can interrupt");
@@ -177,61 +150,52 @@ public class ZenModesSummaryHelperTest {
@Test
public void getBlockedEffectsSummary_none() {
- AutomaticZenRule rule = new AutomaticZenRule.Builder("Bedtime", Uri.parse("bed"))
- .setType(AutomaticZenRule.TYPE_BEDTIME)
- .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
+ ZenMode zenMode = new TestModeBuilder()
.setZenPolicy(new ZenPolicy.Builder()
.showAllVisualEffects()
.allowAlarms(true)
.build())
.build();
- ZenMode zenMode = new ZenMode("id", rule, true);
+
assertThat(mSummaryHelper.getBlockedEffectsSummary(zenMode))
.isEqualTo("Notifications shown");
}
@Test
public void getBlockedEffectsSummary_some() {
- AutomaticZenRule rule = new AutomaticZenRule.Builder("Bedtime", Uri.parse("bed"))
- .setType(AutomaticZenRule.TYPE_BEDTIME)
- .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
+ ZenMode zenMode = new TestModeBuilder()
.setZenPolicy(new ZenPolicy.Builder()
.allowAlarms(true)
.showAllVisualEffects()
.showVisualEffect(VISUAL_EFFECT_AMBIENT, false)
.build())
.build();
- ZenMode zenMode = new ZenMode("id", rule, true);
+
assertThat(mSummaryHelper.getBlockedEffectsSummary(zenMode))
.isEqualTo("Notifications partially hidden");
}
@Test
public void getBlockedEffectsSummary_all() {
- AutomaticZenRule rule = new AutomaticZenRule.Builder("Bedtime", Uri.parse("bed"))
- .setType(AutomaticZenRule.TYPE_BEDTIME)
- .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
+ ZenMode zenMode = new TestModeBuilder()
.setZenPolicy(new ZenPolicy.Builder()
.allowAlarms(true)
.hideAllVisualEffects()
.build())
.build();
- ZenMode zenMode = new ZenMode("id", rule, true);
+
assertThat(mSummaryHelper.getBlockedEffectsSummary(zenMode))
.isEqualTo("Notifications hidden");
}
@Test
public void getDisplayEffectsSummary_single_notifVis() {
- AutomaticZenRule rule = new AutomaticZenRule.Builder("Bedtime", Uri.parse("bed"))
- .setType(AutomaticZenRule.TYPE_BEDTIME)
- .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
+ ZenMode zenMode = new TestModeBuilder()
.setZenPolicy(new ZenPolicy.Builder()
.showAllVisualEffects()
.showVisualEffect(VISUAL_EFFECT_AMBIENT, false)
.build())
.build();
- ZenMode zenMode = new ZenMode("id", rule, true);
assertThat(mSummaryHelper.getDisplayEffectsSummary(zenMode)).isEqualTo(
"Notifications partially hidden");
@@ -239,15 +203,12 @@ public class ZenModesSummaryHelperTest {
@Test
public void getDisplayEffectsSummary_single_notifVis_unusedEffect() {
- AutomaticZenRule rule = new AutomaticZenRule.Builder("Bedtime", Uri.parse("bed"))
- .setType(AutomaticZenRule.TYPE_BEDTIME)
- .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
+ ZenMode zenMode = new TestModeBuilder()
.setZenPolicy(new ZenPolicy.Builder()
.showAllVisualEffects()
.showVisualEffect(VISUAL_EFFECT_LIGHTS, false)
.build())
.build();
- ZenMode zenMode = new ZenMode("id", rule, true);
assertThat(mSummaryHelper.getDisplayEffectsSummary(zenMode)).isEqualTo(
"Notifications shown");
@@ -255,15 +216,12 @@ public class ZenModesSummaryHelperTest {
@Test
public void getDisplayEffectsSummary_single_displayEffect() {
- AutomaticZenRule rule = new AutomaticZenRule.Builder("Bedtime", Uri.parse("bed"))
- .setType(AutomaticZenRule.TYPE_BEDTIME)
- .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
+ ZenMode zenMode = new TestModeBuilder()
.setZenPolicy(new ZenPolicy.Builder().showAllVisualEffects().build())
.setDeviceEffects(new ZenDeviceEffects.Builder()
.setShouldDimWallpaper(true)
.build())
.build();
- ZenMode zenMode = new ZenMode("id", rule, true);
assertThat(mSummaryHelper.getDisplayEffectsSummary(zenMode)).isEqualTo(
"Dim the wallpaper");
@@ -271,16 +229,13 @@ public class ZenModesSummaryHelperTest {
@Test
public void getDisplayEffectsSummary_duo() {
- AutomaticZenRule rule = new AutomaticZenRule.Builder("Bedtime", Uri.parse("bed"))
- .setType(AutomaticZenRule.TYPE_BEDTIME)
- .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
+ ZenMode zenMode = new TestModeBuilder()
.setZenPolicy(new ZenPolicy.Builder().showAllVisualEffects().build())
.setDeviceEffects(new ZenDeviceEffects.Builder()
.setShouldDimWallpaper(true)
.setShouldDisplayGrayscale(true)
.build())
.build();
- ZenMode zenMode = new ZenMode("id", rule, true);
assertThat(mSummaryHelper.getDisplayEffectsSummary(zenMode)).isEqualTo(
"Grayscale and dim the wallpaper");
@@ -288,9 +243,7 @@ public class ZenModesSummaryHelperTest {
@Test
public void getDisplayEffectsSummary_trio() {
- AutomaticZenRule rule = new AutomaticZenRule.Builder("Bedtime", Uri.parse("bed"))
- .setType(AutomaticZenRule.TYPE_BEDTIME)
- .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
+ ZenMode zenMode = new TestModeBuilder()
.setZenPolicy(new ZenPolicy.Builder()
.hideAllVisualEffects()
.allowAlarms(true)
@@ -302,7 +255,6 @@ public class ZenModesSummaryHelperTest {
.setShouldDimWallpaper(true)
.build())
.build();
- ZenMode zenMode = new ZenMode("id", rule, true);
assertThat(mSummaryHelper.getDisplayEffectsSummary(zenMode)).isEqualTo(
"Notifications hidden, grayscale, and dim the wallpaper");
@@ -310,9 +262,7 @@ public class ZenModesSummaryHelperTest {
@Test
public void getDisplayEffectsSummary_quad() {
- AutomaticZenRule rule = new AutomaticZenRule.Builder("Bedtime", Uri.parse("bed"))
- .setType(AutomaticZenRule.TYPE_BEDTIME)
- .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
+ ZenMode zenMode = new TestModeBuilder()
.setZenPolicy(new ZenPolicy.Builder()
.showAllVisualEffects()
.showVisualEffect(VISUAL_EFFECT_AMBIENT, false)
@@ -326,7 +276,6 @@ public class ZenModesSummaryHelperTest {
.setShouldUseNightMode(true)
.build())
.build();
- ZenMode zenMode = new ZenMode("id", rule, true);
assertThat(mSummaryHelper.getDisplayEffectsSummary(zenMode)).isEqualTo(
"Notifications partially hidden, grayscale, and 2 more");
@@ -334,28 +283,22 @@ public class ZenModesSummaryHelperTest {
@Test
public void getAppsSummary_none() {
- AutomaticZenRule rule = new AutomaticZenRule.Builder("Bedtime", Uri.parse("bed"))
- .setType(AutomaticZenRule.TYPE_BEDTIME)
- .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
+ ZenMode zenMode = new TestModeBuilder()
.setZenPolicy(new ZenPolicy.Builder()
.allowChannels(ZenPolicy.CHANNEL_POLICY_NONE)
.build())
.build();
- ZenMode zenMode = new ZenMode("id", rule, true);
assertThat(mSummaryHelper.getAppsSummary(zenMode, new LinkedHashSet<>())).isEqualTo("None");
}
@Test
public void getAppsSummary_priorityAppsNoList() {
- AutomaticZenRule rule = new AutomaticZenRule.Builder("Bedtime", Uri.parse("bed"))
- .setType(AutomaticZenRule.TYPE_BEDTIME)
- .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
+ ZenMode zenMode = new TestModeBuilder()
.setZenPolicy(new ZenPolicy.Builder()
.allowChannels(ZenPolicy.CHANNEL_POLICY_PRIORITY)
.build())
.build();
- ZenMode zenMode = new ZenMode("id", rule, true);
assertThat(mSummaryHelper.getAppsSummary(zenMode, null)).isEqualTo("Selected apps");
}
@@ -397,19 +340,15 @@ public class ZenModesSummaryHelperTest {
@Test
public void getAppsSummary_priorityApps() {
- AutomaticZenRule rule = new AutomaticZenRule.Builder("Bedtime", Uri.parse("bed"))
- .setType(AutomaticZenRule.TYPE_BEDTIME)
- .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
+ ZenMode zenMode = new TestModeBuilder()
.setZenPolicy(new ZenPolicy.Builder()
.allowChannels(ZenPolicy.CHANNEL_POLICY_PRIORITY)
.build())
.build();
- ZenMode zenMode = new ZenMode("id", rule, true);
Set apps = Set.of("My App", "SecondApp", "ThirdApp", "FourthApp",
"FifthApp", "SixthApp");
assertThat(mSummaryHelper.getAppsSummary(zenMode, apps)).isEqualTo("FifthApp, FourthApp, "
+ "and 4 more can interrupt");
}
-
}
diff --git a/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSettingsForSubTest.java b/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSettingsForSubTest.java
index 4497a0a62b9..4440bc94ca0 100644
--- a/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSettingsForSubTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSettingsForSubTest.java
@@ -48,6 +48,8 @@ import android.telephony.TelephonyManager;
import android.telephony.ims.ImsMmTelManager;
import android.view.View;
+import androidx.annotation.NonNull;
+import androidx.lifecycle.LifecycleOwner;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
@@ -56,10 +58,14 @@ import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.network.ims.MockWifiCallingQueryImsState;
import com.android.settings.network.ims.WifiCallingQueryImsState;
+import com.android.settings.network.telephony.wificalling.IWifiCallingRepository;
import com.android.settings.testutils.shadow.ShadowFragment;
import com.android.settings.widget.SettingsMainSwitchBar;
import com.android.settings.widget.SettingsMainSwitchPreference;
+import kotlin.Unit;
+import kotlin.jvm.functions.Function1;
+
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -183,35 +189,24 @@ public class WifiCallingSettingsForSubTest {
}
@Test
- public void onResume_provisioningAllowed_shouldNotFinish() {
- // Call onResume while provisioning is allowed.
- mFragment.onResume();
+ public void onViewCreated_provisioningAllowed_shouldNotFinish() {
+ // Call onViewCreated while provisioning is allowed.
+ mFragment.onViewCreated(mView, null);
// Verify that finish() is not called.
verify(mFragment, never()).finish();
}
@Test
- public void onResume_provisioningDisallowed_shouldFinish() {
- // Call onResume while provisioning is disallowed.
- mQueryImsState.setIsProvisionedOnDevice(false);
- mFragment.onResume();
+ public void onViewCreated_provisioningDisallowed_shouldFinish() {
+ // Call onViewCreated while provisioning is disallowed.
+ mFragment.mIsWifiCallingReady = false;
+ mFragment.onViewCreated(mView, null);
// Verify that finish() is called
verify(mFragment).finish();
}
- @Test
- public void onResumeOnPause_provisioningCallbackRegistration() throws Exception {
- // Verify that provisioning callback is registered after call to onResume().
- mFragment.onResume();
- verify(mFragment).registerProvisioningChangedCallback();
-
- // Verify that provisioning callback is unregistered after call to onPause.
- mFragment.onPause();
- verify(mFragment).unregisterProvisioningChangedCallback();
- }
-
@Test
public void onResume_useWfcHomeModeConfigFalseAndEditable_shouldShowWfcRoaming() {
// Call onResume to update the WFC roaming preference.
@@ -377,6 +372,7 @@ public class WifiCallingSettingsForSubTest {
protected class TestFragment extends WifiCallingSettingsForSub {
private SettingsMainSwitchPreference mSwitchPref;
+ protected boolean mIsWifiCallingReady = true;
protected void setSwitchBar(SettingsMainSwitchPreference switchPref) {
mSwitchPref = switchPref;
@@ -421,6 +417,25 @@ public class WifiCallingSettingsForSubTest {
return mQueryImsState;
}
+ @Override
+ @NonNull
+ IWifiCallingRepository getWifiCallingRepository() {
+ return new IWifiCallingRepository() {
+ @Override
+ public void collectIsWifiCallingReadyFlow(
+ @NonNull LifecycleOwner lifecycleOwner,
+ @NonNull Function1 super Boolean, Unit> action) {
+ action.invoke(mIsWifiCallingReady);
+ }
+ };
+ }
+
+ @NonNull
+ @Override
+ LifecycleOwner getLifecycleOwner() {
+ return this;
+ }
+
@Override
void showAlert(Intent intent) {
}