Merge "Add new database table and proto for battery usage reattribution (2/5)" into main
diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingCallAudioPreferenceController.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingCallAudioPreferenceController.java
index b623ba8..6ba7183 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingCallAudioPreferenceController.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingCallAudioPreferenceController.java
@@ -72,7 +72,7 @@
private static final String PREF_KEY = "calls_and_alarms";
@VisibleForTesting
- protected enum ChangeCallAudioType {
+ enum ChangeCallAudioType {
UNKNOWN,
CONNECTED_EARLIER,
CONNECTED_LATER
@@ -90,7 +90,9 @@
Map<Integer, List<CachedBluetoothDevice>> mGroupedConnectedDevices = new HashMap<>();
private List<AudioSharingDeviceItem> mDeviceItemsInSharingSession = new ArrayList<>();
private final AtomicBoolean mCallbacksRegistered = new AtomicBoolean(false);
- private final BluetoothLeBroadcastAssistant.Callback mBroadcastAssistantCallback =
+
+ @VisibleForTesting
+ final BluetoothLeBroadcastAssistant.Callback mBroadcastAssistantCallback =
new BluetoothLeBroadcastAssistant.Callback() {
@Override
public void onSearchStarted(int reason) {}
@@ -276,7 +278,7 @@
/** Test only: set callback registration status in tests. */
@VisibleForTesting
- public void setCallbacksRegistered(boolean registered) {
+ void setCallbacksRegistered(boolean registered) {
mCallbacksRegistered.set(registered);
}
@@ -385,7 +387,7 @@
}
@VisibleForTesting
- protected void logCallAudioDeviceChange(int currentGroupId, CachedBluetoothDevice target) {
+ void logCallAudioDeviceChange(int currentGroupId, CachedBluetoothDevice target) {
var unused =
ThreadUtils.postOnBackgroundThread(
() -> {
diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingCompatibilityPreferenceController.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingCompatibilityPreferenceController.java
index 581ad62..42a9038 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingCompatibilityPreferenceController.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingCompatibilityPreferenceController.java
@@ -60,7 +60,7 @@
private final AtomicBoolean mCallbacksRegistered = new AtomicBoolean(false);
@VisibleForTesting
- protected final BluetoothLeBroadcast.Callback mBroadcastCallback =
+ final BluetoothLeBroadcast.Callback mBroadcastCallback =
new BluetoothLeBroadcast.Callback() {
@Override
public void onBroadcastStarted(int reason, int broadcastId) {
@@ -219,7 +219,7 @@
/** Test only: set callbacks registration state for test setup. */
@VisibleForTesting
- public void setCallbacksRegistered(boolean registered) {
+ void setCallbacksRegistered(boolean registered) {
mCallbacksRegistered.set(registered);
}
diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDashboardFragment.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDashboardFragment.java
index c7d7407..ad41e8a 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDashboardFragment.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDashboardFragment.java
@@ -103,7 +103,7 @@
/** Test only: set mock controllers for the {@link AudioSharingDashboardFragment} */
@VisibleForTesting
- protected void setControllers(
+ void setControllers(
AudioSharingDeviceVolumeGroupController volumeGroupController,
AudioSharingCallAudioPreferenceController callAudioController,
AudioSharingPlaySoundPreferenceController playSoundController,
diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceController.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceController.java
index 51a8e11..b932a7e 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceController.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceController.java
@@ -87,7 +87,8 @@
@Nullable private AudioSharingDialogHandler mDialogHandler;
private AtomicBoolean mIntentHandled = new AtomicBoolean(false);
- private BluetoothLeBroadcastAssistant.Callback mBroadcastAssistantCallback =
+ @VisibleForTesting
+ BluetoothLeBroadcastAssistant.Callback mBroadcastAssistantCallback =
new BluetoothLeBroadcastAssistant.Callback() {
@Override
public void onSearchStarted(int reason) {}
@@ -368,23 +369,23 @@
}
@VisibleForTesting
- public void setBluetoothDeviceUpdater(@Nullable BluetoothDeviceUpdater bluetoothDeviceUpdater) {
+ void setBluetoothDeviceUpdater(@Nullable BluetoothDeviceUpdater bluetoothDeviceUpdater) {
mBluetoothDeviceUpdater = bluetoothDeviceUpdater;
}
@VisibleForTesting
- public void setDialogHandler(@Nullable AudioSharingDialogHandler dialogHandler) {
+ void setDialogHandler(@Nullable AudioSharingDialogHandler dialogHandler) {
mDialogHandler = dialogHandler;
}
@VisibleForTesting
- public void setHostFragment(@Nullable DashboardFragment fragment) {
+ void setHostFragment(@Nullable DashboardFragment fragment) {
mFragment = fragment;
}
/** Test only: set intent handle state for test. */
@VisibleForTesting
- public void setIntentHandled(boolean handled) {
+ void setIntentHandled(boolean handled) {
mIntentHandled.set(handled);
}
diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumeGroupController.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumeGroupController.java
index 4a067ac..ee2ba7b 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumeGroupController.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumeGroupController.java
@@ -79,13 +79,10 @@
private Map<Integer, Integer> mValueMap = new HashMap<Integer, Integer>();
private AtomicBoolean mCallbacksRegistered = new AtomicBoolean(false);
- private BluetoothVolumeControl.Callback mVolumeControlCallback =
+ @VisibleForTesting
+ BluetoothVolumeControl.Callback mVolumeControlCallback =
new BluetoothVolumeControl.Callback() {
@Override
- public void onVolumeOffsetChanged(
- @NonNull BluetoothDevice device, int volumeOffset) {}
-
- @Override
public void onDeviceVolumeChanged(
@NonNull BluetoothDevice device,
@IntRange(from = -255, to = 255) int volume) {
@@ -117,7 +114,8 @@
}
};
- private BluetoothLeBroadcastAssistant.Callback mBroadcastAssistantCallback =
+ @VisibleForTesting
+ BluetoothLeBroadcastAssistant.Callback mBroadcastAssistantCallback =
new BluetoothLeBroadcastAssistant.Callback() {
@Override
public void onSearchStarted(int reason) {}
@@ -323,26 +321,26 @@
}
@VisibleForTesting
- public void setDeviceUpdater(@Nullable AudioSharingDeviceVolumeControlUpdater updater) {
+ void setDeviceUpdater(@Nullable AudioSharingDeviceVolumeControlUpdater updater) {
mBluetoothDeviceUpdater = updater;
}
/** Test only: set callback registration status in tests. */
@VisibleForTesting
- public void setCallbacksRegistered(boolean registered) {
+ void setCallbacksRegistered(boolean registered) {
mCallbacksRegistered.set(registered);
}
/** Test only: set volume map in tests. */
@VisibleForTesting
- public void setVolumeMap(@Nullable Map<Integer, Integer> map) {
+ void setVolumeMap(@Nullable Map<Integer, Integer> map) {
mValueMap.clear();
mValueMap.putAll(map);
}
/** Test only: set value for private preferenceGroup in tests. */
@VisibleForTesting
- public void setPreferenceGroup(@Nullable PreferenceGroup group) {
+ void setPreferenceGroup(@Nullable PreferenceGroup group) {
mPreferenceGroup = group;
mPreference = group;
}
diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogFactory.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogFactory.java
index 165beae..2ee286d 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogFactory.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogFactory.java
@@ -345,4 +345,6 @@
return dialog;
}
}
+
+ private AudioSharingDialogFactory() {}
}
diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogFragment.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogFragment.java
index 3d111fd..e787be3 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogFragment.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogFragment.java
@@ -100,7 +100,8 @@
/** Test only: get the event data passed to the dialog. */
@VisibleForTesting
- protected @NonNull Pair<Integer, Object>[] getEventData() {
+ @NonNull
+ Pair<Integer, Object>[] getEventData() {
return sEventData;
}
diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogHandler.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogHandler.java
index 5458a9f..8d69cf6 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogHandler.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogHandler.java
@@ -28,6 +28,7 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
import androidx.fragment.app.DialogFragment;
import androidx.fragment.app.Fragment;
@@ -61,7 +62,8 @@
private final MetricsFeatureProvider mMetricsFeatureProvider;
private List<BluetoothDevice> mTargetSinks = new ArrayList<>();
- private final BluetoothLeBroadcast.Callback mBroadcastCallback =
+ @VisibleForTesting
+ final BluetoothLeBroadcast.Callback mBroadcastCallback =
new BluetoothLeBroadcast.Callback() {
@Override
public void onBroadcastStarted(int reason, int broadcastId) {
diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDisconnectDialogFragment.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDisconnectDialogFragment.java
index 5f6d84a..dcd8a3b 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDisconnectDialogFragment.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDisconnectDialogFragment.java
@@ -145,9 +145,17 @@
return sNewDevice;
}
+ /** Test only: get the {@link DialogEventListener} passed to the dialog. */
+ @VisibleForTesting
+ @Nullable
+ DialogEventListener getListener() {
+ return sListener;
+ }
+
/** Test only: get the event data passed to the dialog. */
@VisibleForTesting
- protected @NonNull Pair<Integer, Object>[] getEventData() {
+ @NonNull
+ Pair<Integer, Object>[] getEventData() {
return sEventData;
}
diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingJoinDialogFragment.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingJoinDialogFragment.java
index 7eebbcb..ec669bf 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingJoinDialogFragment.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingJoinDialogFragment.java
@@ -110,9 +110,17 @@
return sNewDevice;
}
+ /** Test only: get the {@link DialogEventListener} passed to the dialog. */
+ @VisibleForTesting
+ @Nullable
+ DialogEventListener getListener() {
+ return sListener;
+ }
+
/** Test only: get the event data passed to the dialog. */
@VisibleForTesting
- protected @NonNull Pair<Integer, Object>[] getEventData() {
+ @NonNull
+ Pair<Integer, Object>[] getEventData() {
return sEventData;
}
diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingPlaySoundPreferenceController.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingPlaySoundPreferenceController.java
index 46c7f9c..11b195c 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingPlaySoundPreferenceController.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingPlaySoundPreferenceController.java
@@ -105,7 +105,7 @@
}
@VisibleForTesting
- protected void setRingtone(Ringtone ringtone) {
+ void setRingtone(Ringtone ringtone) {
mRingtone = ringtone;
}
diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingPreferenceController.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingPreferenceController.java
index d27d3a2..0244889 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingPreferenceController.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingPreferenceController.java
@@ -52,7 +52,7 @@
private final Executor mExecutor;
@VisibleForTesting
- protected final BluetoothLeBroadcast.Callback mBroadcastCallback =
+ final BluetoothLeBroadcast.Callback mBroadcastCallback =
new BluetoothLeBroadcast.Callback() {
@Override
public void onBroadcastStarted(int reason, int broadcastId) {
diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingStopDialogFragment.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingStopDialogFragment.java
index beac4b0..59593ba 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingStopDialogFragment.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingStopDialogFragment.java
@@ -142,7 +142,8 @@
/** Test only: get the event data passed to the dialog. */
@VisibleForTesting
- protected @NonNull Pair<Integer, Object>[] getEventData() {
+ @NonNull
+ Pair<Integer, Object>[] getEventData() {
return sEventData;
}
diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarController.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarController.java
index 5022579..89d2c95 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarController.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarController.java
@@ -117,7 +117,7 @@
};
@VisibleForTesting
- protected final BluetoothLeBroadcast.Callback mBroadcastCallback =
+ final BluetoothLeBroadcast.Callback mBroadcastCallback =
new BluetoothLeBroadcast.Callback() {
@Override
public void onBroadcastStarted(int reason, int broadcastId) {
@@ -392,7 +392,7 @@
/** Test only: set callback registration status in tests. */
@VisibleForTesting
- public void setCallbacksRegistered(boolean registered) {
+ void setCallbacksRegistered(boolean registered) {
mCallbacksRegistered.set(registered);
}
diff --git a/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java b/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java
index f63b649..0132273 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java
@@ -39,6 +39,9 @@
/** Check whether the battery tips card is enabled in the battery usage page */
boolean isBatteryTipsEnabled();
+ /** Check whether force expire the app optimization mode. */
+ boolean isForceExpireAppOptimizationModeEnabled();
+
/** Check whether to log the optimization mode of app entry in period job */
boolean isAppOptimizationModeLogged();
diff --git a/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java b/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java
index cc6659a..1675ce6 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java
@@ -84,6 +84,11 @@
}
@Override
+ public boolean isForceExpireAppOptimizationModeEnabled() {
+ return false;
+ }
+
+ @Override
public boolean isAppOptimizationModeLogged() {
return false;
}
diff --git a/src/com/android/settings/fuelgauge/batteryusage/AppOptModeSharedPreferencesUtils.kt b/src/com/android/settings/fuelgauge/batteryusage/AppOptModeSharedPreferencesUtils.kt
index 1111bd4..afff1c9 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/AppOptModeSharedPreferencesUtils.kt
+++ b/src/com/android/settings/fuelgauge/batteryusage/AppOptModeSharedPreferencesUtils.kt
@@ -25,6 +25,7 @@
import com.android.settings.fuelgauge.BatteryOptimizeHistoricalLogEntry.Action
import com.android.settings.fuelgauge.BatteryOptimizeUtils
import com.android.settings.fuelgauge.BatteryUtils
+import com.android.settings.overlay.FeatureFactory.Companion.featureFactory
/** A util to store and update app optimization mode expiration event data. */
object AppOptModeSharedPreferencesUtils {
@@ -74,10 +75,14 @@
@JvmStatic
fun resetExpiredAppOptModeBeforeTimestamp(context: Context, queryTimestampMs: Long) =
synchronized(appOptimizationModeLock) {
+ val forceExpireEnabled =
+ featureFactory
+ .powerUsageFeatureProvider.isForceExpireAppOptimizationModeEnabled
val eventsMap = getAppOptModeEventsMap(context)
val expirationUids = ArrayList<Int>(eventsMap.size)
for ((uid, event) in eventsMap) {
- if (event.expirationTime > queryTimestampMs) {
+ // Not reset the mode if forceExpireEnabled is false and not expired.
+ if (!forceExpireEnabled && event.expirationTime > queryTimestampMs) {
continue
}
updateBatteryOptimizationMode(
diff --git a/src/com/android/settings/fuelgauge/batteryusage/db/AppUsageEventDao.java b/src/com/android/settings/fuelgauge/batteryusage/db/AppUsageEventDao.java
deleted file mode 100644
index 2497801..0000000
--- a/src/com/android/settings/fuelgauge/batteryusage/db/AppUsageEventDao.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2022 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.fuelgauge.batteryusage.db;
-
-import android.database.Cursor;
-
-import androidx.room.Dao;
-import androidx.room.Insert;
-import androidx.room.OnConflictStrategy;
-import androidx.room.Query;
-
-import java.util.List;
-
-/** Data access object for accessing {@link AppUsageEventEntity} in the database. */
-@Dao
-public interface AppUsageEventDao {
-
- /** Inserts a {@link AppUsageEventEntity} data into the database. */
- @Insert(onConflict = OnConflictStrategy.REPLACE)
- void insert(AppUsageEventEntity event);
-
- /** Inserts {@link AppUsageEventEntity} data into the database. */
- @Insert(onConflict = OnConflictStrategy.REPLACE)
- void insertAll(List<AppUsageEventEntity> events);
-
- /** Lists all recorded data after a specific timestamp. */
- @Query("SELECT * FROM AppUsageEventEntity WHERE timestamp > :timestamp ORDER BY timestamp DESC")
- List<AppUsageEventEntity> getAllAfter(long timestamp);
-
- /** Gets the {@link Cursor} of all recorded data after a specific timestamp of the users. */
- @Query(
- "SELECT * FROM AppUsageEventEntity WHERE timestamp >= :timestamp"
- + " AND userId IN (:userIds) ORDER BY timestamp ASC")
- Cursor getAllForUsersAfter(List<Long> userIds, long timestamp);
-
- /** Gets the {@link Cursor} of the latest timestamp of the specific user. */
- @Query("SELECT MAX(timestamp) as timestamp FROM AppUsageEventEntity WHERE userId = :userId")
- Cursor getLatestTimestampOfUser(long userId);
-
- /** Deletes all recorded data before a specific timestamp. */
- @Query("DELETE FROM AppUsageEventEntity WHERE timestamp <= :timestamp")
- void clearAllBefore(long timestamp);
-
- /** Deletes all recorded data after a specific timestamp. */
- @Query("DELETE FROM AppUsageEventEntity WHERE timestamp >= :timestamp")
- void clearAllAfter(long timestamp);
-
- /** Clears all recorded data in the database. */
- @Query("DELETE FROM AppUsageEventEntity")
- void clearAll();
-}
diff --git a/src/com/android/settings/fuelgauge/batteryusage/db/AppUsageEventDao.kt b/src/com/android/settings/fuelgauge/batteryusage/db/AppUsageEventDao.kt
new file mode 100644
index 0000000..fa5fbc7
--- /dev/null
+++ b/src/com/android/settings/fuelgauge/batteryusage/db/AppUsageEventDao.kt
@@ -0,0 +1,59 @@
+/*
+ * 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.fuelgauge.batteryusage.db
+
+import android.database.Cursor
+import androidx.room.Dao
+import androidx.room.Insert
+import androidx.room.OnConflictStrategy
+import androidx.room.Query
+
+/** Data access object for accessing [AppUsageEventEntity] in the database. */
+@Dao
+interface AppUsageEventDao {
+ /** Inserts a [AppUsageEventEntity] data into the database. */
+ @Insert(onConflict = OnConflictStrategy.REPLACE) fun insert(event: AppUsageEventEntity)
+
+ /** Inserts [AppUsageEventEntity] data into the database. */
+ @Insert(onConflict = OnConflictStrategy.REPLACE)
+ fun insertAll(events: List<AppUsageEventEntity>)
+
+ /** Lists all recorded data after a specific timestamp. */
+ @Query("SELECT * FROM AppUsageEventEntity WHERE timestamp > :timestamp ORDER BY timestamp DESC")
+ fun getAllAfter(timestamp: Long): List<AppUsageEventEntity>
+
+ /** Gets the [Cursor] of all recorded data after a specific timestamp of the users. */
+ @Query(
+ "SELECT * FROM AppUsageEventEntity WHERE timestamp >= :timestamp" +
+ " AND userId IN (:userIds) ORDER BY timestamp ASC"
+ )
+ fun getAllForUsersAfter(userIds: List<Long>, timestamp: Long): Cursor
+
+ /** Gets the [Cursor] of the latest timestamp of the specific user. */
+ @Query("SELECT MAX(timestamp) as timestamp FROM AppUsageEventEntity WHERE userId = :userId")
+ fun getLatestTimestampOfUser(userId: Long): Cursor
+
+ /** Deletes all recorded data before a specific timestamp. */
+ @Query("DELETE FROM AppUsageEventEntity WHERE timestamp <= :timestamp")
+ fun clearAllBefore(timestamp: Long)
+
+ /** Deletes all recorded data after a specific timestamp. */
+ @Query("DELETE FROM AppUsageEventEntity WHERE timestamp >= :timestamp")
+ fun clearAllAfter(timestamp: Long)
+
+ /** Clears all recorded data in the database. */
+ @Query("DELETE FROM AppUsageEventEntity") fun clearAll()
+}
diff --git a/src/com/android/settings/fuelgauge/batteryusage/db/BatteryEventDao.java b/src/com/android/settings/fuelgauge/batteryusage/db/BatteryEventDao.java
deleted file mode 100644
index 19d2043..0000000
--- a/src/com/android/settings/fuelgauge/batteryusage/db/BatteryEventDao.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2023 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.fuelgauge.batteryusage.db;
-
-import android.database.Cursor;
-
-import androidx.room.Dao;
-import androidx.room.Insert;
-import androidx.room.OnConflictStrategy;
-import androidx.room.Query;
-
-import java.util.List;
-
-/** Data access object for accessing {@link BatteryEventEntity} in the database. */
-@Dao
-public interface BatteryEventDao {
- /** Inserts a {@link BatteryEventEntity} data into the database. */
- @Insert(onConflict = OnConflictStrategy.REPLACE)
- void insert(BatteryEventEntity event);
-
- /** Gets all recorded data. */
- @Query("SELECT * FROM BatteryEventEntity ORDER BY timestamp DESC")
- List<BatteryEventEntity> getAll();
-
- /** Gets the {@link Cursor} of the last full charge time . */
- @Query(
- "SELECT MAX(timestamp) FROM BatteryEventEntity"
- + " WHERE batteryEventType = 3") // BatteryEventType.FULL_CHARGED = 3
- Cursor getLastFullChargeTimestamp();
-
- /** Gets the {@link Long} of the last full charge time . */
- @Query(
- "SELECT MAX(timestamp) FROM BatteryEventEntity"
- + " WHERE batteryEventType = 3") // BatteryEventType.FULL_CHARGED = 3
- Long getLastFullChargeTimestampForLog();
-
- /** Gets the {@link Cursor} of all recorded data after a specific timestamp. */
- @Query(
- "SELECT * FROM BatteryEventEntity"
- + " WHERE timestamp >= :timestamp AND batteryEventType IN (:batteryEventTypes)"
- + " ORDER BY timestamp DESC")
- Cursor getAllAfter(long timestamp, List<Integer> batteryEventTypes);
-
- /** Gets all recorded data after a specific timestamp for log.*/
- @Query(
- "SELECT * FROM BatteryEventEntity "
- + "WHERE timestamp >= :timestamp ORDER BY timestamp DESC")
- List<BatteryEventEntity> getAllAfterForLog(long timestamp);
-
- /** Deletes all recorded data before a specific timestamp. */
- @Query("DELETE FROM BatteryEventEntity WHERE timestamp <= :timestamp")
- void clearAllBefore(long timestamp);
-
- /** Deletes all recorded data after a specific timestamp. */
- @Query("DELETE FROM BatteryEventEntity WHERE timestamp >= :timestamp")
- void clearAllAfter(long timestamp);
-
- /** Clears all recorded data in the database. */
- @Query("DELETE FROM BatteryEventEntity")
- void clearAll();
-}
diff --git a/src/com/android/settings/fuelgauge/batteryusage/db/BatteryEventDao.kt b/src/com/android/settings/fuelgauge/batteryusage/db/BatteryEventDao.kt
new file mode 100644
index 0000000..bac97d0
--- /dev/null
+++ b/src/com/android/settings/fuelgauge/batteryusage/db/BatteryEventDao.kt
@@ -0,0 +1,73 @@
+/*
+ * 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.fuelgauge.batteryusage.db
+
+import android.database.Cursor
+import androidx.room.Dao
+import androidx.room.Insert
+import androidx.room.OnConflictStrategy
+import androidx.room.Query
+
+/** Data access object for accessing [BatteryEventEntity] in the database. */
+@Dao
+interface BatteryEventDao {
+ /** Inserts a [BatteryEventEntity] data into the database. */
+ @Insert(onConflict = OnConflictStrategy.REPLACE) fun insert(event: BatteryEventEntity)
+
+ /** Gets all recorded data. */
+ @Query("SELECT * FROM BatteryEventEntity ORDER BY timestamp DESC")
+ fun getAll(): List<BatteryEventEntity>
+
+ /** Gets the [Cursor] of the last full charge time. */
+ @Query(
+ "SELECT MAX(timestamp) FROM BatteryEventEntity" +
+ " WHERE batteryEventType = 3" // BatteryEventType.FULL_CHARGED = 3
+ )
+ fun getLastFullChargeTimestamp(): Cursor
+
+ /** Gets the [Long] of the last full charge time. */
+ @Query(
+ "SELECT MAX(timestamp) FROM BatteryEventEntity" +
+ " WHERE batteryEventType = 3" // BatteryEventType.FULL_CHARGED = 3
+ )
+ fun getLastFullChargeTimestampForLog(): Long?
+
+ /** Gets the [Cursor] of all recorded data after a specific timestamp. */
+ @Query(
+ "SELECT * FROM BatteryEventEntity" +
+ " WHERE timestamp >= :timestamp AND batteryEventType IN (:batteryEventTypes)" +
+ " ORDER BY timestamp DESC"
+ )
+ fun getAllAfter(timestamp: Long, batteryEventTypes: List<Int>): Cursor
+
+ /** Gets all recorded data after a specific timestamp for log. */
+ @Query(
+ "SELECT * FROM BatteryEventEntity " +
+ "WHERE timestamp >= :timestamp ORDER BY timestamp DESC"
+ )
+ fun getAllAfterForLog(timestamp: Long): List<BatteryEventEntity>
+
+ /** Deletes all recorded data before a specific timestamp. */
+ @Query("DELETE FROM BatteryEventEntity WHERE timestamp <= :timestamp")
+ fun clearAllBefore(timestamp: Long)
+
+ /** Deletes all recorded data after a specific timestamp. */
+ @Query("DELETE FROM BatteryEventEntity WHERE timestamp >= :timestamp")
+ fun clearAllAfter(timestamp: Long)
+
+ /** Clears all recorded data in the database. */
+ @Query("DELETE FROM BatteryEventEntity") fun clearAll()
+}
diff --git a/src/com/android/settings/fuelgauge/batteryusage/db/BatteryStateDao.java b/src/com/android/settings/fuelgauge/batteryusage/db/BatteryStateDao.java
deleted file mode 100644
index 049251e..0000000
--- a/src/com/android/settings/fuelgauge/batteryusage/db/BatteryStateDao.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2022 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.fuelgauge.batteryusage.db;
-
-import android.database.Cursor;
-
-import androidx.room.Dao;
-import androidx.room.Insert;
-import androidx.room.OnConflictStrategy;
-import androidx.room.Query;
-
-import java.util.List;
-
-/** Data access object for accessing {@link BatteryState} in the database. */
-@Dao
-public interface BatteryStateDao {
-
- /** Inserts a {@link BatteryState} data into the database. */
- @Insert(onConflict = OnConflictStrategy.REPLACE)
- void insert(BatteryState state);
-
- /** Inserts {@link BatteryState} data into the database. */
- @Insert(onConflict = OnConflictStrategy.REPLACE)
- void insertAll(List<BatteryState> states);
-
- /** Gets the {@link Cursor} of the latest record timestamp no later than the given timestamp. */
- @Query("SELECT MAX(timestamp) FROM BatteryState WHERE timestamp <= :timestamp")
- Cursor getLatestTimestampBefore(long timestamp);
-
- /** Lists all recorded battery states after a specific timestamp. */
- @Query("SELECT * FROM BatteryState WHERE timestamp >= :timestamp ORDER BY timestamp ASC")
- Cursor getBatteryStatesAfter(long timestamp);
-
- /** Lists all recorded data after a specific timestamp. */
- @Query("SELECT * FROM BatteryState WHERE timestamp > :timestamp ORDER BY timestamp DESC")
- List<BatteryState> getAllAfter(long timestamp);
-
- /** Get the count of distinct timestamp after a specific timestamp. */
- @Query("SELECT COUNT(DISTINCT timestamp) FROM BatteryState WHERE timestamp > :timestamp")
- int getDistinctTimestampCount(long timestamp);
-
- /** Lists all distinct timestamps after a specific timestamp. */
- @Query("SELECT DISTINCT timestamp FROM BatteryState WHERE timestamp > :timestamp")
- List<Long> getDistinctTimestamps(long timestamp);
-
- /** Deletes all recorded data before a specific timestamp. */
- @Query("DELETE FROM BatteryState WHERE timestamp <= :timestamp")
- void clearAllBefore(long timestamp);
-
- /** Deletes all recorded data after a specific timestamp. */
- @Query("DELETE FROM BatteryState WHERE timestamp >= :timestamp")
- void clearAllAfter(long timestamp);
-
- /** Clears all recorded data in the database. */
- @Query("DELETE FROM BatteryState")
- void clearAll();
-}
diff --git a/src/com/android/settings/fuelgauge/batteryusage/db/BatteryStateDao.kt b/src/com/android/settings/fuelgauge/batteryusage/db/BatteryStateDao.kt
new file mode 100644
index 0000000..6d31e07
--- /dev/null
+++ b/src/com/android/settings/fuelgauge/batteryusage/db/BatteryStateDao.kt
@@ -0,0 +1,63 @@
+/*
+ * 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.fuelgauge.batteryusage.db
+
+import android.database.Cursor
+import androidx.room.Dao
+import androidx.room.Insert
+import androidx.room.OnConflictStrategy
+import androidx.room.Query
+
+/** Data access object for accessing [BatteryState] in the database. */
+@Dao
+interface BatteryStateDao {
+ /** Inserts a [BatteryState] data into the database. */
+ @Insert(onConflict = OnConflictStrategy.REPLACE) fun insert(state: BatteryState)
+
+ /** Inserts [BatteryState] data into the database. */
+ @Insert(onConflict = OnConflictStrategy.REPLACE) fun insertAll(states: List<BatteryState>)
+
+ /** Gets the [Cursor] of the latest record timestamp no later than the given timestamp. */
+ @Query("SELECT MAX(timestamp) FROM BatteryState WHERE timestamp <= :timestamp")
+ fun getLatestTimestampBefore(timestamp: Long): Cursor
+
+ /** Lists all recorded battery states after a specific timestamp. */
+ @Query("SELECT * FROM BatteryState WHERE timestamp >= :timestamp ORDER BY timestamp ASC")
+ fun getBatteryStatesAfter(timestamp: Long): Cursor
+
+ /** Lists all recorded data after a specific timestamp. */
+ @Query("SELECT * FROM BatteryState WHERE timestamp > :timestamp ORDER BY timestamp DESC")
+ fun getAllAfter(timestamp: Long): List<BatteryState>
+
+ /** Get the count of distinct timestamp after a specific timestamp. */
+ @Query("SELECT COUNT(DISTINCT timestamp) FROM BatteryState WHERE timestamp > :timestamp")
+ fun getDistinctTimestampCount(timestamp: Long): Int
+
+ /** Lists all distinct timestamps after a specific timestamp. */
+ @Query("SELECT DISTINCT timestamp FROM BatteryState WHERE timestamp > :timestamp")
+ fun getDistinctTimestamps(timestamp: Long): List<Long>
+
+ /** Deletes all recorded data before a specific timestamp. */
+ @Query("DELETE FROM BatteryState WHERE timestamp <= :timestamp")
+ fun clearAllBefore(timestamp: Long)
+
+ /** Deletes all recorded data after a specific timestamp. */
+ @Query("DELETE FROM BatteryState WHERE timestamp >= :timestamp")
+ fun clearAllAfter(timestamp: Long)
+
+ /** Clears all recorded data in the database. */
+ @Query("DELETE FROM BatteryState") fun clearAll()
+}
diff --git a/src/com/android/settings/fuelgauge/batteryusage/db/BatteryUsageSlotDao.java b/src/com/android/settings/fuelgauge/batteryusage/db/BatteryUsageSlotDao.java
deleted file mode 100644
index d53b0cf..0000000
--- a/src/com/android/settings/fuelgauge/batteryusage/db/BatteryUsageSlotDao.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2023 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.fuelgauge.batteryusage.db;
-
-import android.database.Cursor;
-
-import androidx.room.Dao;
-import androidx.room.Insert;
-import androidx.room.OnConflictStrategy;
-import androidx.room.Query;
-
-import java.util.List;
-
-/** Data access object for accessing {@link BatteryUsageSlotEntity} in the database. */
-@Dao
-public interface BatteryUsageSlotDao {
- /** Inserts a {@link BatteryUsageSlotEntity} data into the database. */
- @Insert(onConflict = OnConflictStrategy.REPLACE)
- void insert(BatteryUsageSlotEntity event);
-
- /** Gets all recorded data. */
- @Query("SELECT * FROM BatteryUsageSlotEntity ORDER BY timestamp ASC")
- List<BatteryUsageSlotEntity> getAll();
-
- /** Gets the {@link Cursor} of all recorded data after a specific timestamp. */
- @Query(
- "SELECT * FROM BatteryUsageSlotEntity WHERE timestamp >= :timestamp"
- + " ORDER BY timestamp ASC")
- Cursor getAllAfter(long timestamp);
-
- /** Gets all recorded data after a specific timestamp for log.*/
- @Query(
- "SELECT * FROM BatteryUsageSlotEntity WHERE timestamp >= :timestamp"
- + " ORDER BY timestamp DESC")
- List<BatteryUsageSlotEntity> getAllAfterForLog(long timestamp);
-
- /** Deletes all recorded data before a specific timestamp. */
- @Query("DELETE FROM BatteryUsageSlotEntity WHERE timestamp <= :timestamp")
- void clearAllBefore(long timestamp);
-
- /** Deletes all recorded data after a specific timestamp. */
- @Query("DELETE FROM BatteryUsageSlotEntity WHERE timestamp >= :timestamp")
- void clearAllAfter(long timestamp);
-
- /** Clears all recorded data in the database. */
- @Query("DELETE FROM BatteryUsageSlotEntity")
- void clearAll();
-}
diff --git a/src/com/android/settings/fuelgauge/batteryusage/db/BatteryUsageSlotDao.kt b/src/com/android/settings/fuelgauge/batteryusage/db/BatteryUsageSlotDao.kt
new file mode 100644
index 0000000..434c61a
--- /dev/null
+++ b/src/com/android/settings/fuelgauge/batteryusage/db/BatteryUsageSlotDao.kt
@@ -0,0 +1,58 @@
+/*
+ * 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.fuelgauge.batteryusage.db
+
+import android.database.Cursor
+import androidx.room.Dao
+import androidx.room.Insert
+import androidx.room.OnConflictStrategy
+import androidx.room.Query
+
+/** Data access object for accessing [BatteryUsageSlotEntity] in the database. */
+@Dao
+interface BatteryUsageSlotDao {
+ /** Inserts a [BatteryUsageSlotEntity] data into the database. */
+ @Insert(onConflict = OnConflictStrategy.REPLACE) fun insert(event: BatteryUsageSlotEntity)
+
+ /** Gets all recorded data. */
+ @Query("SELECT * FROM BatteryUsageSlotEntity ORDER BY timestamp ASC")
+ fun getAll(): List<BatteryUsageSlotEntity>
+
+ /** Gets the [Cursor] of all recorded data after a specific timestamp. */
+ @Query(
+ "SELECT * FROM BatteryUsageSlotEntity WHERE timestamp >= :timestamp" +
+ " ORDER BY timestamp ASC"
+ )
+ fun getAllAfter(timestamp: Long): Cursor
+
+ /** Gets all recorded data after a specific timestamp for log. */
+ @Query(
+ "SELECT * FROM BatteryUsageSlotEntity WHERE timestamp >= :timestamp" +
+ " ORDER BY timestamp DESC"
+ )
+ fun getAllAfterForLog(timestamp: Long): List<BatteryUsageSlotEntity>
+
+ /** Deletes all recorded data before a specific timestamp. */
+ @Query("DELETE FROM BatteryUsageSlotEntity WHERE timestamp <= :timestamp")
+ fun clearAllBefore(timestamp: Long)
+
+ /** Deletes all recorded data after a specific timestamp. */
+ @Query("DELETE FROM BatteryUsageSlotEntity WHERE timestamp >= :timestamp")
+ fun clearAllAfter(timestamp: Long)
+
+ /** Clears all recorded data in the database. */
+ @Query("DELETE FROM BatteryUsageSlotEntity") fun clearAll()
+}
diff --git a/src/com/android/settings/network/telephony/DataSubscriptionRepository.kt b/src/com/android/settings/network/telephony/DataSubscriptionRepository.kt
index 99f639b..62e7e98 100644
--- a/src/com/android/settings/network/telephony/DataSubscriptionRepository.kt
+++ b/src/com/android/settings/network/telephony/DataSubscriptionRepository.kt
@@ -51,46 +51,41 @@
)
.map { it.getIntExtra(SUBSCRIPTION_KEY, SubscriptionManager.INVALID_SUBSCRIPTION_ID) }
.onStart { emit(SubscriptionManager.getDefaultDataSubscriptionId()) }
+ .distinctUntilChanged()
.conflate()
.flowOn(Dispatchers.Default)
fun activeDataSubscriptionIdFlow(): Flow<Int> =
- telephonyManager.telephonyCallbackFlow {
- object : TelephonyCallback(), TelephonyCallback.ActiveDataSubscriptionIdListener {
- override fun onActiveDataSubscriptionIdChanged(subId: Int) {
- trySend(subId)
- Log.d(TAG, "activeDataSubscriptionIdFlow: $subId")
+ telephonyManager
+ .telephonyCallbackFlow {
+ object : TelephonyCallback(), TelephonyCallback.ActiveDataSubscriptionIdListener {
+ override fun onActiveDataSubscriptionIdChanged(subId: Int) {
+ trySend(subId)
+ Log.d(TAG, "activeDataSubscriptionIdFlow: $subId")
+ }
}
}
- }
+ .distinctUntilChanged()
fun dataSummaryFlow(): Flow<String> =
combine(defaultDataSubscriptionIdFlow(), activeDataSubscriptionIdFlow()) {
- defaultSubId,
- activeSubId ->
- DataSubscriptionIds(defaultSubId, activeSubId)
+ defaultDataSubId,
+ activeDataSubId ->
+ getDataSummary(defaultDataSubId, activeDataSubId)
}
- .distinctUntilChanged()
- .map { it.getDataSummary() }
.conflate()
.flowOn(Dispatchers.Default)
- private data class DataSubscriptionIds(
- val defaultSubId: Int,
- val activeSubId: Int,
- )
-
- private fun DataSubscriptionIds.getDataSummary(): String {
- val activeSubInfo = subscriptionManager.getActiveSubscriptionInfo(activeSubId) ?: return ""
+ private fun getDataSummary(defaultDataSubId: Int, activeDataSubId: Int): String {
+ if (defaultDataSubId == activeDataSubId) return getDisplayName(defaultDataSubId)
+ val activeSubInfo =
+ subscriptionManager.getActiveSubscriptionInfo(activeDataSubId)
+ ?: return getDisplayName(defaultDataSubId)
if (!SubscriptionUtil.isSubscriptionVisible(subscriptionManager, context, activeSubInfo)) {
- return getDisplayName(defaultSubId)
+ return getDisplayName(defaultDataSubId)
}
- val uniqueName = getDisplayName(activeSubId)
- return if (activeSubId == defaultSubId) {
- uniqueName
- } else {
- context.getString(R.string.mobile_data_temp_using, uniqueName)
- }
+ // non-DDS is active
+ return context.getString(R.string.mobile_data_temp_using, getDisplayName(activeDataSubId))
}
companion object {
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingBluetoothDeviceUpdaterTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingBluetoothDeviceUpdaterTest.java
index 23be208..785b1dc 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingBluetoothDeviceUpdaterTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingBluetoothDeviceUpdaterTest.java
@@ -58,6 +58,7 @@
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
+import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -143,6 +144,12 @@
mDeviceUpdater.setPrefContext(mContext);
}
+ @After
+ public void tearDown() {
+ ShadowThreadUtils.reset();
+ ShadowBluetoothUtils.reset();
+ }
+
@Test
public void onProfileConnectionStateChanged_leaDeviceConnected_flagOff_removesPref() {
setupPreferenceMapWithDevice();
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingCallAudioDialogFragmentTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingCallAudioDialogFragmentTest.java
index 979f149..7f0c1c9 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingCallAudioDialogFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingCallAudioDialogFragmentTest.java
@@ -33,6 +33,7 @@
import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
import com.android.settingslib.flags.Flags;
+import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -66,16 +67,16 @@
private Fragment mParent;
private AudioSharingCallAudioDialogFragment mFragment;
- private ShadowBluetoothAdapter mShadowBluetoothAdapter;
@Before
public void setUp() {
ShadowAlertDialogCompat.reset();
- mShadowBluetoothAdapter = Shadow.extract(BluetoothAdapter.getDefaultAdapter());
- mShadowBluetoothAdapter.setEnabled(true);
- mShadowBluetoothAdapter.setIsLeAudioBroadcastSourceSupported(
+ ShadowBluetoothAdapter shadowBluetoothAdapter =
+ Shadow.extract(BluetoothAdapter.getDefaultAdapter());
+ shadowBluetoothAdapter.setEnabled(true);
+ shadowBluetoothAdapter.setIsLeAudioBroadcastSourceSupported(
BluetoothStatusCodes.FEATURE_SUPPORTED);
- mShadowBluetoothAdapter.setIsLeAudioBroadcastAssistantSupported(
+ shadowBluetoothAdapter.setIsLeAudioBroadcastAssistantSupported(
BluetoothStatusCodes.FEATURE_SUPPORTED);
mFragment = new AudioSharingCallAudioDialogFragment();
mParent = new Fragment();
@@ -83,6 +84,11 @@
mParent, FragmentActivity.class, /* containerViewId= */ 0, /* bundle= */ null);
}
+ @After
+ public void tearDown() {
+ ShadowAlertDialogCompat.reset();
+ }
+
@Test
public void getMetricsCategory_correctValue() {
assertThat(mFragment.getMetricsCategory())
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingCallAudioPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingCallAudioPreferenceControllerTest.java
index af817d2..c72b5a5 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingCallAudioPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingCallAudioPreferenceControllerTest.java
@@ -25,7 +25,7 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.robolectric.Shadows.shadowOf;
@@ -35,6 +35,7 @@
import android.bluetooth.BluetoothCsipSetCoordinator;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothLeBroadcastAssistant;
+import android.bluetooth.BluetoothLeBroadcastMetadata;
import android.bluetooth.BluetoothLeBroadcastReceiveState;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothStatusCodes;
@@ -77,6 +78,7 @@
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
+import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -130,6 +132,7 @@
@Mock private CachedBluetoothDevice mCachedDevice2;
@Mock private CachedBluetoothDevice mCachedDevice3;
@Mock private BluetoothLeBroadcastReceiveState mState;
+ @Mock private BluetoothLeBroadcastMetadata mSource;
@Mock private ContentResolver mContentResolver;
private AudioSharingCallAudioPreferenceController mController;
@Spy private ContentObserver mContentObserver;
@@ -142,6 +145,7 @@
@Before
public void setUp() {
+ ShadowAlertDialogCompat.reset();
mShadowBluetoothAdapter = Shadow.extract(BluetoothAdapter.getDefaultAdapter());
mShadowBluetoothAdapter.setEnabled(true);
mShadowBluetoothAdapter.setIsLeAudioBroadcastSourceSupported(
@@ -179,17 +183,24 @@
when(mScreen.findPreference(PREF_KEY)).thenReturn(mPreference);
}
+ @After
+ public void tearDown() {
+ ShadowAlertDialogCompat.reset();
+ ShadowThreadUtils.reset();
+ ShadowBluetoothUtils.reset();
+ }
+
@Test
public void onStart_flagOff_doNothing() {
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
mController.onStart(mLifecycleOwner);
- verify(mBtEventManager, times(0)).registerCallback(mController);
- verify(mContentResolver, times(0))
+ verify(mBtEventManager, never()).registerCallback(mController);
+ verify(mContentResolver, never())
.registerContentObserver(
Settings.Secure.getUriFor(SETTINGS_KEY_FALLBACK_DEVICE_GROUP_ID),
false,
mContentObserver);
- verify(mAssistant, times(0))
+ verify(mAssistant, never())
.registerServiceCallBack(any(), any(BluetoothLeBroadcastAssistant.Callback.class));
}
@@ -212,9 +223,9 @@
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
mController.setCallbacksRegistered(true);
mController.onStop(mLifecycleOwner);
- verify(mBtEventManager, times(0)).unregisterCallback(mController);
- verify(mContentResolver, times(0)).unregisterContentObserver(mContentObserver);
- verify(mAssistant, times(0))
+ verify(mBtEventManager, never()).unregisterCallback(mController);
+ verify(mContentResolver, never()).unregisterContentObserver(mContentObserver);
+ verify(mAssistant, never())
.unregisterServiceCallBack(any(BluetoothLeBroadcastAssistant.Callback.class));
}
@@ -223,9 +234,9 @@
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
mController.setCallbacksRegistered(false);
mController.onStop(mLifecycleOwner);
- verify(mBtEventManager, times(0)).unregisterCallback(mController);
- verify(mContentResolver, times(0)).unregisterContentObserver(mContentObserver);
- verify(mAssistant, times(0))
+ verify(mBtEventManager, never()).unregisterCallback(mController);
+ verify(mContentResolver, never()).unregisterContentObserver(mContentObserver);
+ verify(mAssistant, never())
.unregisterServiceCallBack(any(BluetoothLeBroadcastAssistant.Callback.class));
}
@@ -500,4 +511,80 @@
AudioSharingCallAudioPreferenceController.ChangeCallAudioType.UNKNOWN
.ordinal());
}
+
+ @Test
+ public void testBluetoothLeBroadcastAssistantCallbacks_updateSummary() {
+ when(mCachedDevice1.getGroupId()).thenReturn(TEST_DEVICE_GROUP_ID1);
+ when(mCachedDevice1.getDevice()).thenReturn(mDevice1);
+ when(mCachedDevice1.getName()).thenReturn(TEST_DEVICE_NAME1);
+ when(mCacheManager.findDevice(mDevice1)).thenReturn(mCachedDevice1);
+ Settings.Secure.putInt(
+ mContentResolver, TEST_SETTINGS_KEY, BluetoothCsipSetCoordinator.GROUP_ID_INVALID);
+ when(mBroadcast.isEnabled(any())).thenReturn(true);
+ when(mAssistant.getDevicesMatchingConnectionStates(
+ new int[] {BluetoothProfile.STATE_CONNECTED}))
+ .thenReturn(ImmutableList.of());
+ mController.displayPreference(mScreen);
+ shadowOf(Looper.getMainLooper()).idle();
+ assertThat(mPreference.getSummary().toString()).isEmpty();
+
+ // onReceiveStateChanged will update summary
+ Settings.Secure.putInt(mContentResolver, TEST_SETTINGS_KEY, TEST_DEVICE_GROUP_ID1);
+ when(mAssistant.getDevicesMatchingConnectionStates(
+ new int[] {BluetoothProfile.STATE_CONNECTED}))
+ .thenReturn(ImmutableList.of(mDevice1));
+ when(mAssistant.getAllSources(any())).thenReturn(ImmutableList.of(mState));
+ mController.mBroadcastAssistantCallback.onReceiveStateChanged(
+ mDevice1, /* sourceId= */ 1, mState);
+ shadowOf(Looper.getMainLooper()).idle();
+ assertThat(mPreference.getSummary().toString())
+ .isEqualTo(
+ mContext.getString(
+ R.string.audio_sharing_call_audio_description, TEST_DEVICE_NAME1));
+ }
+
+ @Test
+ public void testBluetoothLeBroadcastAssistantCallbacks_doNothing() {
+ when(mCachedDevice1.getGroupId()).thenReturn(TEST_DEVICE_GROUP_ID1);
+ when(mCachedDevice1.getDevice()).thenReturn(mDevice1);
+ when(mCachedDevice1.getName()).thenReturn(TEST_DEVICE_NAME1);
+ when(mCacheManager.findDevice(mDevice1)).thenReturn(mCachedDevice1);
+ Settings.Secure.putInt(
+ mContentResolver, TEST_SETTINGS_KEY, BluetoothCsipSetCoordinator.GROUP_ID_INVALID);
+ when(mBroadcast.isEnabled(any())).thenReturn(true);
+ when(mAssistant.getDevicesMatchingConnectionStates(
+ new int[] {BluetoothProfile.STATE_CONNECTED}))
+ .thenReturn(ImmutableList.of());
+ mController.displayPreference(mScreen);
+ shadowOf(Looper.getMainLooper()).idle();
+ assertThat(mPreference.getSummary().toString()).isEmpty();
+
+ Settings.Secure.putInt(mContentResolver, TEST_SETTINGS_KEY, TEST_DEVICE_GROUP_ID1);
+ when(mAssistant.getDevicesMatchingConnectionStates(
+ new int[] {BluetoothProfile.STATE_CONNECTED}))
+ .thenReturn(ImmutableList.of(mDevice1));
+ when(mAssistant.getAllSources(any())).thenReturn(ImmutableList.of(mState));
+ mController.mBroadcastAssistantCallback.onSearchStarted(/* reason= */ 1);
+ mController.mBroadcastAssistantCallback.onSearchStartFailed(/* reason= */ 1);
+ mController.mBroadcastAssistantCallback.onSearchStopped(/* reason= */ 1);
+ mController.mBroadcastAssistantCallback.onSearchStopFailed(/* reason= */ 1);
+ mController.mBroadcastAssistantCallback.onSourceAdded(
+ mDevice1, /* sourceId= */ 1, /* reason= */ 1);
+ mController.mBroadcastAssistantCallback.onSourceAddFailed(
+ mDevice1, mSource, /* reason= */ 1);
+ mController.mBroadcastAssistantCallback.onSourceRemoved(
+ mDevice1, /* sourceId= */ 1, /* reason= */ 1);
+ mController.mBroadcastAssistantCallback.onSourceRemoveFailed(
+ mDevice1, /* sourceId= */ 1, /* reason= */ 1);
+ mController.mBroadcastAssistantCallback.onSourceModified(
+ mDevice1, /* sourceId= */ 1, /* reason= */ 1);
+ mController.mBroadcastAssistantCallback.onSourceModifyFailed(
+ mDevice1, /* sourceId= */ 1, /* reason= */ 1);
+ mController.mBroadcastAssistantCallback.onSourceFound(mSource);
+ mController.mBroadcastAssistantCallback.onSourceLost(/* broadcastId= */ 1);
+ shadowOf(Looper.getMainLooper()).idle();
+
+ // Above callbacks won't update summary.
+ assertThat(mPreference.getSummary().toString()).isEmpty();
+ }
}
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingCompatibilityPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingCompatibilityPreferenceControllerTest.java
index 19221a6..74210cd 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingCompatibilityPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingCompatibilityPreferenceControllerTest.java
@@ -61,6 +61,7 @@
import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.flags.Flags;
+import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -128,6 +129,12 @@
when(mScreen.findPreference(PREF_KEY)).thenReturn(mPreference);
}
+ @After
+ public void tearDown() {
+ ShadowThreadUtils.reset();
+ ShadowBluetoothUtils.reset();
+ }
+
@Test
public void onStart_flagOn_registerCallback() {
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingConfirmDialogFragmentTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingConfirmDialogFragmentTest.java
index e5facc1..32f666f 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingConfirmDialogFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingConfirmDialogFragmentTest.java
@@ -61,7 +61,7 @@
@Before
public void setUp() {
- cleanUpDialogs();
+ ShadowAlertDialogCompat.reset();
ShadowBluetoothAdapter shadowBluetoothAdapter =
Shadow.extract(BluetoothAdapter.getDefaultAdapter());
shadowBluetoothAdapter.setEnabled(true);
@@ -77,7 +77,7 @@
@After
public void tearDown() {
- cleanUpDialogs();
+ ShadowAlertDialogCompat.reset();
}
@Test
@@ -118,12 +118,4 @@
shadowMainLooper().idle();
assertThat(dialog.isShowing()).isFalse();
}
-
- private void cleanUpDialogs() {
- AlertDialog latestAlertDialog = ShadowAlertDialogCompat.getLatestAlertDialog();
- if (latestAlertDialog != null) {
- latestAlertDialog.dismiss();
- ShadowAlertDialogCompat.reset();
- }
- }
}
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceControllerTest.java
index 14bca08..18f75ba 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceControllerTest.java
@@ -25,6 +25,7 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -35,6 +36,8 @@
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothLeBroadcastAssistant;
+import android.bluetooth.BluetoothLeBroadcastMetadata;
+import android.bluetooth.BluetoothLeBroadcastReceiveState;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothStatusCodes;
import android.content.Context;
@@ -74,6 +77,7 @@
import com.google.common.collect.ImmutableList;
+import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -85,6 +89,8 @@
import org.robolectric.annotation.Config;
import org.robolectric.shadow.api.Shadow;
+import java.util.ArrayList;
+import java.util.List;
import java.util.concurrent.Executor;
@RunWith(RobolectricTestRunner.class)
@@ -113,6 +119,8 @@
@Mock private LocalBluetoothLeBroadcast mBroadcast;
@Mock private LocalBluetoothLeBroadcastAssistant mAssistant;
@Mock private VolumeControlProfile mVolumeControl;
+ @Mock private BluetoothLeBroadcastReceiveState mState;
+ @Mock private BluetoothLeBroadcastMetadata mSource;
@Mock private PreferenceScreen mScreen;
@Mock private AudioSharingDialogHandler mDialogHandler;
@Mock private DashboardFragment mFragment;
@@ -173,17 +181,22 @@
mController.setHostFragment(mFragment);
}
+ @After
+ public void tearDown() {
+ ShadowBluetoothUtils.reset();
+ }
+
@Test
public void onStart_flagOff_doNothing() {
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
mController.onStart(mLifecycleOwner);
- verify(mEventManager, times(0)).registerCallback(any(BluetoothCallback.class));
- verify(mDialogHandler, times(0)).registerCallbacks(any(Executor.class));
- verify(mAssistant, times(0))
+ verify(mEventManager, never()).registerCallback(any(BluetoothCallback.class));
+ verify(mDialogHandler, never()).registerCallbacks(any(Executor.class));
+ verify(mAssistant, never())
.registerServiceCallBack(
any(Executor.class), any(BluetoothLeBroadcastAssistant.Callback.class));
- verify(mBluetoothDeviceUpdater, times(0)).registerCallback();
- verify(mBluetoothDeviceUpdater, times(0)).refreshPreference();
+ verify(mBluetoothDeviceUpdater, never()).registerCallback();
+ verify(mBluetoothDeviceUpdater, never()).refreshPreference();
}
@Test
@@ -203,11 +216,11 @@
public void onStop_flagOff_doNothing() {
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
mController.onStop(mLifecycleOwner);
- verify(mEventManager, times(0)).unregisterCallback(any(BluetoothCallback.class));
- verify(mDialogHandler, times(0)).unregisterCallbacks();
- verify(mAssistant, times(0))
+ verify(mEventManager, never()).unregisterCallback(any(BluetoothCallback.class));
+ verify(mDialogHandler, never()).unregisterCallbacks();
+ verify(mAssistant, never())
.unregisterServiceCallBack(any(BluetoothLeBroadcastAssistant.Callback.class));
- verify(mBluetoothDeviceUpdater, times(0)).unregisterCallback();
+ verify(mBluetoothDeviceUpdater, never()).unregisterCallback();
}
@Test
@@ -227,7 +240,7 @@
mController.displayPreference(mScreen);
assertThat(mPreferenceGroup.isVisible()).isFalse();
assertThat(mAudioSharingPreference.isVisible()).isFalse();
- verify(mBluetoothDeviceUpdater, times(0)).forceUpdate();
+ verify(mBluetoothDeviceUpdater, never()).forceUpdate();
}
@Test
@@ -401,8 +414,8 @@
doReturn(intent).when(mActivity).getIntent();
mController.displayPreference(mScreen);
- verify(mDeviceManager, times(0)).findDevice(any(BluetoothDevice.class));
- verify(mDialogHandler, times(0))
+ verify(mDeviceManager, never()).findDevice(any(BluetoothDevice.class));
+ verify(mDialogHandler, never())
.handleDeviceConnected(any(CachedBluetoothDevice.class), anyBoolean());
}
@@ -418,8 +431,8 @@
when(mDevice.isConnected()).thenReturn(false);
mController.displayPreference(mScreen);
- verify(mDeviceManager, times(0)).findDevice(any(BluetoothDevice.class));
- verify(mDialogHandler, times(0))
+ verify(mDeviceManager, never()).findDevice(any(BluetoothDevice.class));
+ verify(mDialogHandler, never())
.handleDeviceConnected(any(CachedBluetoothDevice.class), anyBoolean());
}
@@ -436,8 +449,8 @@
mController.setIntentHandled(true);
mController.displayPreference(mScreen);
- verify(mDeviceManager, times(0)).findDevice(any(BluetoothDevice.class));
- verify(mDialogHandler, times(0))
+ verify(mDeviceManager, never()).findDevice(any(BluetoothDevice.class));
+ verify(mDialogHandler, never())
.handleDeviceConnected(any(CachedBluetoothDevice.class), anyBoolean());
}
@@ -484,4 +497,56 @@
verify(mDialogHandler).handleDeviceConnected(mCachedDevice, true);
}
+
+ @Test
+ public void testBluetoothLeBroadcastAssistantCallbacks_updateGroup() {
+ // onReceiveStateChanged with unconnected state will do nothing
+ when(mState.getBisSyncState()).thenReturn(new ArrayList<>());
+ mController.mBroadcastAssistantCallback.onReceiveStateChanged(
+ mDevice, /* sourceId= */ 1, mState);
+ shadowOf(Looper.getMainLooper()).idle();
+ verify(mBluetoothDeviceUpdater, never()).forceUpdate();
+ verify(mDialogHandler, never()).closeOpeningDialogsForLeaDevice(mCachedDevice);
+
+ // onReceiveStateChanged with connected state will update group preference and handle
+ // stale dialogs
+ List<Long> bisSyncState = new ArrayList<>();
+ bisSyncState.add(1L);
+ when(mState.getBisSyncState()).thenReturn(bisSyncState);
+ mController.mBroadcastAssistantCallback.onReceiveStateChanged(
+ mDevice, /* sourceId= */ 1, mState);
+ shadowOf(Looper.getMainLooper()).idle();
+ verify(mBluetoothDeviceUpdater).forceUpdate();
+ verify(mDialogHandler).closeOpeningDialogsForLeaDevice(mCachedDevice);
+
+ // onSourceRemoved will update group preference
+ mController.mBroadcastAssistantCallback.onSourceRemoved(
+ mDevice, /* sourceId= */ 1, /* reason= */ 1);
+ shadowOf(Looper.getMainLooper()).idle();
+ verify(mBluetoothDeviceUpdater, times(2)).forceUpdate();
+ }
+
+ @Test
+ public void testBluetoothLeBroadcastAssistantCallbacks_doNothing() {
+ mController.mBroadcastAssistantCallback.onSearchStarted(/* reason= */ 1);
+ mController.mBroadcastAssistantCallback.onSearchStartFailed(/* reason= */ 1);
+ mController.mBroadcastAssistantCallback.onSearchStopped(/* reason= */ 1);
+ mController.mBroadcastAssistantCallback.onSearchStopFailed(/* reason= */ 1);
+ mController.mBroadcastAssistantCallback.onSourceAdded(
+ mDevice, /* sourceId= */ 1, /* reason= */ 1);
+ mController.mBroadcastAssistantCallback.onSourceAddFailed(
+ mDevice, mSource, /* reason= */ 1);
+ mController.mBroadcastAssistantCallback.onSourceRemoveFailed(
+ mDevice, /* sourceId= */ 1, /* reason= */ 1);
+ mController.mBroadcastAssistantCallback.onSourceModified(
+ mDevice, /* sourceId= */ 1, /* reason= */ 1);
+ mController.mBroadcastAssistantCallback.onSourceModifyFailed(
+ mDevice, /* sourceId= */ 1, /* reason= */ 1);
+ mController.mBroadcastAssistantCallback.onSourceFound(mSource);
+ mController.mBroadcastAssistantCallback.onSourceLost(/* broadcastId= */ 1);
+ shadowOf(Looper.getMainLooper()).idle();
+
+ // Above callbacks won't update group preference
+ verify(mBluetoothDeviceUpdater, never()).forceUpdate();
+ }
}
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumeControlUpdaterTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumeControlUpdaterTest.java
index 7a21f02..e7cfb85 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumeControlUpdaterTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumeControlUpdaterTest.java
@@ -22,6 +22,7 @@
import static org.mockito.Mockito.doNothing;
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.verifyNoInteractions;
@@ -41,6 +42,7 @@
import androidx.preference.Preference;
import androidx.test.core.app.ApplicationProvider;
+import com.android.settings.bluetooth.BluetoothDevicePreference;
import com.android.settings.bluetooth.Utils;
import com.android.settings.connecteddevice.DevicePreferenceCallback;
import com.android.settings.testutils.FakeFeatureFactory;
@@ -56,6 +58,7 @@
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
+import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -80,6 +83,9 @@
private static final String TEST_SETTINGS_KEY =
"bluetooth_le_broadcast_fallback_active_group_id";
private static final int TEST_DEVICE_GROUP_ID = 1;
+ private static final int TEST_VOLUME_VALUE = 255;
+ private static final int TEST_MAX_STREAM_VALUE = 10;
+ private static final int TEST_MIN_STREAM_VALUE = 0;
@Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
@@ -131,6 +137,11 @@
mDeviceUpdater.setPrefContext(mContext);
}
+ @After
+ public void tearDown() {
+ ShadowBluetoothUtils.reset();
+ }
+
@Test
public void onProfileConnectionStateChanged_leaDeviceConnected_noSharing_removesPref() {
setupPreferenceMapWithDevice();
@@ -249,10 +260,11 @@
(AudioSharingDeviceVolumePreference) captor.getValue();
SeekBar seekBar = mock(SeekBar.class);
- when(seekBar.getProgress()).thenReturn(255);
+ when(seekBar.getProgress()).thenReturn(TEST_VOLUME_VALUE);
preference.onStopTrackingTouch(seekBar);
- verify(mVolumeControl).setDeviceVolume(mBluetoothDevice, 255, true);
+ verify(mVolumeControl)
+ .setDeviceVolume(mBluetoothDevice, TEST_VOLUME_VALUE, /* isGroupOp= */ true);
verifyNoInteractions(mAudioManager);
verify(mFeatureFactory.metricsFeatureProvider)
.action(
@@ -273,14 +285,17 @@
Settings.Secure.putInt(
mContext.getContentResolver(), TEST_SETTINGS_KEY, TEST_DEVICE_GROUP_ID);
- when(mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC)).thenReturn(10);
- when(mAudioManager.getStreamMinVolume(AudioManager.STREAM_MUSIC)).thenReturn(0);
+ when(mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC))
+ .thenReturn(TEST_MAX_STREAM_VALUE);
+ when(mAudioManager.getStreamMinVolume(AudioManager.STREAM_MUSIC))
+ .thenReturn(TEST_MIN_STREAM_VALUE);
SeekBar seekBar = mock(SeekBar.class);
- when(seekBar.getProgress()).thenReturn(255);
+ when(seekBar.getProgress()).thenReturn(TEST_VOLUME_VALUE);
preference.onStopTrackingTouch(seekBar);
verifyNoInteractions(mVolumeControl);
- verify(mAudioManager).setStreamVolume(AudioManager.STREAM_MUSIC, 10, 0);
+ verify(mAudioManager)
+ .setStreamVolume(AudioManager.STREAM_MUSIC, TEST_MAX_STREAM_VALUE, /* flags= */ 0);
verify(mFeatureFactory.metricsFeatureProvider)
.action(
mContext,
@@ -289,6 +304,22 @@
}
@Test
+ public void testOnSeekBarChangeListener_doNothing() {
+ ArgumentCaptor<Preference> captor = ArgumentCaptor.forClass(Preference.class);
+ setupPreferenceMapWithDevice();
+
+ verify(mDevicePreferenceCallback).onDeviceAdded(captor.capture());
+ assertThat(captor.getValue() instanceof AudioSharingDeviceVolumePreference).isTrue();
+ AudioSharingDeviceVolumePreference preference =
+ (AudioSharingDeviceVolumePreference) captor.getValue();
+ SeekBar seekBar = mock(SeekBar.class);
+ preference.onProgressChanged(seekBar, TEST_VOLUME_VALUE, /* fromUser= */ false);
+
+ verifyNoInteractions(mAudioManager);
+ verifyNoInteractions(mVolumeControl);
+ }
+
+ @Test
public void getLogTag_returnsCorrectTag() {
assertThat(mDeviceUpdater.getLogTag()).isEqualTo(TAG);
}
@@ -298,6 +329,35 @@
assertThat(mDeviceUpdater.getPreferenceKey()).isEqualTo(PREF_KEY);
}
+ @Test
+ public void addPreferenceWithSortType_doNothing() {
+ mDeviceUpdater.addPreference(
+ mCachedBluetoothDevice, BluetoothDevicePreference.SortType.TYPE_DEFAULT);
+ // Verify AudioSharingDeviceVolumeControlUpdater overrides BluetoothDeviceUpdater and won't
+ // trigger add preference.
+ verifyNoInteractions(mDevicePreferenceCallback);
+ }
+
+ @Test
+ public void launchDeviceDetails_doNothing() {
+ Preference preference = mock(Preference.class);
+ mDeviceUpdater.launchDeviceDetails(preference);
+ // Verify AudioSharingDeviceVolumeControlUpdater overrides BluetoothDeviceUpdater and won't
+ // launch device details
+ verifyNoInteractions(preference);
+ }
+
+ @Test
+ public void refreshPreference_doNothing() {
+ setupPreferenceMapWithDevice();
+ verify(mDevicePreferenceCallback).onDeviceAdded(any(Preference.class));
+ when(mCachedDeviceManager.getCachedDevicesCopy()).thenReturn(ImmutableList.of());
+ mDeviceUpdater.refreshPreference();
+ // Verify AudioSharingDeviceVolumeControlUpdater overrides BluetoothDeviceUpdater and won't
+ // refresh preference map
+ verify(mDevicePreferenceCallback, never()).onDeviceRemoved(any(Preference.class));
+ }
+
private void setupPreferenceMapWithDevice() {
// Add device to preferenceMap
when(mBroadcast.isEnabled(null)).thenReturn(true);
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumeGroupControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumeGroupControllerTest.java
index 7c8709c..f2f0a2f 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumeGroupControllerTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumeGroupControllerTest.java
@@ -25,6 +25,7 @@
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -34,6 +35,8 @@
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothLeBroadcastAssistant;
+import android.bluetooth.BluetoothLeBroadcastMetadata;
+import android.bluetooth.BluetoothLeBroadcastReceiveState;
import android.bluetooth.BluetoothStatusCodes;
import android.bluetooth.BluetoothVolumeControl;
import android.content.ContentResolver;
@@ -69,6 +72,7 @@
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
+import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -81,6 +85,8 @@
import org.robolectric.annotation.Config;
import org.robolectric.shadow.api.Shadow;
+import java.util.ArrayList;
+import java.util.List;
import java.util.concurrent.Executor;
@RunWith(RobolectricTestRunner.class)
@@ -114,6 +120,8 @@
@Mock private LocalBluetoothProfileManager mProfileManager;
@Mock private LocalBluetoothLeBroadcast mBroadcast;
@Mock private LocalBluetoothLeBroadcastAssistant mAssistant;
+ @Mock private BluetoothLeBroadcastReceiveState mState;
+ @Mock private BluetoothLeBroadcastMetadata mSource;
@Mock private AudioSharingDeviceVolumeControlUpdater mDeviceUpdater;
@Mock private VolumeControlProfile mVolumeControl;
@Mock private PreferenceScreen mScreen;
@@ -164,6 +172,7 @@
doReturn(TEST_DEVICE_GROUP_ID1).when(mCachedDevice1).getGroupId();
doReturn(mDevice1).when(mCachedDevice1).getDevice();
doReturn(ImmutableSet.of()).when(mCachedDevice1).getMemberDevice();
+ when(mCachedDeviceManager.findDevice(mDevice1)).thenReturn(mCachedDevice1);
when(mPreference1.getCachedDevice()).thenReturn(mCachedDevice1);
doReturn(TEST_DEVICE_NAME2).when(mCachedDevice2).getName();
doReturn(TEST_DEVICE_GROUP_ID2).when(mCachedDevice2).getGroupId();
@@ -181,17 +190,23 @@
mContentObserver = mController.getSettingsObserver();
}
+ @After
+ public void tearDown() {
+ ShadowThreadUtils.reset();
+ ShadowBluetoothUtils.reset();
+ }
+
@Test
public void onStart_flagOff_doNothing() {
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
mController.onStart(mLifecycleOwner);
- verify(mAssistant, times(0))
+ verify(mAssistant, never())
.registerServiceCallBack(
any(Executor.class), any(BluetoothLeBroadcastAssistant.Callback.class));
- verify(mDeviceUpdater, times(0)).registerCallback();
- verify(mVolumeControl, times(0))
+ verify(mDeviceUpdater, never()).registerCallback();
+ verify(mVolumeControl, never())
.registerCallback(any(Executor.class), any(BluetoothVolumeControl.Callback.class));
- verify(mContentResolver, times(0))
+ verify(mContentResolver, never())
.registerContentObserver(
Settings.Secure.getUriFor(SETTINGS_KEY_FALLBACK_DEVICE_GROUP_ID),
false,
@@ -216,15 +231,32 @@
}
@Test
+ public void onAudioSharingProfilesConnected_flagOn_registerCallbacks() {
+ mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
+ mController.onAudioSharingProfilesConnected();
+ verify(mAssistant)
+ .registerServiceCallBack(
+ any(Executor.class), any(BluetoothLeBroadcastAssistant.Callback.class));
+ verify(mDeviceUpdater).registerCallback();
+ verify(mVolumeControl)
+ .registerCallback(any(Executor.class), any(BluetoothVolumeControl.Callback.class));
+ verify(mContentResolver)
+ .registerContentObserver(
+ Settings.Secure.getUriFor(SETTINGS_KEY_FALLBACK_DEVICE_GROUP_ID),
+ false,
+ mContentObserver);
+ }
+
+ @Test
public void onStop_flagOff_doNothing() {
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
mController.onStop(mLifecycleOwner);
- verify(mAssistant, times(0))
+ verify(mAssistant, never())
.unregisterServiceCallBack(any(BluetoothLeBroadcastAssistant.Callback.class));
- verify(mDeviceUpdater, times(0)).unregisterCallback();
- verify(mVolumeControl, times(0))
+ verify(mDeviceUpdater, never()).unregisterCallback();
+ verify(mVolumeControl, never())
.unregisterCallback(any(BluetoothVolumeControl.Callback.class));
- verify(mContentResolver, times(0)).unregisterContentObserver(mContentObserver);
+ verify(mContentResolver, never()).unregisterContentObserver(mContentObserver);
}
@Test
@@ -232,12 +264,12 @@
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
mController.setCallbacksRegistered(false);
mController.onStop(mLifecycleOwner);
- verify(mAssistant, times(0))
+ verify(mAssistant, never())
.unregisterServiceCallBack(any(BluetoothLeBroadcastAssistant.Callback.class));
- verify(mDeviceUpdater, times(0)).unregisterCallback();
- verify(mVolumeControl, times(0))
+ verify(mDeviceUpdater, never()).unregisterCallback();
+ verify(mVolumeControl, never())
.unregisterCallback(any(BluetoothVolumeControl.Callback.class));
- verify(mContentResolver, times(0)).unregisterContentObserver(mContentObserver);
+ verify(mContentResolver, never()).unregisterContentObserver(mContentObserver);
}
@Test
@@ -257,7 +289,7 @@
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
mController.displayPreference(mScreen);
assertThat(mPreferenceGroup.isVisible()).isFalse();
- verify(mDeviceUpdater, times(0)).forceUpdate();
+ verify(mDeviceUpdater, never()).forceUpdate();
}
@Test
@@ -324,7 +356,7 @@
mPreferenceGroup.addPreference(mPreference1);
mController.setPreferenceGroup(mPreferenceGroup);
mController.onDeviceRemoved(mPreference1);
- verify(mPreferenceGroup, times(0)).setVisible(false);
+ verify(mPreferenceGroup, never()).setVisible(false);
assertThat(mPreferenceGroup.isVisible()).isTrue();
}
@@ -344,7 +376,7 @@
mController.updateVisibility();
shadowOf(Looper.getMainLooper()).idle();
- verify(mPreferenceGroup, times(0)).setVisible(anyBoolean());
+ verify(mPreferenceGroup, never()).setVisible(anyBoolean());
}
@Test
@@ -411,4 +443,64 @@
verify(mPreference1).setOrder(0);
verify(mPreference2).setOrder(1);
}
+
+ @Test
+ public void onDeviceVolumeChanged_updatePreference() {
+ when(mPreference1.getProgress()).thenReturn(TEST_MAX_VOLUME_VALUE);
+ mController.setPreferenceGroup(mPreferenceGroup);
+ mController.onDeviceAdded(mPreference1);
+ shadowOf(Looper.getMainLooper()).idle();
+ assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(1);
+
+ mController.mVolumeControlCallback.onDeviceVolumeChanged(mDevice1, TEST_VOLUME_VALUE);
+ shadowOf(Looper.getMainLooper()).idle();
+
+ verify(mPreference1).setProgress(TEST_VOLUME_VALUE);
+ }
+
+ @Test
+ public void testBluetoothLeBroadcastAssistantCallbacks_updateGroup() {
+ when(mState.getBisSyncState()).thenReturn(new ArrayList<>());
+ // onReceiveStateChanged with unconnected state will do nothing
+ mController.mBroadcastAssistantCallback.onReceiveStateChanged(
+ mDevice1, /* sourceId= */ 1, mState);
+ verify(mDeviceUpdater, never()).forceUpdate();
+
+ // onReceiveStateChanged with connected state will update group preference
+ List<Long> bisSyncState = new ArrayList<>();
+ bisSyncState.add(1L);
+ when(mState.getBisSyncState()).thenReturn(bisSyncState);
+ mController.mBroadcastAssistantCallback.onReceiveStateChanged(
+ mDevice1, /* sourceId= */ 1, mState);
+ verify(mDeviceUpdater).forceUpdate();
+
+ // onSourceRemoved will update group preference
+ mController.mBroadcastAssistantCallback.onSourceRemoved(
+ mDevice1, /* sourceId= */ 1, /* reason= */ 1);
+ verify(mDeviceUpdater, times(2)).forceUpdate();
+ }
+
+ @Test
+ public void testBluetoothLeBroadcastAssistantCallbacks_doNothing() {
+ mController.mBroadcastAssistantCallback.onSearchStarted(/* reason= */ 1);
+ mController.mBroadcastAssistantCallback.onSearchStartFailed(/* reason= */ 1);
+ mController.mBroadcastAssistantCallback.onSearchStopped(/* reason= */ 1);
+ mController.mBroadcastAssistantCallback.onSearchStopFailed(/* reason= */ 1);
+ mController.mBroadcastAssistantCallback.onSourceAdded(
+ mDevice1, /* sourceId= */ 1, /* reason= */ 1);
+ mController.mBroadcastAssistantCallback.onSourceAddFailed(
+ mDevice1, mSource, /* reason= */ 1);
+ mController.mBroadcastAssistantCallback.onSourceRemoveFailed(
+ mDevice1, /* sourceId= */ 1, /* reason= */ 1);
+ mController.mBroadcastAssistantCallback.onSourceModified(
+ mDevice1, /* sourceId= */ 1, /* reason= */ 1);
+ mController.mBroadcastAssistantCallback.onSourceModifyFailed(
+ mDevice1, /* sourceId= */ 1, /* reason= */ 1);
+ mController.mBroadcastAssistantCallback.onSourceFound(mSource);
+ mController.mBroadcastAssistantCallback.onSourceLost(/* broadcastId= */ 1);
+ shadowOf(Looper.getMainLooper()).idle();
+
+ // Above callbacks won't update group preference
+ verify(mDeviceUpdater, never()).forceUpdate();
+ }
}
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogFragmentTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogFragmentTest.java
index c63a1a9..39709c1 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogFragmentTest.java
@@ -45,6 +45,7 @@
import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
import com.android.settingslib.flags.Flags;
+import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -112,6 +113,11 @@
mParent, FragmentActivity.class, /* containerViewId= */ 0, /* bundle= */ null);
}
+ @After
+ public void tearDown() {
+ ShadowAlertDialogCompat.reset();
+ }
+
@Test
public void getMetricsCategory_correctValue() {
assertThat(mFragment.getMetricsCategory())
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogHandlerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogHandlerTest.java
index 633bc06..4c060d4 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogHandlerTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogHandlerTest.java
@@ -19,7 +19,11 @@
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.times;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+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.verify;
import static org.mockito.Mockito.when;
import static org.robolectric.Shadows.shadowOf;
@@ -27,6 +31,8 @@
import android.app.settings.SettingsEnums;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothLeBroadcast;
+import android.bluetooth.BluetoothLeBroadcastMetadata;
import android.bluetooth.BluetoothLeBroadcastReceiveState;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothStatusCodes;
@@ -38,7 +44,6 @@
import androidx.fragment.app.DialogFragment;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
-import androidx.test.core.app.ApplicationProvider;
import com.android.settings.bluetooth.Utils;
import com.android.settings.testutils.FakeFeatureFactory;
@@ -57,6 +62,7 @@
import com.google.common.collect.Iterables;
import com.google.common.truth.Correspondence;
+import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -71,6 +77,7 @@
import java.util.ArrayList;
import java.util.List;
+import java.util.concurrent.Executor;
@RunWith(RobolectricTestRunner.class)
@Config(
@@ -82,6 +89,7 @@
@Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
@Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+ private static final int TEST_SOURCE_ID = 1;
private static final String TEST_DEVICE_NAME1 = "test1";
private static final String TEST_DEVICE_NAME2 = "test2";
private static final String TEST_DEVICE_NAME3 = "test3";
@@ -109,15 +117,22 @@
@Mock private BluetoothDevice mDevice3;
@Mock private BluetoothDevice mDevice4;
@Mock private LeAudioProfile mLeAudioProfile;
- private Fragment mParentFragment;
@Mock private BluetoothLeBroadcastReceiveState mState;
+ @Mock private BluetoothLeBroadcastMetadata mMetadata;
+ private Fragment mParentFragment;
private Context mContext;
private AudioSharingDialogHandler mHandler;
private FakeFeatureFactory mFeatureFactory;
@Before
public void setup() {
- mContext = ApplicationProvider.getApplicationContext();
+ mParentFragment = new Fragment();
+ FragmentController.setupFragment(
+ mParentFragment,
+ FragmentActivity.class,
+ 0 /* containerViewId */,
+ null /* bundle */);
+ mContext = mParentFragment.getContext();
ShadowBluetoothUtils.sLocalBluetoothManager = mLocalBtManager;
mLocalBtManager = Utils.getLocalBtManager(mContext);
ShadowBluetoothAdapter shadowBluetoothAdapter =
@@ -135,6 +150,7 @@
List<Long> bisSyncState = new ArrayList<>();
bisSyncState.add(1L);
when(mState.getBisSyncState()).thenReturn(bisSyncState);
+ when(mState.getSourceId()).thenReturn(TEST_SOURCE_ID);
when(mLeAudioProfile.isEnabled(any())).thenReturn(true);
when(mCachedDevice1.getName()).thenReturn(TEST_DEVICE_NAME1);
when(mCachedDevice1.getDevice()).thenReturn(mDevice1);
@@ -158,15 +174,14 @@
when(mCacheManager.findDevice(mDevice2)).thenReturn(mCachedDevice2);
when(mCacheManager.findDevice(mDevice3)).thenReturn(mCachedDevice3);
when(mCacheManager.findDevice(mDevice4)).thenReturn(mCachedDevice4);
- mParentFragment = new Fragment();
- FragmentController.setupFragment(
- mParentFragment,
- FragmentActivity.class,
- 0 /* containerViewId */,
- null /* bundle */);
mHandler = new AudioSharingDialogHandler(mContext, mParentFragment);
}
+ @After
+ public void tearDown() {
+ ShadowBluetoothUtils.reset();
+ }
+
@Test
public void handleUserTriggeredNonLeaDeviceConnected_noSharing_setActive() {
setUpBroadcast(false);
@@ -269,6 +284,10 @@
AudioSharingUtils.MetricKey.METRIC_KEY_CANDIDATE_DEVICE_COUNT
.ordinal(),
2));
+ AudioSharingJoinDialogFragment.DialogEventListener listener = fragment.getListener();
+ assertThat(listener).isNotNull();
+ listener.onShareClick();
+ verify(mBroadcast).startPrivateBroadcast();
}
@Test
@@ -309,6 +328,10 @@
AudioSharingUtils.MetricKey.METRIC_KEY_CANDIDATE_DEVICE_COUNT
.ordinal(),
1));
+ AudioSharingJoinDialogFragment.DialogEventListener listener = fragment.getListener();
+ assertThat(listener).isNotNull();
+ listener.onShareClick();
+ verify(mAssistant).addSource(mDevice1, mMetadata, /* isGroupOp= */ false);
}
@Test
@@ -351,6 +374,11 @@
AudioSharingUtils.MetricKey.METRIC_KEY_CANDIDATE_DEVICE_COUNT
.ordinal(),
1));
+ AudioSharingDisconnectDialogFragment.DialogEventListener listener = fragment.getListener();
+ assertThat(listener).isNotNull();
+ listener.onItemClick(AudioSharingUtils.buildAudioSharingDeviceItem(mCachedDevice3));
+ verify(mAssistant).removeSource(mDevice3, TEST_SOURCE_ID);
+ verify(mAssistant).addSource(mDevice1, mMetadata, /* isGroupOp= */ false);
}
@Test
@@ -363,7 +391,7 @@
when(mAssistant.getAllSources(any())).thenReturn(ImmutableList.of());
mHandler.handleDeviceConnected(mCachedDevice2, /* userTriggered= */ false);
shadowOf(Looper.getMainLooper()).idle();
- verify(mCachedDevice2, times(0)).setActive();
+ verify(mCachedDevice2, never()).setActive();
}
@Test
@@ -415,7 +443,7 @@
when(mAssistant.getAllSources(any())).thenReturn(ImmutableList.of());
mHandler.handleDeviceConnected(mCachedDevice1, /* userTriggered= */ false);
shadowOf(Looper.getMainLooper()).idle();
- verify(mCachedDevice1, times(0)).setActive();
+ verify(mCachedDevice1, never()).setActive();
}
@Test
@@ -455,6 +483,10 @@
AudioSharingUtils.MetricKey.METRIC_KEY_CANDIDATE_DEVICE_COUNT
.ordinal(),
2));
+ AudioSharingJoinDialogFragment.DialogEventListener listener = fragment.getListener();
+ assertThat(listener).isNotNull();
+ listener.onShareClick();
+ verify(mBroadcast).startPrivateBroadcast();
}
@Test
@@ -495,6 +527,10 @@
AudioSharingUtils.MetricKey.METRIC_KEY_CANDIDATE_DEVICE_COUNT
.ordinal(),
1));
+ AudioSharingJoinDialogFragment.DialogEventListener listener = fragment.getListener();
+ assertThat(listener).isNotNull();
+ listener.onShareClick();
+ verify(mAssistant).addSource(mDevice1, mMetadata, /* isGroupOp= */ false);
}
@Test
@@ -536,6 +572,11 @@
AudioSharingUtils.MetricKey.METRIC_KEY_CANDIDATE_DEVICE_COUNT
.ordinal(),
1));
+ AudioSharingDisconnectDialogFragment.DialogEventListener listener = fragment.getListener();
+ assertThat(listener).isNotNull();
+ listener.onItemClick(AudioSharingUtils.buildAudioSharingDeviceItem(mCachedDevice3));
+ verify(mAssistant).removeSource(mDevice3, TEST_SOURCE_ID);
+ verify(mAssistant).addSource(mDevice1, mMetadata, /* isGroupOp= */ false);
}
@Test
@@ -588,7 +629,106 @@
SettingsEnums.DIALOG_STOP_AUDIO_SHARING);
}
+ @Test
+ public void closeOpeningDialogsOtherThan() {
+ setUpBroadcast(true);
+ ImmutableList<BluetoothDevice> deviceList = ImmutableList.of(mDevice3);
+ when(mAssistant.getDevicesMatchingConnectionStates(
+ new int[] {BluetoothProfile.STATE_CONNECTED}))
+ .thenReturn(deviceList);
+ when(mAssistant.getAllSources(mDevice3)).thenReturn(ImmutableList.of(mState));
+ mHandler.handleDeviceConnected(mCachedDevice2, /* userTriggered= */ true);
+ shadowOf(Looper.getMainLooper()).idle();
+ List<Fragment> childFragments = mParentFragment.getChildFragmentManager().getFragments();
+ assertThat(childFragments)
+ .comparingElementsUsing(TAG_EQUALS)
+ .containsExactly(AudioSharingStopDialogFragment.tag());
+
+ deviceList = ImmutableList.of(mDevice1, mDevice3);
+ when(mAssistant.getDevicesMatchingConnectionStates(
+ new int[] {BluetoothProfile.STATE_CONNECTED}))
+ .thenReturn(deviceList);
+ when(mAssistant.getAllSources(mDevice1)).thenReturn(ImmutableList.of());
+ mHandler.handleDeviceConnected(mCachedDevice1, /* userTriggered= */ false);
+ shadowOf(Looper.getMainLooper()).idle();
+ childFragments = mParentFragment.getChildFragmentManager().getFragments();
+ assertThat(childFragments)
+ .comparingElementsUsing(TAG_EQUALS)
+ .containsExactly(AudioSharingJoinDialogFragment.tag());
+
+ verify(mFeatureFactory.metricsFeatureProvider)
+ .action(
+ mContext,
+ SettingsEnums.ACTION_AUDIO_SHARING_DIALOG_AUTO_DISMISS,
+ SettingsEnums.DIALOG_STOP_AUDIO_SHARING);
+ }
+
+ @Test
+ public void registerCallbacks() {
+ Executor executor = mock(Executor.class);
+ mHandler.registerCallbacks(executor);
+ verify(mBroadcast)
+ .registerServiceCallBack(eq(executor), any(BluetoothLeBroadcast.Callback.class));
+ }
+
+ @Test
+ public void unregisterCallbacks() {
+ mHandler.unregisterCallbacks();
+ verify(mBroadcast).unregisterServiceCallBack(any(BluetoothLeBroadcast.Callback.class));
+ }
+
+ @Test
+ public void onPlaybackStarted_addSource() {
+ setUpBroadcast(false);
+ ImmutableList<BluetoothDevice> deviceList = ImmutableList.of(mDevice1, mDevice3);
+ when(mAssistant.getDevicesMatchingConnectionStates(
+ new int[] {BluetoothProfile.STATE_CONNECTED}))
+ .thenReturn(deviceList);
+ when(mAssistant.getAllSources(any())).thenReturn(ImmutableList.of());
+ mHandler.handleDeviceConnected(mCachedDevice1, /* userTriggered= */ true);
+ shadowOf(Looper.getMainLooper()).idle();
+ List<Fragment> childFragments = mParentFragment.getChildFragmentManager().getFragments();
+ assertThat(childFragments)
+ .comparingElementsUsing(TAG_EQUALS)
+ .containsExactly(AudioSharingJoinDialogFragment.tag());
+ AudioSharingJoinDialogFragment fragment =
+ (AudioSharingJoinDialogFragment) Iterables.getOnlyElement(childFragments);
+ AudioSharingJoinDialogFragment.DialogEventListener listener = fragment.getListener();
+ assertThat(listener).isNotNull();
+ listener.onShareClick();
+
+ setUpBroadcast(true);
+ mHandler.mBroadcastCallback.onPlaybackStarted(/* reason= */ 1, /* broadcastId= */ 1);
+ shadowOf(Looper.getMainLooper()).idle();
+
+ verify(mAssistant).addSource(mDevice1, mMetadata, /* isGroupOp= */ false);
+ verify(mAssistant).addSource(mDevice3, mMetadata, /* isGroupOp= */ false);
+ }
+
+ @Test
+ public void testBluetoothLeBroadcastCallbacks_doNothing() {
+ mHandler.mBroadcastCallback.onBroadcastStarted(/* reason= */ 1, /* broadcastId= */ 1);
+ mHandler.mBroadcastCallback.onBroadcastStopped(/* reason= */ 1, /* broadcastId= */ 1);
+ mHandler.mBroadcastCallback.onBroadcastMetadataChanged(/* reason= */ 1, mMetadata);
+ mHandler.mBroadcastCallback.onBroadcastUpdated(/* reason= */ 1, /* broadcastId= */ 1);
+ mHandler.mBroadcastCallback.onPlaybackStarted(/* reason= */ 1, /* broadcastId= */ 1);
+ mHandler.mBroadcastCallback.onPlaybackStopped(/* reason= */ 1, /* broadcastId= */ 1);
+ mHandler.mBroadcastCallback.onBroadcastStartFailed(/* reason= */ 1);
+ mHandler.mBroadcastCallback.onBroadcastStopFailed(/* reason= */ 1);
+ mHandler.mBroadcastCallback.onBroadcastUpdateFailed(/* reason= */ 1, /* broadcastId= */ 1);
+
+ verify(mAssistant, never())
+ .addSource(
+ any(BluetoothDevice.class),
+ any(BluetoothLeBroadcastMetadata.class),
+ anyBoolean());
+ verify(mAssistant, never()).removeSource(any(BluetoothDevice.class), anyInt());
+ }
+
private void setUpBroadcast(boolean isBroadcasting) {
when(mBroadcast.isEnabled(any())).thenReturn(isBroadcasting);
+ if (isBroadcasting) {
+ when(mBroadcast.getLatestBluetoothLeBroadcastMetadata()).thenReturn(mMetadata);
+ }
}
}
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDisconnectDialogFragmentTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDisconnectDialogFragmentTest.java
index 481c78d..6b984af 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDisconnectDialogFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDisconnectDialogFragmentTest.java
@@ -47,6 +47,7 @@
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.flags.Flags;
+import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -104,11 +105,7 @@
@Before
public void setUp() {
- AlertDialog latestAlertDialog = ShadowAlertDialogCompat.getLatestAlertDialog();
- if (latestAlertDialog != null) {
- latestAlertDialog.dismiss();
- ShadowAlertDialogCompat.reset();
- }
+ ShadowAlertDialogCompat.reset();
ShadowBluetoothAdapter shadowBluetoothAdapter =
Shadow.extract(BluetoothAdapter.getDefaultAdapter());
shadowBluetoothAdapter.setEnabled(true);
@@ -131,6 +128,11 @@
mParent, FragmentActivity.class, /* containerViewId= */ 0, /* bundle= */ null);
}
+ @After
+ public void tearDown() {
+ ShadowAlertDialogCompat.reset();
+ }
+
@Test
public void getMetricsCategory_correctValue() {
assertThat(mFragment.getMetricsCategory())
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingJoinDialogFragmentTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingJoinDialogFragmentTest.java
index c7b21ad..13ea965 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingJoinDialogFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingJoinDialogFragmentTest.java
@@ -48,6 +48,7 @@
import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
import com.android.settingslib.flags.Flags;
+import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -104,11 +105,7 @@
@Before
public void setUp() {
- AlertDialog latestAlertDialog = ShadowAlertDialogCompat.getLatestAlertDialog();
- if (latestAlertDialog != null) {
- latestAlertDialog.dismiss();
- ShadowAlertDialogCompat.reset();
- }
+ ShadowAlertDialogCompat.reset();
ShadowBluetoothAdapter shadowBluetoothAdapter =
Shadow.extract(BluetoothAdapter.getDefaultAdapter());
shadowBluetoothAdapter.setEnabled(true);
@@ -129,6 +126,12 @@
mParent, FragmentActivity.class, /* containerViewId= */ 0, /* bundle= */ null);
}
+ @After
+ public void tearDown() {
+ ShadowAlertDialogCompat.reset();
+ ShadowBluetoothUtils.reset();
+ }
+
@Test
public void getMetricsCategory_notInSharing_correctValue() {
when(mBroadcast.isEnabled(null)).thenReturn(false);
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingPreferenceControllerTest.java
index 046a4ce..d9c883e 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingPreferenceControllerTest.java
@@ -56,6 +56,7 @@
import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.flags.Flags;
+import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -114,6 +115,12 @@
when(mScreen.findPreference(PREF_KEY)).thenReturn(mPreference);
}
+ @After
+ public void tearDown() {
+ ShadowBluetoothUtils.reset();
+ ShadowThreadUtils.reset();
+ }
+
@Test
public void onStart_flagOn_registerCallback() {
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingReceiverTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingReceiverTest.java
index d542b98..deed229 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingReceiverTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingReceiverTest.java
@@ -50,6 +50,7 @@
import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
import com.android.settingslib.flags.Flags;
+import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -103,6 +104,11 @@
mFeatureFactory = FakeFeatureFactory.setupForTest();
}
+ @After
+ public void tearDown() {
+ ShadowBluetoothUtils.reset();
+ }
+
@Test
public void broadcastReceiver_isRegistered() {
List<ShadowApplication.Wrapper> registeredReceivers =
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingStopDialogFragmentTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingStopDialogFragmentTest.java
index 7d46a18..b6babfb 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingStopDialogFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingStopDialogFragmentTest.java
@@ -48,6 +48,7 @@
import com.google.common.collect.ImmutableList;
+import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -101,11 +102,7 @@
@Before
public void setUp() {
- AlertDialog latestAlertDialog = ShadowAlertDialogCompat.getLatestAlertDialog();
- if (latestAlertDialog != null) {
- latestAlertDialog.dismiss();
- ShadowAlertDialogCompat.reset();
- }
+ ShadowAlertDialogCompat.reset();
ShadowBluetoothAdapter shadowBluetoothAdapter =
Shadow.extract(BluetoothAdapter.getDefaultAdapter());
shadowBluetoothAdapter.setEnabled(true);
@@ -126,6 +123,11 @@
mParent, FragmentActivity.class, /* containerViewId= */ 0, /* bundle= */ null);
}
+ @After
+ public void tearDown() {
+ ShadowAlertDialogCompat.reset();
+ }
+
@Test
public void getMetricsCategory_correctValue() {
assertThat(mFragment.getMetricsCategory())
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarControllerTest.java
index 8f85feb8..45d99c7 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarControllerTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarControllerTest.java
@@ -22,11 +22,13 @@
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.eq;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
+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;
@@ -36,6 +38,7 @@
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothLeBroadcast;
import android.bluetooth.BluetoothLeBroadcastAssistant;
+import android.bluetooth.BluetoothLeBroadcastMetadata;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothStatusCodes;
import android.content.BroadcastReceiver;
@@ -75,6 +78,7 @@
import com.google.common.collect.Iterables;
import com.google.common.truth.Correspondence;
+import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -181,7 +185,7 @@
doNothing()
.when(mAssistant)
.unregisterServiceCallBack(any(BluetoothLeBroadcastAssistant.Callback.class));
- mSwitchBar = new SettingsMainSwitchBar(mContext);
+ mSwitchBar = spy(new SettingsMainSwitchBar(mContext));
mSwitchBar.setDisabledByAdmin(mock(RestrictedLockUtils.EnforcedAdmin.class));
mOnAudioSharingStateChanged = false;
mOnAudioSharingServiceConnected = false;
@@ -207,6 +211,12 @@
mController.init(mParentFragment);
}
+ @After
+ public void tearDown() {
+ ShadowBluetoothUtils.reset();
+ ShadowThreadUtils.reset();
+ }
+
@Test
public void bluetoothOff_switchDisabled() {
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
@@ -258,15 +268,15 @@
public void onStart_flagOff_doNothing() {
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
mController.onStart(mLifecycleOwner);
- verify(mContext, times(0))
+ verify(mContext, never())
.registerReceiver(any(BroadcastReceiver.class), any(IntentFilter.class), anyInt());
- verify(mBroadcast, times(0))
+ verify(mBroadcast, never())
.registerServiceCallBack(
any(Executor.class), any(BluetoothLeBroadcast.Callback.class));
- verify(mAssistant, times(0))
+ verify(mAssistant, never())
.registerServiceCallBack(
any(Executor.class), any(BluetoothLeBroadcastAssistant.Callback.class));
- verify(mBtProfileManager, times(0)).addServiceListener(mController);
+ verify(mBtProfileManager, never()).addServiceListener(mController);
}
@Test
@@ -279,10 +289,10 @@
verify(mContext)
.registerReceiver(any(BroadcastReceiver.class), any(IntentFilter.class), anyInt());
- verify(mBroadcast, times(0))
+ verify(mBroadcast, never())
.registerServiceCallBack(
any(Executor.class), any(BluetoothLeBroadcast.Callback.class));
- verify(mAssistant, times(0))
+ verify(mAssistant, never())
.registerServiceCallBack(
any(Executor.class), any(BluetoothLeBroadcastAssistant.Callback.class));
verify(mBtProfileManager).addServiceListener(mController);
@@ -305,7 +315,7 @@
verify(mAssistant)
.registerServiceCallBack(
any(Executor.class), any(BluetoothLeBroadcastAssistant.Callback.class));
- verify(mBtProfileManager, times(0)).addServiceListener(mController);
+ verify(mBtProfileManager, never()).addServiceListener(mController);
assertThat(mSwitchBar.isChecked()).isTrue();
assertThat(mSwitchBar.isEnabled()).isTrue();
}
@@ -314,12 +324,12 @@
public void onStop_flagOff_doNothing() {
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
mController.onStop(mLifecycleOwner);
- verify(mContext, times(0)).unregisterReceiver(any(BroadcastReceiver.class));
- verify(mBroadcast, times(0))
+ verify(mContext, never()).unregisterReceiver(any(BroadcastReceiver.class));
+ verify(mBroadcast, never())
.unregisterServiceCallBack(any(BluetoothLeBroadcast.Callback.class));
- verify(mAssistant, times(0))
+ verify(mAssistant, never())
.unregisterServiceCallBack(any(BluetoothLeBroadcastAssistant.Callback.class));
- verify(mBtProfileManager, times(0)).removeServiceListener(mController);
+ verify(mBtProfileManager, never()).removeServiceListener(mController);
}
@Test
@@ -331,9 +341,9 @@
verify(mContext).unregisterReceiver(any(BroadcastReceiver.class));
verify(mBtProfileManager).removeServiceListener(mController);
- verify(mBroadcast, times(0))
+ verify(mBroadcast, never())
.unregisterServiceCallBack(any(BluetoothLeBroadcast.Callback.class));
- verify(mAssistant, times(0))
+ verify(mAssistant, never())
.unregisterServiceCallBack(any(BluetoothLeBroadcastAssistant.Callback.class));
}
@@ -358,7 +368,7 @@
when(mBtnView.isEnabled()).thenReturn(true);
when(mBroadcast.isEnabled(null)).thenReturn(true);
mController.onCheckedChanged(mBtnView, /* isChecked= */ true);
- verify(mBroadcast, times(0)).startPrivateBroadcast();
+ verify(mBroadcast, never()).startPrivateBroadcast();
}
@Test
@@ -372,7 +382,7 @@
doNothing().when(mBroadcast).startPrivateBroadcast();
mController.onCheckedChanged(mBtnView, /* isChecked= */ true);
assertThat(mSwitchBar.isChecked()).isFalse();
- verify(mBroadcast, times(0)).startPrivateBroadcast();
+ verify(mBroadcast, never()).startPrivateBroadcast();
}
@Test
@@ -407,7 +417,7 @@
when(mBroadcast.isEnabled(null)).thenReturn(false);
when(mBroadcast.getLatestBroadcastId()).thenReturn(1);
mController.onCheckedChanged(mBtnView, /* isChecked= */ false);
- verify(mBroadcast, times(0)).stopBroadcast(anyInt());
+ verify(mBroadcast, never()).stopBroadcast(anyInt());
}
@Test
@@ -465,4 +475,46 @@
.ordinal(),
1));
}
+
+ @Test
+ public void testBluetoothLeBroadcastCallbacks_updateSwitch() {
+ mOnAudioSharingStateChanged = false;
+ mSwitchBar.setChecked(false);
+ when(mBroadcast.isEnabled(any())).thenReturn(false);
+ mController.mBroadcastCallback.onBroadcastStartFailed(/* reason= */ 1);
+ shadowOf(Looper.getMainLooper()).idle();
+ assertThat(mSwitchBar.isChecked()).isFalse();
+ assertThat(mOnAudioSharingStateChanged).isFalse();
+
+ when(mBroadcast.isEnabled(any())).thenReturn(true);
+ mController.mBroadcastCallback.onBroadcastStarted(/* reason= */ 1, /* broadcastId= */ 1);
+ shadowOf(Looper.getMainLooper()).idle();
+ assertThat(mSwitchBar.isChecked()).isTrue();
+ assertThat(mOnAudioSharingStateChanged).isTrue();
+
+ mOnAudioSharingStateChanged = false;
+ mController.mBroadcastCallback.onBroadcastStopFailed(/* reason= */ 1);
+ shadowOf(Looper.getMainLooper()).idle();
+ assertThat(mSwitchBar.isChecked()).isTrue();
+ assertThat(mOnAudioSharingStateChanged).isFalse();
+
+ when(mBroadcast.isEnabled(any())).thenReturn(false);
+ mController.mBroadcastCallback.onBroadcastStopped(/* reason= */ 1, /* broadcastId= */ 1);
+ shadowOf(Looper.getMainLooper()).idle();
+ assertThat(mSwitchBar.isChecked()).isFalse();
+ assertThat(mOnAudioSharingStateChanged).isTrue();
+ }
+
+ @Test
+ public void testBluetoothLeBroadcastCallbacks_doNothing() {
+ BluetoothLeBroadcastMetadata metadata = mock(BluetoothLeBroadcastMetadata.class);
+ mController.mBroadcastCallback.onBroadcastMetadataChanged(/* reason= */ 1, metadata);
+ mController.mBroadcastCallback.onBroadcastUpdated(/* reason= */ 1, /* broadcastId= */ 1);
+ mController.mBroadcastCallback.onPlaybackStarted(/* reason= */ 1, /* broadcastId= */ 1);
+ mController.mBroadcastCallback.onPlaybackStopped(/* reason= */ 1, /* broadcastId= */ 1);
+ mController.mBroadcastCallback.onBroadcastUpdateFailed(
+ /* reason= */ 1, /* broadcastId= */ 1);
+ verify(mSwitchBar, never()).setChecked(anyBoolean());
+ assertThat(mOnAudioSharingStateChanged).isFalse();
+ }
}
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/StreamSettingsCategoryControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/StreamSettingsCategoryControllerTest.java
index 50dde0f..ee92b3b 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/StreamSettingsCategoryControllerTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/StreamSettingsCategoryControllerTest.java
@@ -54,6 +54,7 @@
import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.flags.Flags;
+import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -117,6 +118,11 @@
when(mScreen.findPreference(KEY)).thenReturn(mPreference);
}
+ @After
+ public void tearDown() {
+ ShadowBluetoothUtils.reset();
+ }
+
@Test
public void bluetoothOff_updateVisibility() {
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImplTest.java b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImplTest.java
index 354afd0..6b32ff5 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImplTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImplTest.java
@@ -78,6 +78,11 @@
}
@Test
+ public void isForceExpireAppOptimizationModeEnabled_returnFalse() {
+ assertThat(mPowerFeatureProvider.isForceExpireAppOptimizationModeEnabled()).isFalse();
+ }
+
+ @Test
public void isAppOptimizationModeLogged_returnFalse() {
assertThat(mPowerFeatureProvider.isAppOptimizationModeLogged()).isFalse();
}
diff --git a/tests/spa_unit/src/com/android/settings/network/apn/ApnEditPageProviderTest.kt b/tests/spa_unit/src/com/android/settings/network/apn/ApnEditPageProviderTest.kt
index 4dbe050..3621948 100644
--- a/tests/spa_unit/src/com/android/settings/network/apn/ApnEditPageProviderTest.kt
+++ b/tests/spa_unit/src/com/android/settings/network/apn/ApnEditPageProviderTest.kt
@@ -58,7 +58,6 @@
private val apnEnable = context.resources.getString(R.string.carrier_enabled)
private val apnProtocolOptions =
context.resources.getStringArray(R.array.apn_protocol_entries).toList()
- private val networkType = context.resources.getString(R.string.network_type)
private val passwordTitle = context.resources.getString(R.string.apn_password)
private val apnInit = ApnData(
name = apnName,
@@ -168,48 +167,6 @@
}
@Test
- fun network_type_displayed() {
- composeTestRule.setContent {
- ApnPage(apnInit, remember { apnData }, uri)
- }
- composeTestRule.onRoot().onChild().onChildAt(0)
- .performScrollToNode(hasText(networkType, true))
- composeTestRule.onNodeWithText(networkType, true).assertIsDisplayed()
- }
-
- @Test
- fun network_type_changed() {
- composeTestRule.setContent {
- ApnPage(apnInit, remember { apnData }, uri)
- }
- composeTestRule.onRoot().onChild().onChildAt(0)
- .performScrollToNode(hasText(networkType, true))
- composeTestRule.onNodeWithText(networkType, true).performClick()
- composeTestRule.onNodeWithText(NETWORK_TYPE_LTE, true).performClick()
- composeTestRule.onNode(hasText(NETWORK_TYPE_UNSPECIFIED) and isFocused(), true)
- .assertDoesNotExist()
- composeTestRule.onNode(hasText(NETWORK_TYPE_LTE) and isFocused(), true).assertIsDisplayed()
- }
-
- @Test
- fun network_type_changed_back2Default() {
- composeTestRule.setContent {
- ApnPage(apnInit, remember { apnData }, uri)
- }
- composeTestRule.onRoot().onChild().onChildAt(0)
- .performScrollToNode(hasText(networkType, true))
- composeTestRule.onNodeWithText(networkType, true).performClick()
- composeTestRule.onNodeWithText(NETWORK_TYPE_LTE, true).performClick()
- composeTestRule.onNode(hasText(NETWORK_TYPE_UNSPECIFIED) and isFocused(), true)
- .assertDoesNotExist()
- composeTestRule.onNode(hasText(NETWORK_TYPE_LTE) and isFocused(), true).assertIsDisplayed()
- composeTestRule.onAllNodesWithText(NETWORK_TYPE_LTE, true).onLast().performClick()
- composeTestRule.onNode(hasText(NETWORK_TYPE_UNSPECIFIED) and isFocused(), true)
- .assertIsDisplayed()
- composeTestRule.onNode(hasText(NETWORK_TYPE_LTE) and isFocused(), true).assertDoesNotExist()
- }
-
- @Test
fun password_displayed() {
composeTestRule.setContent {
ApnPage(apnInit, remember { apnData }, uri)
@@ -218,9 +175,4 @@
.performScrollToNode(hasText(passwordTitle, true))
composeTestRule.onNodeWithText(passwordTitle, true).assertIsDisplayed()
}
-
- private companion object {
- const val NETWORK_TYPE_UNSPECIFIED = "Unspecified"
- const val NETWORK_TYPE_LTE = "LTE"
- }
}
\ No newline at end of file
diff --git a/tests/spa_unit/src/com/android/settings/network/apn/ApnNetworkTypeCheckBoxTest.kt b/tests/spa_unit/src/com/android/settings/network/apn/ApnNetworkTypeCheckBoxTest.kt
new file mode 100644
index 0000000..5a8e40a
--- /dev/null
+++ b/tests/spa_unit/src/com/android/settings/network/apn/ApnNetworkTypeCheckBoxTest.kt
@@ -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.network.apn
+
+import android.content.Context
+import android.telephony.TelephonyManager
+import androidx.compose.ui.semantics.Role
+import androidx.compose.ui.test.assertIsDisplayed
+import androidx.compose.ui.test.hasText
+import androidx.compose.ui.test.isToggleable
+import androidx.compose.ui.test.junit4.ComposeTestRule
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.onNodeWithText
+import androidx.compose.ui.test.performClick
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.settings.R
+import com.android.settingslib.spa.testutils.hasRole
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class ApnNetworkTypeCheckBoxTest {
+ @get:Rule val composeTestRule = createComposeRule()
+
+ private val context: Context = ApplicationProvider.getApplicationContext()
+
+ private val apnData = ApnData()
+
+ @Test
+ fun networkType_displayed() {
+ composeTestRule.setContent { ApnNetworkTypeCheckBox(apnData) {} }
+
+ composeTestRule.onNodeWithText(context.getString(R.string.network_type)).assertIsDisplayed()
+ }
+
+ @Test
+ fun networkType_changed() {
+ composeTestRule.setContent { ApnNetworkTypeCheckBox(apnData) {} }
+
+ composeTestRule.onNodeWithText(context.getString(R.string.network_type)).performClick()
+ composeTestRule.onNode(hasText(LTE_TEXT) and isToggleable()).performClick()
+
+ composeTestRule
+ .onDropdownListWithText(context.getString(R.string.network_type_unspecified))
+ .assertDoesNotExist()
+ composeTestRule.onDropdownListWithText(LTE_TEXT).assertIsDisplayed()
+ }
+
+ @Test
+ fun networkType_changed_back2Default() {
+ composeTestRule.setContent { ApnNetworkTypeCheckBox(apnData) {} }
+
+ composeTestRule.onNodeWithText(context.getString(R.string.network_type)).performClick()
+ composeTestRule.onNode(hasText(LTE_TEXT) and isToggleable()).performClick()
+ composeTestRule.onNode(hasText(LTE_TEXT) and isToggleable()).performClick()
+
+ composeTestRule
+ .onDropdownListWithText(context.getString(R.string.network_type_unspecified))
+ .assertIsDisplayed()
+ composeTestRule.onDropdownListWithText(LTE_TEXT).assertDoesNotExist()
+ }
+
+ private fun ComposeTestRule.onDropdownListWithText(text: String) =
+ onNode(hasText(text) and hasRole(Role.DropdownList))
+
+ private companion object {
+ val LTE_TEXT = TelephonyManager.getNetworkTypeName(TelephonyManager.NETWORK_TYPE_LTE)
+ }
+}
diff --git a/tests/unit/src/com/android/settings/fuelgauge/batteryusage/AppOptModeSharedPreferencesUtilsTest.kt b/tests/unit/src/com/android/settings/fuelgauge/batteryusage/AppOptModeSharedPreferencesUtilsTest.kt
index 76ae491..94f082d 100644
--- a/tests/unit/src/com/android/settings/fuelgauge/batteryusage/AppOptModeSharedPreferencesUtilsTest.kt
+++ b/tests/unit/src/com/android/settings/fuelgauge/batteryusage/AppOptModeSharedPreferencesUtilsTest.kt
@@ -26,6 +26,7 @@
import com.android.settings.fuelgauge.BatteryOptimizeUtils.MODE_UNKNOWN
import com.android.settings.fuelgauge.BatteryOptimizeUtils.MODE_UNRESTRICTED
import com.android.settings.fuelgauge.batteryusage.AppOptModeSharedPreferencesUtils.UNLIMITED_EXPIRE_TIME
+import com.android.settings.testutils.FakeFeatureFactory
import com.google.common.truth.Truth.assertThat
import org.junit.After
import org.junit.Before
@@ -51,9 +52,14 @@
@Spy
private var testBatteryOptimizeUtils = spy(BatteryOptimizeUtils(context, UID, PACKAGE_NAME))
+ private lateinit var featureFactory: FakeFeatureFactory
+
@Before
fun setup() {
AppOptModeSharedPreferencesUtils.clearAll(context)
+ featureFactory = FakeFeatureFactory.setupForTest()
+ whenever(featureFactory.powerUsageFeatureProvider.isForceExpireAppOptimizationModeEnabled)
+ .thenReturn(false)
}
@After
@@ -127,6 +133,20 @@
}
@Test
+ fun resetExpiredAppOptModeBeforeTimestamp_forceExpiredData_verifyEmptyList() {
+ whenever(featureFactory.powerUsageFeatureProvider.isForceExpireAppOptimizationModeEnabled)
+ .thenReturn(true)
+ insertAppOptModeEventForTest(expirationTime = 1000L)
+
+ AppOptModeSharedPreferencesUtils.resetExpiredAppOptModeBeforeTimestamp(
+ context,
+ queryTimestampMs = 999L
+ )
+
+ assertThat(AppOptModeSharedPreferencesUtils.getAllEvents(context)).isEmpty()
+ }
+
+ @Test
fun resetExpiredAppOptModeBeforeTimestamp_noExpiredData_verifyData() {
insertAppOptModeEventForTest(expirationTime = 1000L)
diff --git a/tests/unit/src/com/android/settings/network/NetworkProviderCallsSmsFragmentTest.java b/tests/unit/src/com/android/settings/network/NetworkProviderCallsSmsFragmentTest.java
index cc9e116..fa61820 100644
--- a/tests/unit/src/com/android/settings/network/NetworkProviderCallsSmsFragmentTest.java
+++ b/tests/unit/src/com/android/settings/network/NetworkProviderCallsSmsFragmentTest.java
@@ -22,6 +22,7 @@
import android.content.Context;
import android.os.Looper;
+import android.platform.test.annotations.DisableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
import androidx.test.annotation.UiThreadTest;
@@ -54,11 +55,11 @@
if (Looper.myLooper() == null) {
Looper.prepare();
}
- mSetFlagsRule.disableFlags(Flags.FLAG_IS_DUAL_SIM_ONBOARDING_ENABLED);
}
@Test
@UiThreadTest
+ @DisableFlags(Flags.FLAG_IS_DUAL_SIM_ONBOARDING_ENABLED)
public void isPageSearchEnabled_shouldIncludeFragmentXml() {
mPreferenceKeyList =
NetworkProviderCallsSmsFragment.SEARCH_INDEX_DATA_PROVIDER