Snap for 13039724 from a7caa23deb to 25Q2-release
Change-Id: I9fc10105bf69586473a7927e11b9b05490511e91
This commit is contained in:
@@ -10399,7 +10399,7 @@
|
||||
<!-- Body text of prompt dialog app can invoke to turn off optimization [CHAR LIMIT=NONE] -->
|
||||
<string name="high_power_prompt_body">
|
||||
Allowing <xliff:g id="app_name" example="Settings">%1$s</xliff:g> to always run in the background may reduce battery life.
|
||||
\n\nYou can change this later from Settings > Apps.</string>
|
||||
\n\nYou can change this later from Settings -> Apps.</string>
|
||||
<!-- Summary of power usage for an app [CHAR LIMIT=NONE] -->
|
||||
<string name="battery_summary"><xliff:g id="percentage" example="2">%1$s</xliff:g> use since last full charge</string>
|
||||
<!-- Summary of power usage for an app within past 24 hr[CHAR LIMIT=NONE] -->
|
||||
|
||||
@@ -17,9 +17,12 @@
|
||||
package com.android.settings.accessibility
|
||||
|
||||
import android.annotation.DrawableRes
|
||||
import android.app.settings.SettingsEnums.ACTION_REMOVE_ANIMATION
|
||||
import android.content.Context
|
||||
import android.provider.Settings
|
||||
import com.android.settings.PreferenceActionMetricsProvider
|
||||
import com.android.settings.R
|
||||
import com.android.settings.contract.KEY_REMOVE_ANIMATION
|
||||
import com.android.settingslib.datastore.HandlerExecutor
|
||||
import com.android.settingslib.datastore.KeyValueStore
|
||||
import com.android.settingslib.datastore.KeyedObserver
|
||||
@@ -37,6 +40,7 @@ class RemoveAnimationsPreference :
|
||||
R.string.accessibility_disable_animations,
|
||||
R.string.accessibility_disable_animations_summary,
|
||||
),
|
||||
PreferenceActionMetricsProvider,
|
||||
PreferenceLifecycleProvider {
|
||||
|
||||
private var mSettingsKeyedObserver: KeyedObserver<String>? = null
|
||||
@@ -44,6 +48,11 @@ class RemoveAnimationsPreference :
|
||||
override val icon: Int
|
||||
@DrawableRes get() = R.drawable.ic_accessibility_animation
|
||||
|
||||
override val preferenceActionMetrics: Int
|
||||
get() = ACTION_REMOVE_ANIMATION
|
||||
|
||||
override fun tags(context: Context) = arrayOf(KEY_REMOVE_ANIMATION)
|
||||
|
||||
override fun onStart(context: PreferenceLifecycleContext) {
|
||||
val observer = KeyedObserver<String> { _, _ -> context.notifyPreferenceChange(KEY) }
|
||||
mSettingsKeyedObserver = observer
|
||||
|
||||
@@ -15,13 +15,16 @@
|
||||
*/
|
||||
package com.android.settings.accessibility
|
||||
|
||||
import android.app.settings.SettingsEnums.ACTION_VIBRATION_HAPTICS
|
||||
import android.content.Context
|
||||
import android.os.VibrationAttributes
|
||||
import android.os.Vibrator
|
||||
import android.provider.Settings
|
||||
import android.widget.CompoundButton
|
||||
import android.widget.CompoundButton.OnCheckedChangeListener
|
||||
import com.android.settings.PreferenceActionMetricsProvider
|
||||
import com.android.settings.R
|
||||
import com.android.settings.contract.KEY_VIBRATION_HAPTICS
|
||||
import com.android.settingslib.datastore.KeyValueStore
|
||||
import com.android.settingslib.datastore.KeyedObservableDelegate
|
||||
import com.android.settingslib.datastore.SettingsStore
|
||||
@@ -39,6 +42,7 @@ class VibrationMainSwitchPreference :
|
||||
key = Settings.System.VIBRATE_ON,
|
||||
title = R.string.accessibility_vibration_primary_switch_title,
|
||||
),
|
||||
PreferenceActionMetricsProvider,
|
||||
PreferenceLifecycleProvider,
|
||||
OnCheckedChangeListener {
|
||||
override val keywords: Int
|
||||
@@ -46,6 +50,11 @@ class VibrationMainSwitchPreference :
|
||||
|
||||
lateinit var vibrator: Vibrator
|
||||
|
||||
override val preferenceActionMetrics: Int
|
||||
get() = ACTION_VIBRATION_HAPTICS
|
||||
|
||||
override fun tags(context: Context) = arrayOf(KEY_VIBRATION_HAPTICS)
|
||||
|
||||
override fun storage(context: Context): KeyValueStore =
|
||||
VibrationMainSwitchToggleStorage(SettingsSystemStore.get(context))
|
||||
|
||||
|
||||
@@ -46,6 +46,7 @@ import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settingslib.bluetooth.BluetoothUtils;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||
import com.android.settingslib.bluetooth.HearingAidStatsLogUtils;
|
||||
import com.android.settingslib.flags.Flags;
|
||||
import com.android.settingslib.utils.ThreadUtils;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
@@ -62,6 +63,7 @@ import java.util.concurrent.TimeUnit;
|
||||
public abstract class BluetoothDevicePairingDetailBase extends DeviceListPreferenceFragment {
|
||||
private static final long AUTO_DISMISS_TIME_THRESHOLD_MS = TimeUnit.SECONDS.toMillis(15);
|
||||
private static final int AUTO_DISMISS_MESSAGE_ID = 1001;
|
||||
private static final int AUTO_FINISH_MESSAGE_ID = 1002;
|
||||
private static final ImmutableList<Integer> AUDIO_SHARING_PROFILES = ImmutableList.of(
|
||||
BluetoothProfile.LE_AUDIO,
|
||||
BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT, BluetoothProfile.VOLUME_CONTROL);
|
||||
@@ -77,7 +79,7 @@ public abstract class BluetoothDevicePairingDetailBase extends DeviceListPrefere
|
||||
@Nullable
|
||||
ProgressDialogFragment mProgressDialog = null;
|
||||
@VisibleForTesting
|
||||
boolean mShouldTriggerAudioSharingShareThenPairFlow = false;
|
||||
boolean mShouldTriggerShareThenPairFlow = false;
|
||||
private CopyOnWriteArrayList<BluetoothDevice> mDevicesWithMetadataChangedListener =
|
||||
new CopyOnWriteArrayList<>();
|
||||
|
||||
@@ -89,7 +91,8 @@ public abstract class BluetoothDevicePairingDetailBase extends DeviceListPrefere
|
||||
// onDeviceBondStateChanged(BOND_BONDED), BluetoothDevicePreference's summary has already
|
||||
// change from "Pairing..." to empty since it listens to metadata changes happens earlier.
|
||||
//
|
||||
// In share then pair flow, we have to wait on this page till the device is connected.
|
||||
// In pairing flow during audio sharing, we have to wait on this page till the device is
|
||||
// connected to check the device type and handle extra logic for audio sharing.
|
||||
// The BluetoothDevicePreference summary will be blank for seconds between "Pairing..." and
|
||||
// "Connecting..." To help users better understand the process, we listen to metadata change
|
||||
// as well and show a progress dialog with "Connecting to ...." once BluetoothDevice.getState()
|
||||
@@ -100,10 +103,11 @@ public abstract class BluetoothDevicePairingDetailBase extends DeviceListPrefere
|
||||
public void onMetadataChanged(@NonNull BluetoothDevice device, int key,
|
||||
@Nullable byte[] value) {
|
||||
Log.d(getLogTag(), "onMetadataChanged device = " + device + ", key = " + key);
|
||||
if (mShouldTriggerAudioSharingShareThenPairFlow && mProgressDialog == null
|
||||
if ((mShouldTriggerShareThenPairFlow || shouldSetTempBondMetadata())
|
||||
&& mProgressDialog == null
|
||||
&& device.getBondState() == BluetoothDevice.BOND_BONDED
|
||||
&& mSelectedList.contains(device)) {
|
||||
triggerAudioSharingShareThenPairFlow(device);
|
||||
handleDeviceBondedInAudioSharing(device);
|
||||
// Once device is bonded, remove the listener
|
||||
removeOnMetadataChangedListener(device);
|
||||
}
|
||||
@@ -133,7 +137,7 @@ public abstract class BluetoothDevicePairingDetailBase extends DeviceListPrefere
|
||||
return;
|
||||
}
|
||||
updateBluetooth();
|
||||
mShouldTriggerAudioSharingShareThenPairFlow = shouldTriggerAudioSharingShareThenPairFlow();
|
||||
mShouldTriggerShareThenPairFlow = shouldTriggerShareThenPairFlow();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -177,11 +181,12 @@ public abstract class BluetoothDevicePairingDetailBase extends DeviceListPrefere
|
||||
|
||||
@Override
|
||||
public void onDeviceBondStateChanged(CachedBluetoothDevice cachedDevice, int bondState) {
|
||||
boolean shouldSetTempBond = shouldSetTempBondMetadata();
|
||||
if (bondState == BluetoothDevice.BOND_BONDED) {
|
||||
if (cachedDevice != null && mShouldTriggerAudioSharingShareThenPairFlow) {
|
||||
if (cachedDevice != null && (mShouldTriggerShareThenPairFlow || shouldSetTempBond)) {
|
||||
BluetoothDevice device = cachedDevice.getDevice();
|
||||
if (device != null && mSelectedList.contains(device)) {
|
||||
triggerAudioSharingShareThenPairFlow(device);
|
||||
handleDeviceBondedInAudioSharing(device);
|
||||
removeOnMetadataChangedListener(device);
|
||||
return;
|
||||
}
|
||||
@@ -190,7 +195,7 @@ public abstract class BluetoothDevicePairingDetailBase extends DeviceListPrefere
|
||||
finish();
|
||||
return;
|
||||
} else if (bondState == BluetoothDevice.BOND_BONDING) {
|
||||
if (mShouldTriggerAudioSharingShareThenPairFlow && cachedDevice != null) {
|
||||
if ((mShouldTriggerShareThenPairFlow || shouldSetTempBond) && cachedDevice != null) {
|
||||
BluetoothDevice device = cachedDevice.getDevice();
|
||||
if (device != null && mSelectedList.contains(device)) {
|
||||
addOnMetadataChangedListener(device);
|
||||
@@ -203,7 +208,7 @@ public abstract class BluetoothDevicePairingDetailBase extends DeviceListPrefere
|
||||
pageId);
|
||||
HearingAidStatsLogUtils.setBondEntryForDevice(bondEntry, cachedDevice);
|
||||
} else if (bondState == BluetoothDevice.BOND_NONE) {
|
||||
if (mShouldTriggerAudioSharingShareThenPairFlow && cachedDevice != null) {
|
||||
if ((mShouldTriggerShareThenPairFlow || shouldSetTempBond) && cachedDevice != null) {
|
||||
BluetoothDevice device = cachedDevice.getDevice();
|
||||
if (device != null && mSelectedList.contains(device)) {
|
||||
removeOnMetadataChangedListener(device);
|
||||
@@ -233,21 +238,29 @@ public abstract class BluetoothDevicePairingDetailBase extends DeviceListPrefere
|
||||
final BluetoothDevice device = cachedDevice.getDevice();
|
||||
if (device != null
|
||||
&& mSelectedList.contains(device)) {
|
||||
var unused = ThreadUtils.postOnBackgroundThread(() -> {
|
||||
if (BluetoothUtils.isAudioSharingUIAvailable(getContext())) {
|
||||
if (mShouldTriggerAudioSharingShareThenPairFlow
|
||||
if ((mShouldTriggerShareThenPairFlow || shouldSetTempBondMetadata())
|
||||
&& state == BluetoothAdapter.STATE_CONNECTED
|
||||
&& device.equals(mJustBonded)
|
||||
&& AUDIO_SHARING_PROFILES.contains(bluetoothProfile)
|
||||
&& isReadyForAudioSharing(cachedDevice, bluetoothProfile)) {
|
||||
Log.d(getLogTag(),
|
||||
"onProfileConnectionStateChanged, ready for audio sharing");
|
||||
Log.d(getLogTag(), "onProfileConnectionStateChanged, lea eligible");
|
||||
dismissConnectingDialog();
|
||||
BluetoothUtils.setTemporaryBondMetadata(device);
|
||||
if (mShouldTriggerShareThenPairFlow) {
|
||||
mHandler.removeMessages(AUTO_DISMISS_MESSAGE_ID);
|
||||
finishFragmentWithResultForAudioSharing(device);
|
||||
postOnMainThread(() ->
|
||||
finishFragmentWithResultForAudioSharing(device));
|
||||
} else {
|
||||
mHandler.removeMessages(AUTO_FINISH_MESSAGE_ID);
|
||||
postOnMainThread(() -> finish());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
finish();
|
||||
postOnMainThread(() -> finish());
|
||||
}
|
||||
});
|
||||
} else {
|
||||
onDeviceDeleted(cachedDevice);
|
||||
}
|
||||
@@ -314,7 +327,7 @@ public abstract class BluetoothDevicePairingDetailBase extends DeviceListPrefere
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
boolean shouldTriggerAudioSharingShareThenPairFlow() {
|
||||
boolean shouldTriggerShareThenPairFlow() {
|
||||
if (BluetoothUtils.isAudioSharingUIAvailable(getContext())) {
|
||||
Activity activity = getActivity();
|
||||
Intent intent = activity == null ? null : activity.getIntent();
|
||||
@@ -328,6 +341,16 @@ public abstract class BluetoothDevicePairingDetailBase extends DeviceListPrefere
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean shouldSetTempBondMetadata() {
|
||||
return Flags.enableTemporaryBondDevicesUi()
|
||||
&& BluetoothUtils.isAudioSharingUIAvailable(getContext())
|
||||
&& BluetoothUtils.isBroadcasting(mLocalManager)
|
||||
&& mLocalManager != null
|
||||
&& mLocalManager.getCachedDeviceManager() != null
|
||||
&& mLocalManager.getProfileManager().getLeAudioBroadcastAssistantProfile() != null
|
||||
&& !Utils.shouldBlockPairingInAudioSharing(mLocalManager);
|
||||
}
|
||||
|
||||
private boolean isReadyForAudioSharing(@NonNull CachedBluetoothDevice cachedDevice,
|
||||
int justConnectedProfile) {
|
||||
for (int profile : AUDIO_SHARING_PROFILES) {
|
||||
@@ -382,11 +405,10 @@ public abstract class BluetoothDevicePairingDetailBase extends DeviceListPrefere
|
||||
});
|
||||
}
|
||||
|
||||
private void triggerAudioSharingShareThenPairFlow(
|
||||
@NonNull BluetoothDevice device) {
|
||||
private void handleDeviceBondedInAudioSharing(@Nullable BluetoothDevice device) {
|
||||
var unused = ThreadUtils.postOnBackgroundThread(() -> {
|
||||
if (mJustBonded != null) {
|
||||
Log.d(getLogTag(), "Skip triggerAudioSharingShareThenPairFlow, already done");
|
||||
Log.d(getLogTag(), "Skip handleDeviceBondedInAudioSharing, already done");
|
||||
return;
|
||||
}
|
||||
mJustBonded = device;
|
||||
@@ -395,18 +417,39 @@ public abstract class BluetoothDevicePairingDetailBase extends DeviceListPrefere
|
||||
String deviceName = TextUtils.isEmpty(aliasName) ? device.getAddress()
|
||||
: aliasName;
|
||||
showConnectingDialog(deviceName);
|
||||
// Wait for AUTO_DISMISS_TIME_THRESHOLD_MS and check if the paired device supports audio
|
||||
// sharing.
|
||||
if (mShouldTriggerShareThenPairFlow) {
|
||||
// For share then pair flow, we have strong signal that users wish to pair new
|
||||
// device to join sharing.
|
||||
// So we wait for AUTO_DISMISS_TIME_THRESHOLD_MS, if we find that the bonded device
|
||||
// is lea in onProfileConnectionStateChanged, we finish the activity, set the device
|
||||
// as temp bond and auto add source; otherwise, show dialog to notify that the
|
||||
// device is incompatible for audio sharing.
|
||||
if (!mHandler.hasMessages(AUTO_DISMISS_MESSAGE_ID)) {
|
||||
mHandler.postDelayed(() ->
|
||||
postOnMainThread(
|
||||
() -> {
|
||||
Log.d(getLogTag(), "Show incompatible dialog when timeout");
|
||||
Log.d(getLogTag(),
|
||||
"Show incompatible dialog when timeout");
|
||||
dismissConnectingDialog();
|
||||
AudioSharingIncompatibleDialogFragment.show(this, deviceName,
|
||||
AudioSharingIncompatibleDialogFragment.show(this,
|
||||
deviceName,
|
||||
() -> finish());
|
||||
}), AUTO_DISMISS_MESSAGE_ID, AUTO_DISMISS_TIME_THRESHOLD_MS);
|
||||
}
|
||||
} else {
|
||||
// For other pairing request during audio sharing with sinks < 2, we wait for
|
||||
// AUTO_DISMISS_TIME_THRESHOLD_MS, if we find that the bonded device is lea in
|
||||
// onProfileConnectionStateChanged, we finish the activity and set the device as
|
||||
// temp bond; otherwise, we just finish the activity.
|
||||
if (!mHandler.hasMessages(AUTO_FINISH_MESSAGE_ID)) {
|
||||
mHandler.postDelayed(() ->
|
||||
postOnMainThread(
|
||||
() -> {
|
||||
Log.d(getLogTag(), "Finish activity when timeout");
|
||||
finish();
|
||||
}), AUTO_FINISH_MESSAGE_ID, AUTO_DISMISS_TIME_THRESHOLD_MS);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ import android.provider.Settings;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
|
||||
@@ -42,17 +43,21 @@ import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settingslib.bluetooth.BluetoothUtils;
|
||||
import com.android.settingslib.bluetooth.BluetoothUtils.ErrorListener;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothManager.BluetoothManagerCallback;
|
||||
import com.android.settingslib.utils.ThreadUtils;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.FutureTask;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Utils is a helper class that contains constants for various
|
||||
@@ -293,4 +298,30 @@ public final class Utils {
|
||||
ThreadUtils.postOnMainThread(runnable);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if need to block pairing during audio sharing
|
||||
*
|
||||
* @param localBtManager {@link LocalBluetoothManager}
|
||||
* @return if need to block pairing during audio sharing
|
||||
*/
|
||||
public static boolean shouldBlockPairingInAudioSharing(
|
||||
@NonNull LocalBluetoothManager localBtManager) {
|
||||
if (!BluetoothUtils.isBroadcasting(localBtManager)) return false;
|
||||
LocalBluetoothLeBroadcastAssistant assistant =
|
||||
localBtManager.getProfileManager().getLeAudioBroadcastAssistantProfile();
|
||||
CachedBluetoothDeviceManager deviceManager = localBtManager.getCachedDeviceManager();
|
||||
List<BluetoothDevice> connectedDevices =
|
||||
assistant == null ? ImmutableList.of() : assistant.getAllConnectedDevices();
|
||||
// Block the pairing if there is ongoing audio sharing session and
|
||||
// a) there is already one temp bond sink connected
|
||||
// or b) there are already two sinks joining the audio sharing
|
||||
return assistant != null && deviceManager != null
|
||||
&& (connectedDevices.stream().anyMatch(BluetoothUtils::isTemporaryBondDevice)
|
||||
|| connectedDevices.stream().filter(
|
||||
d -> BluetoothUtils.hasActiveLocalBroadcastSourceForBtDevice(d,
|
||||
localBtManager))
|
||||
.map(d -> BluetoothUtils.getGroupId(deviceManager.findDevice(d))).collect(
|
||||
Collectors.toSet()).size() >= 2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,8 +159,6 @@ class TopologyScale(
|
||||
}
|
||||
}
|
||||
|
||||
const val TOPOLOGY_PREFERENCE_KEY = "display_topology_preference"
|
||||
|
||||
/** Represents a draggable block in the topology pane. */
|
||||
class DisplayBlock(context : Context) : Button(context) {
|
||||
@VisibleForTesting var mSelectedImage: Drawable = ColorDrawable(Color.BLACK)
|
||||
@@ -240,7 +238,6 @@ class DisplayTopologyPreference(context : Context)
|
||||
// Prevent highlight when hovering with mouse.
|
||||
isSelectable = false
|
||||
|
||||
key = TOPOLOGY_PREFERENCE_KEY
|
||||
isPersistent = false
|
||||
|
||||
injector = Injector(context)
|
||||
|
||||
@@ -64,33 +64,69 @@ import java.util.List;
|
||||
* The Settings screen for External Displays configuration and connection management.
|
||||
*/
|
||||
public class ExternalDisplayPreferenceFragment extends SettingsPreferenceFragmentBase {
|
||||
@VisibleForTesting enum PrefBasics {
|
||||
DISPLAY_TOPOLOGY(10, "display_topology_preference", null),
|
||||
MIRROR(20, "mirror_preference", null),
|
||||
|
||||
// If shown, use toggle should be before other per-display settings.
|
||||
EXTERNAL_DISPLAY_USE(30, "external_display_use_preference",
|
||||
R.string.external_display_use_title),
|
||||
|
||||
ILLUSTRATION(35, "external_display_illustration", null),
|
||||
|
||||
// If shown, external display size is before other per-display settings.
|
||||
EXTERNAL_DISPLAY_SIZE(40, "external_display_size", R.string.screen_zoom_title),
|
||||
EXTERNAL_DISPLAY_ROTATION(50, "external_display_rotation",
|
||||
R.string.external_display_rotation),
|
||||
EXTERNAL_DISPLAY_RESOLUTION(60, "external_display_resolution",
|
||||
R.string.external_display_resolution_settings_title),
|
||||
|
||||
// Built-in display link is after per-display settings.
|
||||
BUILTIN_DISPLAY_LIST(70, "builtin_display_list_preference",
|
||||
R.string.builtin_display_settings_category),
|
||||
|
||||
DISPLAYS_LIST(80, "displays_list_preference", null),
|
||||
|
||||
// If shown, footer should appear below everything.
|
||||
FOOTER(90, "footer_preference", null);
|
||||
|
||||
|
||||
PrefBasics(int order, String key, @Nullable Integer titleResource) {
|
||||
this.order = order;
|
||||
this.key = key;
|
||||
this.titleResource = titleResource;
|
||||
}
|
||||
|
||||
// Fields must be public to make the linter happy.
|
||||
public final int order;
|
||||
public final String key;
|
||||
@Nullable public final Integer titleResource;
|
||||
|
||||
void apply(Preference preference) {
|
||||
if (order != -1) {
|
||||
preference.setOrder(order);
|
||||
}
|
||||
if (titleResource != null) {
|
||||
preference.setTitle(titleResource);
|
||||
}
|
||||
preference.setKey(key);
|
||||
preference.setPersistent(false);
|
||||
}
|
||||
}
|
||||
|
||||
static final int EXTERNAL_DISPLAY_SETTINGS_RESOURCE = R.xml.external_display_settings;
|
||||
static final String DISPLAYS_LIST_PREFERENCE_KEY = "displays_list_preference";
|
||||
static final String BUILTIN_DISPLAY_LIST_PREFERENCE_KEY = "builtin_display_list_preference";
|
||||
static final String EXTERNAL_DISPLAY_USE_PREFERENCE_KEY = "external_display_use_preference";
|
||||
static final String EXTERNAL_DISPLAY_ROTATION_KEY = "external_display_rotation";
|
||||
static final String EXTERNAL_DISPLAY_RESOLUTION_PREFERENCE_KEY = "external_display_resolution";
|
||||
static final String EXTERNAL_DISPLAY_SIZE_PREFERENCE_KEY = "external_display_size";
|
||||
static final int EXTERNAL_DISPLAY_CHANGE_RESOLUTION_FOOTER_RESOURCE =
|
||||
R.string.external_display_change_resolution_footer_title;
|
||||
static final int EXTERNAL_DISPLAY_LANDSCAPE_DRAWABLE =
|
||||
R.drawable.external_display_mirror_landscape;
|
||||
static final int EXTERNAL_DISPLAY_TITLE_RESOURCE =
|
||||
R.string.external_display_settings_title;
|
||||
static final int EXTERNAL_DISPLAY_USE_TITLE_RESOURCE =
|
||||
R.string.external_display_use_title;
|
||||
static final int EXTERNAL_DISPLAY_NOT_FOUND_FOOTER_RESOURCE =
|
||||
R.string.external_display_not_found_footer_title;
|
||||
static final int EXTERNAL_DISPLAY_PORTRAIT_DRAWABLE =
|
||||
R.drawable.external_display_mirror_portrait;
|
||||
static final int EXTERNAL_DISPLAY_ROTATION_TITLE_RESOURCE =
|
||||
R.string.external_display_rotation;
|
||||
static final int EXTERNAL_DISPLAY_RESOLUTION_TITLE_RESOURCE =
|
||||
R.string.external_display_resolution_settings_title;
|
||||
static final int EXTERNAL_DISPLAY_SIZE_TITLE_RESOURCE = R.string.screen_zoom_title;
|
||||
static final int EXTERNAL_DISPLAY_SIZE_SUMMARY_RESOURCE = R.string.screen_zoom_short_summary;
|
||||
static final int BUILTIN_DISPLAY_SETTINGS_CATEGORY_RESOURCE =
|
||||
R.string.builtin_display_settings_category;
|
||||
|
||||
@VisibleForTesting
|
||||
static final String PREVIOUSLY_SHOWN_LIST_KEY = "mPreviouslyShownListOfDisplays";
|
||||
private boolean mStarted;
|
||||
@@ -253,9 +289,7 @@ public class ExternalDisplayPreferenceFragment extends SettingsPreferenceFragmen
|
||||
ListPreference getRotationPreference(@NonNull Context context) {
|
||||
if (mRotationPref == null) {
|
||||
mRotationPref = new ListPreference(context);
|
||||
mRotationPref.setPersistent(false);
|
||||
mRotationPref.setKey(EXTERNAL_DISPLAY_ROTATION_KEY);
|
||||
mRotationPref.setTitle(EXTERNAL_DISPLAY_ROTATION_TITLE_RESOURCE);
|
||||
PrefBasics.EXTERNAL_DISPLAY_ROTATION.apply(mRotationPref);
|
||||
}
|
||||
return mRotationPref;
|
||||
}
|
||||
@@ -265,9 +299,7 @@ public class ExternalDisplayPreferenceFragment extends SettingsPreferenceFragmen
|
||||
Preference getResolutionPreference(@NonNull Context context) {
|
||||
if (mResolutionPreference == null) {
|
||||
mResolutionPreference = new Preference(context);
|
||||
mResolutionPreference.setPersistent(false);
|
||||
mResolutionPreference.setKey(EXTERNAL_DISPLAY_RESOLUTION_PREFERENCE_KEY);
|
||||
mResolutionPreference.setTitle(EXTERNAL_DISPLAY_RESOLUTION_TITLE_RESOURCE);
|
||||
PrefBasics.EXTERNAL_DISPLAY_RESOLUTION.apply(mResolutionPreference);
|
||||
}
|
||||
return mResolutionPreference;
|
||||
}
|
||||
@@ -277,9 +309,7 @@ public class ExternalDisplayPreferenceFragment extends SettingsPreferenceFragmen
|
||||
MainSwitchPreference getUseDisplayPreference(@NonNull Context context) {
|
||||
if (mUseDisplayPref == null) {
|
||||
mUseDisplayPref = new MainSwitchPreference(context);
|
||||
mUseDisplayPref.setPersistent(false);
|
||||
mUseDisplayPref.setKey(EXTERNAL_DISPLAY_USE_PREFERENCE_KEY);
|
||||
mUseDisplayPref.setTitle(EXTERNAL_DISPLAY_USE_TITLE_RESOURCE);
|
||||
PrefBasics.EXTERNAL_DISPLAY_USE.apply(mUseDisplayPref);
|
||||
}
|
||||
return mUseDisplayPref;
|
||||
}
|
||||
@@ -289,8 +319,7 @@ public class ExternalDisplayPreferenceFragment extends SettingsPreferenceFragmen
|
||||
IllustrationPreference getIllustrationPreference(@NonNull Context context) {
|
||||
if (mImagePreference == null) {
|
||||
mImagePreference = new IllustrationPreference(context);
|
||||
mImagePreference.setPersistent(false);
|
||||
mImagePreference.setKey("external_display_illustration");
|
||||
PrefBasics.ILLUSTRATION.apply(mImagePreference);
|
||||
}
|
||||
return mImagePreference;
|
||||
}
|
||||
@@ -308,9 +337,7 @@ public class ExternalDisplayPreferenceFragment extends SettingsPreferenceFragmen
|
||||
private PreferenceCategory getDisplaysListPreference(@NonNull Context context) {
|
||||
if (mDisplaysPreference == null) {
|
||||
mDisplaysPreference = new PreferenceCategory(context);
|
||||
mDisplaysPreference.setPersistent(false);
|
||||
mDisplaysPreference.setOrder(40);
|
||||
mDisplaysPreference.setKey(DISPLAYS_LIST_PREFERENCE_KEY);
|
||||
PrefBasics.DISPLAYS_LIST.apply(mDisplaysPreference);
|
||||
}
|
||||
return mDisplaysPreference;
|
||||
}
|
||||
@@ -319,10 +346,7 @@ public class ExternalDisplayPreferenceFragment extends SettingsPreferenceFragmen
|
||||
private PreferenceCategory getBuiltinDisplayListPreference(@NonNull Context context) {
|
||||
if (mBuiltinDisplayPreference == null) {
|
||||
mBuiltinDisplayPreference = new PreferenceCategory(context);
|
||||
mBuiltinDisplayPreference.setPersistent(false);
|
||||
mBuiltinDisplayPreference.setOrder(30);
|
||||
mBuiltinDisplayPreference.setKey(BUILTIN_DISPLAY_LIST_PREFERENCE_KEY);
|
||||
mBuiltinDisplayPreference.setTitle(BUILTIN_DISPLAY_SETTINGS_CATEGORY_RESOURCE);
|
||||
PrefBasics.BUILTIN_DISPLAY_LIST.apply(mBuiltinDisplayPreference);
|
||||
}
|
||||
return mBuiltinDisplayPreference;
|
||||
}
|
||||
@@ -338,7 +362,7 @@ public class ExternalDisplayPreferenceFragment extends SettingsPreferenceFragmen
|
||||
@NonNull Preference getDisplayTopologyPreference(@NonNull Context context) {
|
||||
if (mDisplayTopologyPreference == null) {
|
||||
mDisplayTopologyPreference = new DisplayTopologyPreference(context);
|
||||
mDisplayTopologyPreference.setOrder(10);
|
||||
PrefBasics.DISPLAY_TOPOLOGY.apply(mDisplayTopologyPreference);
|
||||
}
|
||||
return mDisplayTopologyPreference;
|
||||
}
|
||||
@@ -346,7 +370,7 @@ public class ExternalDisplayPreferenceFragment extends SettingsPreferenceFragmen
|
||||
@NonNull Preference getMirrorPreference(@NonNull Context context) {
|
||||
if (mMirrorPreference == null) {
|
||||
mMirrorPreference = new MirrorPreference(context);
|
||||
mMirrorPreference.setOrder(20);
|
||||
PrefBasics.MIRROR.apply(mMirrorPreference);
|
||||
}
|
||||
return mMirrorPreference;
|
||||
}
|
||||
@@ -386,16 +410,18 @@ public class ExternalDisplayPreferenceFragment extends SettingsPreferenceFragmen
|
||||
|
||||
private void updateScreenForDisplayId(final int displayId,
|
||||
@NonNull final PrefRefresh screen, @NonNull Context context) {
|
||||
final boolean forceShowList = displayId == INVALID_DISPLAY
|
||||
&& isTopologyPaneEnabled(mInjector);
|
||||
final var displaysToShow = externalDisplaysToShow(displayId);
|
||||
|
||||
if (!forceShowList && displaysToShow.isEmpty() && displayId == INVALID_DISPLAY) {
|
||||
if (displaysToShow.isEmpty() && displayId == INVALID_DISPLAY) {
|
||||
showTextWhenNoDisplaysToShow(screen, context);
|
||||
} else if (!forceShowList && displaysToShow.size() == 1
|
||||
} else if (displaysToShow.size() == 1
|
||||
&& ((displayId == INVALID_DISPLAY && !mPreviouslyShownListOfDisplays)
|
||||
|| displaysToShow.get(0).getDisplayId() == displayId)) {
|
||||
showDisplaySettings(displaysToShow.get(0), screen, context);
|
||||
if (displayId == INVALID_DISPLAY && isTopologyPaneEnabled(mInjector)) {
|
||||
// Only show the topology pane if the user did not arrive via the displays list.
|
||||
maybeAddV2Components(context, screen);
|
||||
}
|
||||
} else if (displayId == INVALID_DISPLAY) {
|
||||
// If ever shown a list of displays - keep showing it for consistency after
|
||||
// disconnecting one of the displays, and only one display is left.
|
||||
@@ -446,21 +472,30 @@ public class ExternalDisplayPreferenceFragment extends SettingsPreferenceFragmen
|
||||
screen.addPreference(updateResolutionPreference(context, display));
|
||||
screen.addPreference(updateRotationPreference(context, display, displayRotation));
|
||||
if (isResolutionSettingEnabled(mInjector)) {
|
||||
// Do not show the footer about changing resolution affecting apps. This is not in the
|
||||
// UX design for v2, and there is no good place to put it, since (a) if it is on the
|
||||
// bottom of the screen, the external resolution setting must be below the built-in
|
||||
// display options for the per-display fragment, which is too hidden for the per-display
|
||||
// fragment, or (b) the footer is above the Built-in display settings, rather than the
|
||||
// bottom of the screen, which contradicts the visual style and purpose of the
|
||||
// FooterPreference class, or (c) we must hide the built-in display settings, which is
|
||||
// inconsistent with the topology pane, which shows that display.
|
||||
// TODO(b/352648432): probably remove footer once the pane and rest of v2 UI is in
|
||||
// place.
|
||||
if (!isTopologyPaneEnabled(mInjector)) {
|
||||
screen.addPreference(updateFooterPreference(context,
|
||||
EXTERNAL_DISPLAY_CHANGE_RESOLUTION_FOOTER_RESOURCE));
|
||||
}
|
||||
}
|
||||
if (isDisplaySizeSettingEnabled(mInjector)) {
|
||||
screen.addPreference(updateSizePreference(context));
|
||||
}
|
||||
}
|
||||
|
||||
private void showDisplaysList(@NonNull List<Display> displaysToShow,
|
||||
@NonNull PrefRefresh screen, @NonNull Context context) {
|
||||
private void maybeAddV2Components(Context context, PrefRefresh screen) {
|
||||
if (isTopologyPaneEnabled(mInjector)) {
|
||||
screen.addPreference(getDisplayTopologyPreference(context));
|
||||
if (!displaysToShow.isEmpty()) {
|
||||
screen.addPreference(getMirrorPreference(context));
|
||||
}
|
||||
|
||||
// If topology is shown, we also show a preference for the built-in display for
|
||||
// consistency with the topology.
|
||||
@@ -468,7 +503,11 @@ public class ExternalDisplayPreferenceFragment extends SettingsPreferenceFragmen
|
||||
screen.addPreference(builtinCategory);
|
||||
builtinCategory.addPreference(getBuiltinDisplaySizeAndTextPreference(context));
|
||||
}
|
||||
}
|
||||
|
||||
private void showDisplaysList(@NonNull List<Display> displaysToShow,
|
||||
@NonNull PrefRefresh screen, @NonNull Context context) {
|
||||
maybeAddV2Components(context, screen);
|
||||
var displayGroupPref = getDisplaysListPreference(context);
|
||||
if (!displaysToShow.isEmpty()) {
|
||||
screen.addPreference(displayGroupPref);
|
||||
@@ -501,8 +540,9 @@ public class ExternalDisplayPreferenceFragment extends SettingsPreferenceFragmen
|
||||
groupCleanable.addPreference(category);
|
||||
|
||||
var prefItem = new DisplayPreference(context, display);
|
||||
prefItem.setTitle(context.getString(EXTERNAL_DISPLAY_RESOLUTION_TITLE_RESOURCE)
|
||||
+ " | " + context.getString(EXTERNAL_DISPLAY_ROTATION_TITLE_RESOURCE));
|
||||
prefItem.setTitle(
|
||||
context.getString(PrefBasics.EXTERNAL_DISPLAY_RESOLUTION.titleResource) + " | "
|
||||
+ context.getString(PrefBasics.EXTERNAL_DISPLAY_ROTATION.titleResource));
|
||||
prefItem.setKey(itemKey);
|
||||
|
||||
category.addPreference(prefItem);
|
||||
@@ -577,6 +617,7 @@ public class ExternalDisplayPreferenceFragment extends SettingsPreferenceFragmen
|
||||
private Preference updateFooterPreference(@NonNull final Context context, final int title) {
|
||||
var pref = getFooterPreference(context);
|
||||
pref.setTitle(title);
|
||||
PrefBasics.FOOTER.apply(pref);
|
||||
return pref;
|
||||
}
|
||||
|
||||
@@ -625,10 +666,8 @@ public class ExternalDisplayPreferenceFragment extends SettingsPreferenceFragmen
|
||||
|
||||
private Preference updateSizePreference(@NonNull final Context context) {
|
||||
var pref = (Preference) getSizePreference(context);
|
||||
pref.setKey(EXTERNAL_DISPLAY_SIZE_PREFERENCE_KEY);
|
||||
PrefBasics.EXTERNAL_DISPLAY_SIZE.apply(pref);
|
||||
pref.setSummary(EXTERNAL_DISPLAY_SIZE_SUMMARY_RESOURCE);
|
||||
pref.setPersistent(false);
|
||||
pref.setTitle(EXTERNAL_DISPLAY_SIZE_TITLE_RESOURCE);
|
||||
pref.setOnPreferenceClickListener(
|
||||
(Preference p) -> {
|
||||
writePreferenceClickMetric(p);
|
||||
|
||||
@@ -23,8 +23,6 @@ import androidx.preference.SwitchPreferenceCompat
|
||||
|
||||
import com.android.settings.R
|
||||
|
||||
const val MIRROR_PREFERENCE_KEY = "mirror_builtin_display"
|
||||
|
||||
/**
|
||||
* A switch preference which is backed by the MIRROR_BUILT_IN_DISPLAY global setting.
|
||||
*/
|
||||
@@ -32,7 +30,6 @@ class MirrorPreference(context: Context): SwitchPreferenceCompat(context) {
|
||||
init {
|
||||
setTitle(R.string.external_display_mirroring_title)
|
||||
|
||||
key = MIRROR_PREFERENCE_KEY
|
||||
isPersistent = false
|
||||
}
|
||||
|
||||
|
||||
@@ -450,8 +450,16 @@ public class SimStatusDialogController implements DefaultLifecycleObserver {
|
||||
String dataNetworkTypeName = null;
|
||||
String voiceNetworkTypeName = null;
|
||||
final int subId = mSubscriptionInfo.getSubscriptionId();
|
||||
final int actualDataNetworkType = getTelephonyManager().getDataNetworkType();
|
||||
final int actualVoiceNetworkType = getTelephonyManager().getVoiceNetworkType();
|
||||
int actualDataNetworkType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
|
||||
int actualVoiceNetworkType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
|
||||
PackageManager pm = mContext.getPackageManager();
|
||||
if (pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)) {
|
||||
actualDataNetworkType = getTelephonyManager().getDataNetworkType();
|
||||
}
|
||||
if (pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY_CALLING)) {
|
||||
actualVoiceNetworkType = getTelephonyManager().getVoiceNetworkType();
|
||||
}
|
||||
|
||||
final int overrideNetworkType = mTelephonyDisplayInfo == null
|
||||
? TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE
|
||||
: mTelephonyDisplayInfo.getOverrideNetworkType();
|
||||
|
||||
@@ -16,12 +16,14 @@
|
||||
|
||||
package com.android.settings.display
|
||||
|
||||
import android.app.settings.SettingsEnums.ACTION_AMBIENT_DISPLAY_ALWAYS_ON
|
||||
import android.content.Context
|
||||
import android.hardware.display.AmbientDisplayConfiguration
|
||||
import android.os.SystemProperties
|
||||
import android.os.UserHandle
|
||||
import android.os.UserManager
|
||||
import android.provider.Settings.Secure.DOZE_ALWAYS_ON
|
||||
import com.android.settings.PreferenceActionMetricsProvider
|
||||
import com.android.settings.PreferenceRestrictionMixin
|
||||
import com.android.settings.R
|
||||
import com.android.settings.contract.KEY_AMBIENT_DISPLAY_ALWAYS_ON
|
||||
@@ -41,6 +43,7 @@ import com.android.settingslib.metadata.SwitchPreference
|
||||
// LINT.IfChange
|
||||
class AmbientDisplayAlwaysOnPreference :
|
||||
SwitchPreference(KEY, R.string.doze_always_on_title, R.string.doze_always_on_summary),
|
||||
PreferenceActionMetricsProvider,
|
||||
PreferenceAvailabilityProvider,
|
||||
PreferenceSummaryProvider,
|
||||
PreferenceRestrictionMixin {
|
||||
@@ -48,6 +51,11 @@ class AmbientDisplayAlwaysOnPreference :
|
||||
override val keywords: Int
|
||||
get() = R.string.keywords_always_show_time_info
|
||||
|
||||
override val preferenceActionMetrics: Int
|
||||
get() = ACTION_AMBIENT_DISPLAY_ALWAYS_ON
|
||||
|
||||
override fun tags(context: Context) = arrayOf(KEY_AMBIENT_DISPLAY_ALWAYS_ON)
|
||||
|
||||
override val restrictionKeys: Array<String>
|
||||
get() = arrayOf(UserManager.DISALLOW_AMBIENT_DISPLAY)
|
||||
|
||||
|
||||
@@ -15,30 +15,32 @@
|
||||
*/
|
||||
package com.android.settings.display
|
||||
|
||||
import android.app.settings.SettingsEnums
|
||||
import android.app.settings.SettingsEnums.OPEN_BATTERY_PERCENTAGE
|
||||
import android.content.Context
|
||||
import android.provider.Settings
|
||||
import androidx.preference.Preference
|
||||
import com.android.settings.PreferenceActionMetricsProvider
|
||||
import com.android.settings.R
|
||||
import com.android.settings.Utils
|
||||
import com.android.settings.overlay.FeatureFactory.Companion.featureFactory
|
||||
import com.android.settings.contract.KEY_BATTERY_PERCENTAGE
|
||||
import com.android.settingslib.datastore.KeyValueStore
|
||||
import com.android.settingslib.datastore.KeyedObservableDelegate
|
||||
import com.android.settingslib.datastore.SettingsStore
|
||||
import com.android.settingslib.datastore.SettingsSystemStore
|
||||
import com.android.settingslib.metadata.PreferenceAvailabilityProvider
|
||||
import com.android.settingslib.metadata.PreferenceMetadata
|
||||
import com.android.settingslib.metadata.ReadWritePermit
|
||||
import com.android.settingslib.metadata.SensitivityLevel
|
||||
import com.android.settingslib.metadata.SwitchPreference
|
||||
import com.android.settingslib.preference.SwitchPreferenceBinding
|
||||
|
||||
// LINT.IfChange
|
||||
class BatteryPercentageSwitchPreference :
|
||||
SwitchPreference(KEY, R.string.battery_percentage, R.string.battery_percentage_description),
|
||||
SwitchPreferenceBinding,
|
||||
PreferenceAvailabilityProvider,
|
||||
Preference.OnPreferenceChangeListener {
|
||||
PreferenceActionMetricsProvider,
|
||||
PreferenceAvailabilityProvider {
|
||||
|
||||
override val preferenceActionMetrics: Int
|
||||
get() = OPEN_BATTERY_PERCENTAGE
|
||||
|
||||
override fun tags(context: Context) = arrayOf(KEY_BATTERY_PERCENTAGE)
|
||||
|
||||
override fun storage(context: Context): KeyValueStore =
|
||||
BatteryPercentageStorage(context, SettingsSystemStore.get(context))
|
||||
@@ -66,22 +68,6 @@ class BatteryPercentageSwitchPreference :
|
||||
override val sensitivityLevel
|
||||
get() = SensitivityLevel.NO_SENSITIVITY
|
||||
|
||||
override fun bind(preference: Preference, metadata: PreferenceMetadata) {
|
||||
super.bind(preference, metadata)
|
||||
preference.onPreferenceChangeListener = this
|
||||
}
|
||||
|
||||
override fun onPreferenceChange(preference: Preference, newValue: Any?): Boolean {
|
||||
val showPercentage = newValue as Boolean
|
||||
|
||||
featureFactory.metricsFeatureProvider.action(
|
||||
preference.context,
|
||||
SettingsEnums.OPEN_BATTERY_PERCENTAGE,
|
||||
showPercentage,
|
||||
)
|
||||
return true
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
private class BatteryPercentageStorage(
|
||||
private val context: Context,
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
package com.android.settings.display
|
||||
|
||||
import android.app.ActivityOptions
|
||||
import android.app.settings.SettingsEnums.ACTION_BRIGHTNESS_LEVEL
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.Intent.ACTION_SHOW_BRIGHTNESS_DIALOG
|
||||
@@ -26,9 +27,11 @@ import android.hardware.display.DisplayManager.DisplayListener
|
||||
import android.os.UserManager
|
||||
import android.provider.Settings.System
|
||||
import androidx.preference.Preference
|
||||
import com.android.settings.PreferenceActionMetricsProvider
|
||||
import com.android.settings.PreferenceRestrictionMixin
|
||||
import com.android.settings.R
|
||||
import com.android.settings.Utils
|
||||
import com.android.settings.contract.KEY_BRIGHTNESS_LEVEL
|
||||
import com.android.settings.core.SettingsBaseActivity
|
||||
import com.android.settingslib.RestrictedPreference
|
||||
import com.android.settingslib.datastore.AbstractKeyedDataObservable
|
||||
@@ -56,6 +59,7 @@ class BrightnessLevelPreference :
|
||||
IntRangeValuePreference,
|
||||
PreferenceBinding,
|
||||
PreferenceRestrictionMixin,
|
||||
PreferenceActionMetricsProvider,
|
||||
PreferenceSummaryProvider,
|
||||
Preference.OnPreferenceClickListener {
|
||||
|
||||
@@ -68,6 +72,11 @@ class BrightnessLevelPreference :
|
||||
override val keywords: Int
|
||||
get() = R.string.keywords_display_brightness_level
|
||||
|
||||
override val preferenceActionMetrics: Int
|
||||
get() = ACTION_BRIGHTNESS_LEVEL
|
||||
|
||||
override fun tags(context: Context) = arrayOf(KEY_BRIGHTNESS_LEVEL)
|
||||
|
||||
override fun getSummary(context: Context): CharSequence? =
|
||||
NumberFormat.getPercentInstance().format(context.brightnessPercent)
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.android.settings.display
|
||||
|
||||
import android.app.settings.SettingsEnums.ACTION_SMOOTH_DISPLAY
|
||||
import android.content.Context
|
||||
import android.hardware.display.DisplayManager
|
||||
import android.provider.DeviceConfig
|
||||
@@ -23,7 +24,9 @@ import com.android.internal.display.RefreshRateSettingsUtils.DEFAULT_REFRESH_RAT
|
||||
import com.android.internal.display.RefreshRateSettingsUtils.findHighestRefreshRateAmongAllDisplays
|
||||
import com.android.internal.display.RefreshRateSettingsUtils.findHighestRefreshRateForDefaultDisplay
|
||||
import com.android.server.display.feature.flags.Flags
|
||||
import com.android.settings.PreferenceActionMetricsProvider
|
||||
import com.android.settings.R
|
||||
import com.android.settings.contract.KEY_SMOOTH_DISPLAY
|
||||
import com.android.settingslib.datastore.HandlerExecutor
|
||||
import com.android.settingslib.datastore.KeyValueStore
|
||||
import com.android.settingslib.datastore.KeyedObservableDelegate
|
||||
@@ -41,12 +44,18 @@ import kotlin.math.roundToInt
|
||||
// LINT.IfChange
|
||||
class PeakRefreshRateSwitchPreference :
|
||||
SwitchPreference(KEY, R.string.peak_refresh_rate_title),
|
||||
PreferenceActionMetricsProvider,
|
||||
PreferenceAvailabilityProvider,
|
||||
PreferenceSummaryProvider,
|
||||
PreferenceLifecycleProvider {
|
||||
|
||||
private var propertiesChangedListener: DeviceConfig.OnPropertiesChangedListener? = null
|
||||
|
||||
override val preferenceActionMetrics: Int
|
||||
get() = ACTION_SMOOTH_DISPLAY
|
||||
|
||||
override fun tags(context: Context) = arrayOf(KEY_SMOOTH_DISPLAY)
|
||||
|
||||
override fun storage(context: Context): KeyValueStore =
|
||||
PeakRefreshRateStore(context, SettingsSystemStore.get(context))
|
||||
|
||||
|
||||
@@ -17,11 +17,14 @@
|
||||
package com.android.settings.display.darkmode
|
||||
|
||||
import android.Manifest
|
||||
import android.app.settings.SettingsEnums.ACTION_DARK_THEME
|
||||
import android.content.Context
|
||||
import android.os.PowerManager
|
||||
import androidx.preference.Preference
|
||||
import androidx.preference.PreferenceScreen
|
||||
import com.android.settings.PreferenceActionMetricsProvider
|
||||
import com.android.settings.R
|
||||
import com.android.settings.contract.KEY_DARK_THEME
|
||||
import com.android.settings.flags.Flags
|
||||
import com.android.settingslib.PrimarySwitchPreferenceBinding
|
||||
import com.android.settingslib.datastore.KeyValueStore
|
||||
@@ -42,6 +45,7 @@ class DarkModeScreen(context: Context) :
|
||||
PreferenceScreenCreator,
|
||||
PreferenceScreenBinding, // binding for screen page
|
||||
PrimarySwitchPreferenceBinding, // binding for screen entry point widget
|
||||
PreferenceActionMetricsProvider,
|
||||
BooleanValuePreference,
|
||||
PreferenceSummaryProvider {
|
||||
|
||||
@@ -56,6 +60,11 @@ class DarkModeScreen(context: Context) :
|
||||
override val keywords: Int
|
||||
get() = R.string.keywords_dark_ui_mode
|
||||
|
||||
override val preferenceActionMetrics: Int
|
||||
get() = ACTION_DARK_THEME
|
||||
|
||||
override fun tags(context: Context) = arrayOf(KEY_DARK_THEME)
|
||||
|
||||
override fun getReadPermissions(context: Context) = Permissions.EMPTY
|
||||
|
||||
override fun getWritePermissions(context: Context) =
|
||||
|
||||
@@ -16,10 +16,13 @@
|
||||
|
||||
package com.android.settings.fuelgauge
|
||||
|
||||
import android.app.settings.SettingsEnums.ACTION_BATTERY_LEVEL
|
||||
import android.content.Context
|
||||
import androidx.annotation.VisibleForTesting
|
||||
import androidx.preference.Preference
|
||||
import com.android.settings.PreferenceActionMetricsProvider
|
||||
import com.android.settings.R
|
||||
import com.android.settings.contract.KEY_BATTERY_LEVEL
|
||||
import com.android.settings.fuelgauge.BatteryBroadcastReceiver.BatteryUpdateType.BATTERY_NOT_PRESENT
|
||||
import com.android.settingslib.Utils
|
||||
import com.android.settingslib.datastore.KeyValueStore
|
||||
@@ -37,7 +40,10 @@ import com.android.settingslib.widget.UsageProgressBarPreference
|
||||
|
||||
// LINT.IfChange
|
||||
class BatteryHeaderPreference :
|
||||
IntRangeValuePreference, PreferenceBinding, PreferenceLifecycleProvider {
|
||||
IntRangeValuePreference,
|
||||
PreferenceBinding,
|
||||
PreferenceActionMetricsProvider,
|
||||
PreferenceLifecycleProvider {
|
||||
|
||||
@VisibleForTesting var batteryBroadcastReceiver: BatteryBroadcastReceiver? = null
|
||||
|
||||
@@ -47,6 +53,11 @@ class BatteryHeaderPreference :
|
||||
override val title: Int
|
||||
get() = R.string.summary_placeholder
|
||||
|
||||
override val preferenceActionMetrics: Int
|
||||
get() = ACTION_BATTERY_LEVEL
|
||||
|
||||
override fun tags(context: Context) = arrayOf(KEY_BATTERY_LEVEL)
|
||||
|
||||
override fun createWidget(context: Context) = UsageProgressBarPreference(context)
|
||||
|
||||
override fun bind(preference: Preference, metadata: PreferenceMetadata) {
|
||||
|
||||
@@ -16,10 +16,13 @@
|
||||
|
||||
package com.android.settings.network
|
||||
|
||||
import android.app.settings.SettingsEnums.ACTION_ADAPTIVE_CONNECTIVITY
|
||||
import android.content.Context
|
||||
import android.net.wifi.WifiManager
|
||||
import android.provider.Settings.Secure.ADAPTIVE_CONNECTIVITY_ENABLED
|
||||
import com.android.settings.PreferenceActionMetricsProvider
|
||||
import com.android.settings.R
|
||||
import com.android.settings.contract.KEY_ADAPTIVE_CONNECTIVITY
|
||||
import com.android.settingslib.datastore.KeyValueStore
|
||||
import com.android.settingslib.datastore.KeyedObservableDelegate
|
||||
import com.android.settingslib.datastore.SettingsSecureStore
|
||||
@@ -31,7 +34,13 @@ import com.android.settingslib.metadata.SensitivityLevel
|
||||
|
||||
// LINT.IfChange
|
||||
class AdaptiveConnectivityTogglePreference :
|
||||
MainSwitchPreference(KEY, R.string.adaptive_connectivity_main_switch_title) {
|
||||
MainSwitchPreference(KEY, R.string.adaptive_connectivity_main_switch_title),
|
||||
PreferenceActionMetricsProvider {
|
||||
|
||||
override val preferenceActionMetrics: Int
|
||||
get() = ACTION_ADAPTIVE_CONNECTIVITY
|
||||
|
||||
override fun tags(context: Context) = arrayOf(KEY_ADAPTIVE_CONNECTIVITY)
|
||||
|
||||
override fun storage(context: Context): KeyValueStore =
|
||||
AdaptiveConnectivityToggleStorage(context, SettingsSecureStore.get(context))
|
||||
|
||||
@@ -35,7 +35,6 @@ import androidx.annotation.VisibleForTesting;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
|
||||
import com.android.internal.telephony.flags.Flags;
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
import com.android.settings.core.SubSettingLauncher;
|
||||
import com.android.settings.network.telephony.CellularSecuritySettingsFragment;
|
||||
@@ -71,8 +70,7 @@ public class CellularSecurityPreferenceController extends BasePreferenceControll
|
||||
|
||||
@Override
|
||||
public int getAvailabilityStatus() {
|
||||
if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY)
|
||||
|| !Flags.enableModemCipherTransparencyUnsolEvents()) {
|
||||
if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
|
||||
return UNSUPPORTED_ON_DEVICE;
|
||||
}
|
||||
if (mTelephonyManager == null) {
|
||||
|
||||
@@ -47,6 +47,8 @@ public class ImsQueryEnhanced4gLteModeUserSetting implements ImsQuery {
|
||||
return imsMmTelManager.isAdvancedCallingSettingEnabled();
|
||||
} catch (IllegalArgumentException exception) {
|
||||
Log.w(LOG_TAG, "fail to get VoLte settings. subId=" + mSubId, exception);
|
||||
} catch (UnsupportedOperationException ex) {
|
||||
// expected on devices without IMS
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -26,7 +26,6 @@ import android.util.Log;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import com.android.internal.telephony.flags.Flags;
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
import com.android.settings.network.SubscriptionUtil;
|
||||
|
||||
@@ -60,9 +59,6 @@ public class CellularSecurityNotificationsDividerController extends
|
||||
|
||||
@Override
|
||||
public int getAvailabilityStatus() {
|
||||
if (!Flags.enableModemCipherTransparencyUnsolEvents()) {
|
||||
return UNSUPPORTED_ON_DEVICE;
|
||||
}
|
||||
if (!isSafetyCenterSupported()) {
|
||||
return UNSUPPORTED_ON_DEVICE;
|
||||
}
|
||||
|
||||
@@ -26,7 +26,6 @@ import android.util.Log;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import com.android.internal.telephony.flags.Flags;
|
||||
import com.android.settings.network.SubscriptionUtil;
|
||||
|
||||
import java.util.List;
|
||||
@@ -75,10 +74,6 @@ public class CellularSecurityNotificationsPreferenceController extends
|
||||
return UNSUPPORTED_ON_DEVICE;
|
||||
}
|
||||
|
||||
if (!areFlagsEnabled()) {
|
||||
return UNSUPPORTED_ON_DEVICE;
|
||||
}
|
||||
|
||||
// Check there are valid SIM cards which can be displayed to the user, otherwise this
|
||||
// setting should not be shown.
|
||||
List<SubscriptionInfo> availableSubs = SubscriptionUtil.getAvailableSubscriptions(mContext);
|
||||
@@ -106,10 +101,6 @@ public class CellularSecurityNotificationsPreferenceController extends
|
||||
*/
|
||||
@Override
|
||||
public boolean isChecked() {
|
||||
if (!areFlagsEnabled()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
// Note: the default behavior for this toggle is disabled (as the underlying
|
||||
// TelephonyManager APIs are disabled by default)
|
||||
@@ -144,11 +135,6 @@ public class CellularSecurityNotificationsPreferenceController extends
|
||||
Log.i(LOG_TAG, "Disabling cellular security notifications.");
|
||||
}
|
||||
|
||||
// Check flag status
|
||||
if (!areFlagsEnabled()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
setNotifications(isChecked);
|
||||
} catch (Exception e) {
|
||||
@@ -177,13 +163,6 @@ public class CellularSecurityNotificationsPreferenceController extends
|
||||
&& mTelephonyManager.isCellularIdentifierDisclosureNotificationsEnabled();
|
||||
}
|
||||
|
||||
private boolean areFlagsEnabled() {
|
||||
if (!Flags.enableModemCipherTransparencyUnsolEvents()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected boolean isSafetyCenterSupported() {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
|
||||
return false;
|
||||
|
||||
@@ -112,9 +112,13 @@ public class Enhanced4gBasePreferenceController extends TelephonyTogglePreferenc
|
||||
return CONDITIONALLY_UNAVAILABLE;
|
||||
}
|
||||
|
||||
try {
|
||||
if (!queryState.isReadyToVoLte()) {
|
||||
return CONDITIONALLY_UNAVAILABLE;
|
||||
}
|
||||
} catch (UnsupportedOperationException ex) {
|
||||
return UNSUPPORTED_ON_DEVICE;
|
||||
}
|
||||
return (isUserControlAllowed(carrierConfig) && queryState.isAllowUserControl())
|
||||
? AVAILABLE : AVAILABLE_UNSEARCHABLE;
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ package com.android.settings.notification
|
||||
import android.Manifest.permission.MODIFY_AUDIO_SETTINGS
|
||||
import android.Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED
|
||||
import android.Manifest.permission.MODIFY_PHONE_STATE
|
||||
import android.app.settings.SettingsEnums.ACTION_CALL_VOLUME
|
||||
import android.content.Context
|
||||
import android.content.pm.PackageManager.FEATURE_AUTOMOTIVE
|
||||
import android.media.AudioManager
|
||||
@@ -26,8 +27,10 @@ import android.media.AudioManager.STREAM_BLUETOOTH_SCO
|
||||
import android.media.AudioManager.STREAM_VOICE_CALL
|
||||
import android.os.UserManager
|
||||
import androidx.preference.Preference
|
||||
import com.android.settings.PreferenceActionMetricsProvider
|
||||
import com.android.settings.PreferenceRestrictionMixin
|
||||
import com.android.settings.R
|
||||
import com.android.settings.contract.KEY_CALL_VOLUME
|
||||
import com.android.settingslib.datastore.KeyValueStore
|
||||
import com.android.settingslib.datastore.NoOpKeyedObservable
|
||||
import com.android.settingslib.datastore.Permissions
|
||||
@@ -44,6 +47,7 @@ import com.android.settingslib.preference.PreferenceBinding
|
||||
open class CallVolumePreference :
|
||||
IntRangeValuePreference,
|
||||
PreferenceBinding,
|
||||
PreferenceActionMetricsProvider,
|
||||
PreferenceAvailabilityProvider,
|
||||
PreferenceIconProvider,
|
||||
PreferenceRestrictionMixin {
|
||||
@@ -53,6 +57,11 @@ open class CallVolumePreference :
|
||||
override val title: Int
|
||||
get() = R.string.call_volume_option_title
|
||||
|
||||
override val preferenceActionMetrics: Int
|
||||
get() = ACTION_CALL_VOLUME
|
||||
|
||||
override fun tags(context: Context) = arrayOf(KEY_CALL_VOLUME)
|
||||
|
||||
override fun getIcon(context: Context) = R.drawable.ic_local_phone_24_lib
|
||||
|
||||
override fun isAvailable(context: Context) =
|
||||
|
||||
@@ -18,13 +18,16 @@ package com.android.settings.notification
|
||||
|
||||
import android.Manifest.permission.MODIFY_AUDIO_SETTINGS
|
||||
import android.Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED
|
||||
import android.app.settings.SettingsEnums.ACTION_MEDIA_VOLUME
|
||||
import android.content.Context
|
||||
import android.content.pm.PackageManager.FEATURE_AUTOMOTIVE
|
||||
import android.media.AudioManager.STREAM_MUSIC
|
||||
import android.os.UserManager
|
||||
import androidx.preference.Preference
|
||||
import com.android.settings.PreferenceActionMetricsProvider
|
||||
import com.android.settings.PreferenceRestrictionMixin
|
||||
import com.android.settings.R
|
||||
import com.android.settings.contract.KEY_MEDIA_VOLUME
|
||||
import com.android.settingslib.datastore.KeyValueStore
|
||||
import com.android.settingslib.datastore.NoOpKeyedObservable
|
||||
import com.android.settingslib.datastore.Permissions
|
||||
@@ -41,6 +44,7 @@ import com.android.settingslib.preference.PreferenceBinding
|
||||
open class MediaVolumePreference :
|
||||
IntRangeValuePreference,
|
||||
PreferenceBinding,
|
||||
PreferenceActionMetricsProvider,
|
||||
PreferenceAvailabilityProvider,
|
||||
PreferenceIconProvider,
|
||||
PreferenceRestrictionMixin {
|
||||
@@ -50,6 +54,11 @@ open class MediaVolumePreference :
|
||||
override val title: Int
|
||||
get() = R.string.media_volume_option_title
|
||||
|
||||
override val preferenceActionMetrics: Int
|
||||
get() = ACTION_MEDIA_VOLUME
|
||||
|
||||
override fun tags(context: Context) = arrayOf(KEY_MEDIA_VOLUME)
|
||||
|
||||
override fun getIcon(context: Context) =
|
||||
when {
|
||||
VolumeHelper.isMuted(context, STREAM_MUSIC) -> R.drawable.ic_media_stream_off
|
||||
|
||||
@@ -21,6 +21,7 @@ import android.Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED
|
||||
import android.app.INotificationManager
|
||||
import android.app.NotificationManager
|
||||
import android.app.NotificationManager.ACTION_EFFECTS_SUPPRESSOR_CHANGED
|
||||
import android.app.settings.SettingsEnums.ACTION_RING_VOLUME
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Context.NOTIFICATION_SERVICE
|
||||
@@ -39,8 +40,10 @@ import android.os.Vibrator
|
||||
import android.service.notification.NotificationListenerService.HINT_HOST_DISABLE_CALL_EFFECTS
|
||||
import android.service.notification.NotificationListenerService.HINT_HOST_DISABLE_EFFECTS
|
||||
import androidx.preference.Preference
|
||||
import com.android.settings.PreferenceActionMetricsProvider
|
||||
import com.android.settings.PreferenceRestrictionMixin
|
||||
import com.android.settings.R
|
||||
import com.android.settings.contract.KEY_RING_VOLUME
|
||||
import com.android.settingslib.datastore.KeyValueStore
|
||||
import com.android.settingslib.datastore.NoOpKeyedObservable
|
||||
import com.android.settingslib.datastore.Permissions
|
||||
@@ -59,6 +62,7 @@ import com.android.settingslib.preference.PreferenceBinding
|
||||
open class SeparateRingVolumePreference :
|
||||
IntRangeValuePreference,
|
||||
PreferenceBinding,
|
||||
PreferenceActionMetricsProvider,
|
||||
PreferenceAvailabilityProvider,
|
||||
PreferenceIconProvider,
|
||||
PreferenceLifecycleProvider,
|
||||
@@ -72,6 +76,11 @@ open class SeparateRingVolumePreference :
|
||||
override val title: Int
|
||||
get() = R.string.separate_ring_volume_option_title
|
||||
|
||||
override val preferenceActionMetrics: Int
|
||||
get() = ACTION_RING_VOLUME
|
||||
|
||||
override fun tags(context: Context) = arrayOf(KEY_RING_VOLUME)
|
||||
|
||||
override fun getIcon(context: Context) = context.getIconRes()
|
||||
|
||||
override fun isAvailable(context: Context) = !createAudioHelper(context).isSingleVolume
|
||||
|
||||
@@ -17,7 +17,8 @@
|
||||
package com.android.settings.wifi.tether
|
||||
|
||||
import android.Manifest
|
||||
import android.app.settings.SettingsEnums
|
||||
import android.app.settings.SettingsEnums.ACTION_WIFI_HOTSPOT
|
||||
import android.app.settings.SettingsEnums.WIFI_TETHER_SETTINGS
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.TetheringManager
|
||||
@@ -27,9 +28,11 @@ import android.net.wifi.WifiManager
|
||||
import android.os.UserManager
|
||||
import android.text.BidiFormatter
|
||||
import android.util.Log
|
||||
import com.android.settings.PreferenceActionMetricsProvider
|
||||
import com.android.settings.PreferenceRestrictionMixin
|
||||
import com.android.settings.R
|
||||
import com.android.settings.Utils
|
||||
import com.android.settings.contract.KEY_WIFI_HOTSPOT
|
||||
import com.android.settings.core.SubSettingLauncher
|
||||
import com.android.settings.datausage.DataSaverMainSwitchPreference.Companion.KEY as DATA_SAVER_KEY
|
||||
import com.android.settings.wifi.WifiUtils.canShowWifiHotspot
|
||||
@@ -56,10 +59,16 @@ import com.android.settingslib.wifi.WifiUtils.Companion.getWifiTetherSummaryForC
|
||||
class WifiHotspotSwitchPreference(context: Context, dataSaverStore: KeyValueStore) :
|
||||
SwitchPreference(KEY, R.string.wifi_hotspot_checkbox_text),
|
||||
PrimarySwitchPreferenceBinding,
|
||||
PreferenceActionMetricsProvider,
|
||||
PreferenceAvailabilityProvider,
|
||||
PreferenceSummaryProvider,
|
||||
PreferenceRestrictionMixin {
|
||||
|
||||
override val preferenceActionMetrics: Int
|
||||
get() = ACTION_WIFI_HOTSPOT
|
||||
|
||||
override fun tags(context: Context) = arrayOf(KEY_WIFI_HOTSPOT)
|
||||
|
||||
private val wifiHotspotStore = WifiHotspotStore(context, dataSaverStore)
|
||||
|
||||
override fun isAvailable(context: Context) =
|
||||
@@ -97,7 +106,7 @@ class WifiHotspotSwitchPreference(context: Context, dataSaverStore: KeyValueStor
|
||||
.apply {
|
||||
setDestination(WifiTetherSettings::class.java.name)
|
||||
setTitleRes(R.string.wifi_hotspot_checkbox_text)
|
||||
setSourceMetricsCategory(SettingsEnums.WIFI_TETHER_SETTINGS)
|
||||
setSourceMetricsCategory(WIFI_TETHER_SETTINGS)
|
||||
}
|
||||
.toIntent()
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.android.settings.bluetooth;
|
||||
|
||||
import static com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast.EXTRA_BT_DEVICE_TO_AUTO_ADD_SOURCE;
|
||||
import static com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast.EXTRA_PAIR_AND_JOIN_SHARING;
|
||||
import static com.android.settingslib.bluetooth.devicesettings.data.repository.DeviceSettingServiceConnection.METADATA_FAST_PAIR_CUSTOMIZED_FIELDS;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
@@ -36,6 +37,7 @@ import static org.robolectric.Shadows.shadowOf;
|
||||
import android.app.Activity;
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.BluetoothLeBroadcastReceiveState;
|
||||
import android.bluetooth.BluetoothProfile;
|
||||
import android.bluetooth.BluetoothStatusCodes;
|
||||
import android.content.Context;
|
||||
@@ -44,6 +46,8 @@ import android.content.res.Resources;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Bundle;
|
||||
import android.os.Looper;
|
||||
import android.platform.test.annotations.DisableFlags;
|
||||
import android.platform.test.annotations.EnableFlags;
|
||||
import android.platform.test.flag.junit.SetFlagsRule;
|
||||
import android.util.Pair;
|
||||
|
||||
@@ -62,9 +66,15 @@ import com.android.settings.testutils.shadow.ShadowAlertDialogCompat;
|
||||
import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
|
||||
import com.android.settings.testutils.shadow.ShadowFragment;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
|
||||
import com.android.settingslib.flags.Flags;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
@@ -112,6 +122,14 @@ public class BluetoothDevicePairingDetailBaseTest {
|
||||
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
|
||||
private LocalBluetoothManager mLocalManager;
|
||||
@Mock
|
||||
private CachedBluetoothDeviceManager mDeviceManager;
|
||||
@Mock
|
||||
private LocalBluetoothProfileManager mProfileManager;
|
||||
@Mock
|
||||
private LocalBluetoothLeBroadcast mBroadcast;
|
||||
@Mock
|
||||
private LocalBluetoothLeBroadcastAssistant mAssistant;
|
||||
@Mock
|
||||
private CachedBluetoothDevice mCachedBluetoothDevice;
|
||||
@Mock
|
||||
private Drawable mDrawable;
|
||||
@@ -197,11 +215,13 @@ public class BluetoothDevicePairingDetailBaseTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onDeviceBondStateChanged_bonded_pairAndJoinSharingDisabled_finish() {
|
||||
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
|
||||
@EnableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
|
||||
@DisableFlags(Flags.FLAG_ENABLE_TEMPORARY_BOND_DEVICES_UI)
|
||||
public void onDeviceBondStateChanged_bonded_notPairInSharing_finish() {
|
||||
when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice);
|
||||
mFragment.mSelectedList.add(mBluetoothDevice);
|
||||
setUpFragmentWithPairAndJoinSharingIntent(false);
|
||||
setUpFragmentWithShareThenPairIntent(false);
|
||||
setUpAudioSharingStates(/* enabled = */ false, /* needSetTempBondMetadata = */ false);
|
||||
mFragment.onDeviceBondStateChanged(mCachedBluetoothDevice, BluetoothDevice.BOND_BONDED);
|
||||
|
||||
verify(mFragment).finish();
|
||||
@@ -209,12 +229,14 @@ public class BluetoothDevicePairingDetailBaseTest {
|
||||
|
||||
@Test
|
||||
@Config(shadows = ShadowDialogFragment.class)
|
||||
public void onDeviceBondStateChanged_bonded_pairAndJoinSharingEnabled_handle() {
|
||||
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
|
||||
@EnableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
|
||||
@DisableFlags(Flags.FLAG_ENABLE_TEMPORARY_BOND_DEVICES_UI)
|
||||
public void onDeviceBondStateChanged_bonded_shareThenPair_handle() {
|
||||
ShadowDialogFragment.reset();
|
||||
when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice);
|
||||
mFragment.mSelectedList.add(mBluetoothDevice);
|
||||
setUpFragmentWithPairAndJoinSharingIntent(true);
|
||||
setUpFragmentWithShareThenPairIntent(true);
|
||||
setUpAudioSharingStates(/* enabled = */ true, /* needSetTempBondMetadata = */ false);
|
||||
mFragment.onDeviceBondStateChanged(mCachedBluetoothDevice, BluetoothDevice.BOND_BONDED);
|
||||
shadowOf(Looper.getMainLooper()).idle();
|
||||
|
||||
@@ -231,11 +253,37 @@ public class BluetoothDevicePairingDetailBaseTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onDeviceBondStateChanged_bonding_pairAndJoinSharingDisabled_doNothing() {
|
||||
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
|
||||
@Config(shadows = ShadowDialogFragment.class)
|
||||
@EnableFlags({Flags.FLAG_ENABLE_LE_AUDIO_SHARING, Flags.FLAG_ENABLE_TEMPORARY_BOND_DEVICES_UI})
|
||||
public void onDeviceBondStateChanged_bonded_pairAfterShare_handle() {
|
||||
ShadowDialogFragment.reset();
|
||||
when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice);
|
||||
mFragment.mSelectedList.add(mBluetoothDevice);
|
||||
setUpFragmentWithPairAndJoinSharingIntent(false);
|
||||
setUpFragmentWithShareThenPairIntent(false);
|
||||
setUpAudioSharingStates(/* enabled = */ true, /* needSetTempBondMetadata = */ true);
|
||||
mFragment.onDeviceBondStateChanged(mCachedBluetoothDevice, BluetoothDevice.BOND_BONDED);
|
||||
shadowOf(Looper.getMainLooper()).idle();
|
||||
|
||||
ProgressDialogFragment progressDialog = mFragment.mProgressDialog;
|
||||
assertThat(progressDialog).isNotNull();
|
||||
assertThat(progressDialog.getMessage()).isEqualTo(
|
||||
mContext.getString(R.string.progress_dialog_connect_device_content,
|
||||
TEST_DEVICE_ADDRESS));
|
||||
assertThat(
|
||||
ShadowDialogFragment.isIsShowing(ProgressDialogFragment.class.getName())).isTrue();
|
||||
verify(mFragment, never()).finish();
|
||||
|
||||
ShadowDialogFragment.reset();
|
||||
}
|
||||
|
||||
@Test
|
||||
@EnableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
|
||||
@DisableFlags(Flags.FLAG_ENABLE_TEMPORARY_BOND_DEVICES_UI)
|
||||
public void onDeviceBondStateChanged_bonding_notPairInSharing_doNothing() {
|
||||
when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice);
|
||||
mFragment.mSelectedList.add(mBluetoothDevice);
|
||||
setUpFragmentWithShareThenPairIntent(false);
|
||||
setUpAudioSharingStates(/* enabled = */ false, /* needSetTempBondMetadata = */ false);
|
||||
mFragment.onDeviceBondStateChanged(mCachedBluetoothDevice, BluetoothDevice.BOND_BONDING);
|
||||
|
||||
verify(mBluetoothAdapter, never()).addOnMetadataChangedListener(any(BluetoothDevice.class),
|
||||
@@ -243,11 +291,13 @@ public class BluetoothDevicePairingDetailBaseTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onDeviceBondStateChanged_bonding_pairAndJoinSharingEnabled_addListener() {
|
||||
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
|
||||
@EnableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
|
||||
@DisableFlags(Flags.FLAG_ENABLE_TEMPORARY_BOND_DEVICES_UI)
|
||||
public void onDeviceBondStateChanged_bonding_shareThenPair_addListener() {
|
||||
when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice);
|
||||
mFragment.mSelectedList.add(mBluetoothDevice);
|
||||
setUpFragmentWithPairAndJoinSharingIntent(true);
|
||||
setUpFragmentWithShareThenPairIntent(true);
|
||||
setUpAudioSharingStates(/* enabled = */ true, /* needSetTempBondMetadata = */ false);
|
||||
mFragment.onDeviceBondStateChanged(mCachedBluetoothDevice, BluetoothDevice.BOND_BONDING);
|
||||
|
||||
verify(mBluetoothAdapter).addOnMetadataChangedListener(eq(mBluetoothDevice),
|
||||
@@ -256,8 +306,22 @@ public class BluetoothDevicePairingDetailBaseTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onDeviceBondStateChanged_unbonded_pairAndJoinSharingDisabled_doNothing() {
|
||||
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
|
||||
@EnableFlags({Flags.FLAG_ENABLE_LE_AUDIO_SHARING, Flags.FLAG_ENABLE_TEMPORARY_BOND_DEVICES_UI})
|
||||
public void onDeviceBondStateChanged_bonding_pairAfterShare_addListener() {
|
||||
when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice);
|
||||
mFragment.mSelectedList.add(mBluetoothDevice);
|
||||
setUpFragmentWithShareThenPairIntent(false);
|
||||
setUpAudioSharingStates(/* enabled = */ true, /* needSetTempBondMetadata = */ true);
|
||||
mFragment.onDeviceBondStateChanged(mCachedBluetoothDevice, BluetoothDevice.BOND_BONDING);
|
||||
|
||||
verify(mBluetoothAdapter).addOnMetadataChangedListener(eq(mBluetoothDevice),
|
||||
any(Executor.class),
|
||||
any(BluetoothAdapter.OnMetadataChangedListener.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisableFlags({Flags.FLAG_ENABLE_LE_AUDIO_SHARING, Flags.FLAG_ENABLE_TEMPORARY_BOND_DEVICES_UI})
|
||||
public void onDeviceBondStateChanged_unbonded_notPairInSharing_doNothing() {
|
||||
when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice);
|
||||
mFragment.mSelectedList.add(mBluetoothDevice);
|
||||
mFragment.onDeviceBondStateChanged(mCachedBluetoothDevice, BluetoothDevice.BOND_NONE);
|
||||
@@ -267,11 +331,13 @@ public class BluetoothDevicePairingDetailBaseTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onDeviceBondStateChanged_unbonded_pairAndJoinSharingEnabled_removeListener() {
|
||||
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
|
||||
@EnableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
|
||||
@DisableFlags(Flags.FLAG_ENABLE_TEMPORARY_BOND_DEVICES_UI)
|
||||
public void onDeviceBondStateChanged_unbonded_shareThenPair_removeListener() {
|
||||
when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice);
|
||||
mFragment.mSelectedList.add(mBluetoothDevice);
|
||||
setUpFragmentWithPairAndJoinSharingIntent(true);
|
||||
setUpFragmentWithShareThenPairIntent(true);
|
||||
setUpAudioSharingStates(/* enabled = */ true, /* needSetTempBondMetadata = */ false);
|
||||
mFragment.onDeviceBondStateChanged(mCachedBluetoothDevice, BluetoothDevice.BOND_BONDING);
|
||||
mFragment.onDeviceBondStateChanged(mCachedBluetoothDevice, BluetoothDevice.BOND_NONE);
|
||||
|
||||
@@ -280,8 +346,23 @@ public class BluetoothDevicePairingDetailBaseTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onProfileConnectionStateChanged_deviceInSelectedListAndConnected_finish() {
|
||||
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
|
||||
@EnableFlags({Flags.FLAG_ENABLE_LE_AUDIO_SHARING, Flags.FLAG_ENABLE_TEMPORARY_BOND_DEVICES_UI})
|
||||
public void onDeviceBondStateChanged_unbonded_pairAfterShare_removeListener() {
|
||||
when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice);
|
||||
mFragment.mSelectedList.add(mBluetoothDevice);
|
||||
setUpFragmentWithShareThenPairIntent(false);
|
||||
setUpAudioSharingStates(/* enabled = */ true, /* needSetTempBondMetadata = */ true);
|
||||
mFragment.onDeviceBondStateChanged(mCachedBluetoothDevice, BluetoothDevice.BOND_BONDING);
|
||||
mFragment.onDeviceBondStateChanged(mCachedBluetoothDevice, BluetoothDevice.BOND_NONE);
|
||||
|
||||
verify(mBluetoothAdapter).removeOnMetadataChangedListener(eq(mBluetoothDevice),
|
||||
any(BluetoothAdapter.OnMetadataChangedListener.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisableFlags({Flags.FLAG_ENABLE_LE_AUDIO_SHARING, Flags.FLAG_ENABLE_TEMPORARY_BOND_DEVICES_UI})
|
||||
public void
|
||||
onProfileConnectionStateChanged_deviceInSelectedListAndConnected_notInSharing_finish() {
|
||||
final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_B);
|
||||
mFragment.mSelectedList.add(mBluetoothDevice);
|
||||
mFragment.mSelectedList.add(device);
|
||||
@@ -291,19 +372,22 @@ public class BluetoothDevicePairingDetailBaseTest {
|
||||
|
||||
mFragment.onProfileConnectionStateChanged(mCachedBluetoothDevice,
|
||||
BluetoothAdapter.STATE_CONNECTED, BluetoothProfile.A2DP);
|
||||
shadowOf(Looper.getMainLooper()).idle();
|
||||
|
||||
verify(mFragment).finish();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Config(shadows = ShadowDialogFragment.class)
|
||||
@EnableFlags({Flags.FLAG_ENABLE_LE_AUDIO_SHARING, Flags.FLAG_ENABLE_TEMPORARY_BOND_DEVICES_UI})
|
||||
public void
|
||||
onProfileConnectionStateChanged_deviceInSelectedListAndConnected_pairAndJoinSharing() {
|
||||
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
|
||||
onProfileConnectionStateChanged_inSelectedListAndConnected_shareThenPair_handle() {
|
||||
ShadowDialogFragment.reset();
|
||||
when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice);
|
||||
mFragment.mSelectedList.add(mBluetoothDevice);
|
||||
setUpFragmentWithPairAndJoinSharingIntent(true);
|
||||
BluetoothDevice device = spy(mBluetoothDevice);
|
||||
when(mCachedBluetoothDevice.getDevice()).thenReturn(device);
|
||||
mFragment.mSelectedList.add(device);
|
||||
setUpFragmentWithShareThenPairIntent(true);
|
||||
setUpAudioSharingStates(/* enabled = */ true, /* needSetTempBondMetadata = */ false);
|
||||
mFragment.onDeviceBondStateChanged(mCachedBluetoothDevice, BluetoothDevice.BOND_BONDED);
|
||||
shadowOf(Looper.getMainLooper()).idle();
|
||||
|
||||
@@ -316,6 +400,7 @@ public class BluetoothDevicePairingDetailBaseTest {
|
||||
BluetoothAdapter.STATE_CONNECTED, BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT);
|
||||
shadowOf(Looper.getMainLooper()).idle();
|
||||
|
||||
verify(device).setMetadata(eq(METADATA_FAST_PAIR_CUSTOMIZED_FIELDS), any());
|
||||
ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
|
||||
verify(mFragment.getActivity()).setResult(eq(Activity.RESULT_OK), captor.capture());
|
||||
Intent intent = captor.getValue();
|
||||
@@ -325,15 +410,44 @@ public class BluetoothDevicePairingDetailBaseTest {
|
||||
BluetoothDevice.class)
|
||||
: null;
|
||||
assertThat(btDevice).isNotNull();
|
||||
assertThat(btDevice).isEqualTo(mBluetoothDevice);
|
||||
assertThat(btDevice).isEqualTo(device);
|
||||
verify(mFragment).finish();
|
||||
|
||||
ShadowDialogFragment.reset();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Config(shadows = ShadowDialogFragment.class)
|
||||
@EnableFlags({Flags.FLAG_ENABLE_LE_AUDIO_SHARING, Flags.FLAG_ENABLE_TEMPORARY_BOND_DEVICES_UI})
|
||||
public void
|
||||
onProfileConnectionStateChanged_inSelectedListAndConnected_pairAfterShare_handle() {
|
||||
ShadowDialogFragment.reset();
|
||||
BluetoothDevice device = spy(mBluetoothDevice);
|
||||
when(mCachedBluetoothDevice.getDevice()).thenReturn(device);
|
||||
mFragment.mSelectedList.add(device);
|
||||
setUpFragmentWithShareThenPairIntent(false);
|
||||
setUpAudioSharingStates(/* enabled = */ true, /* needSetTempBondMetadata = */ true);
|
||||
mFragment.onDeviceBondStateChanged(mCachedBluetoothDevice, BluetoothDevice.BOND_BONDED);
|
||||
shadowOf(Looper.getMainLooper()).idle();
|
||||
|
||||
when(mCachedBluetoothDevice.isConnected()).thenReturn(true);
|
||||
when(mCachedBluetoothDevice.isConnectedLeAudioDevice()).thenReturn(true);
|
||||
when(mCachedBluetoothDevice.isConnectedLeAudioBroadcastAssistantDevice()).thenReturn(true);
|
||||
when(mCachedBluetoothDevice.isConnectedVolumeControlDevice()).thenReturn(true);
|
||||
|
||||
mFragment.onProfileConnectionStateChanged(mCachedBluetoothDevice,
|
||||
BluetoothAdapter.STATE_CONNECTED, BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT);
|
||||
shadowOf(Looper.getMainLooper()).idle();
|
||||
|
||||
verify(device).setMetadata(eq(METADATA_FAST_PAIR_CUSTOMIZED_FIELDS), any());
|
||||
verify(mFragment).finish();
|
||||
|
||||
ShadowDialogFragment.reset();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisableFlags({Flags.FLAG_ENABLE_LE_AUDIO_SHARING, Flags.FLAG_ENABLE_TEMPORARY_BOND_DEVICES_UI})
|
||||
public void onProfileConnectionStateChanged_deviceNotInSelectedList_doNothing() {
|
||||
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
|
||||
final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_B);
|
||||
mFragment.mSelectedList.add(device);
|
||||
|
||||
@@ -347,8 +461,8 @@ public class BluetoothDevicePairingDetailBaseTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisableFlags({Flags.FLAG_ENABLE_LE_AUDIO_SHARING, Flags.FLAG_ENABLE_TEMPORARY_BOND_DEVICES_UI})
|
||||
public void onProfileConnectionStateChanged_deviceDisconnected_doNothing() {
|
||||
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
|
||||
final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_B);
|
||||
mFragment.mSelectedList.add(mBluetoothDevice);
|
||||
mFragment.mSelectedList.add(device);
|
||||
@@ -363,8 +477,8 @@ public class BluetoothDevicePairingDetailBaseTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisableFlags({Flags.FLAG_ENABLE_LE_AUDIO_SHARING, Flags.FLAG_ENABLE_TEMPORARY_BOND_DEVICES_UI})
|
||||
public void onProfileConnectionStateChanged_deviceInPreferenceMapAndConnected_removed() {
|
||||
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
|
||||
final BluetoothDevicePreference preference =
|
||||
new BluetoothDevicePreference(mContext, mCachedBluetoothDevice,
|
||||
true, BluetoothDevicePreference.SortType.TYPE_FIFO);
|
||||
@@ -381,8 +495,8 @@ public class BluetoothDevicePairingDetailBaseTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisableFlags({Flags.FLAG_ENABLE_LE_AUDIO_SHARING, Flags.FLAG_ENABLE_TEMPORARY_BOND_DEVICES_UI})
|
||||
public void onProfileConnectionStateChanged_deviceNotInPreferenceMap_doNothing() {
|
||||
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
|
||||
final CachedBluetoothDevice cachedDevice = mock(CachedBluetoothDevice.class);
|
||||
final BluetoothDevicePreference preference =
|
||||
new BluetoothDevicePreference(mContext, mCachedBluetoothDevice,
|
||||
@@ -404,9 +518,9 @@ public class BluetoothDevicePairingDetailBaseTest {
|
||||
// not crash
|
||||
}
|
||||
|
||||
private void setUpFragmentWithPairAndJoinSharingIntent(boolean enablePairAndJoinSharing) {
|
||||
private void setUpFragmentWithShareThenPairIntent(boolean enableShareThenPair) {
|
||||
Bundle args = new Bundle();
|
||||
args.putBoolean(EXTRA_PAIR_AND_JOIN_SHARING, enablePairAndJoinSharing);
|
||||
args.putBoolean(EXTRA_PAIR_AND_JOIN_SHARING, enableShareThenPair);
|
||||
Intent intent = new Intent();
|
||||
intent.putExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT_ARGUMENTS, args);
|
||||
FragmentActivity activity = spy(Robolectric.setupActivity(FragmentActivity.class));
|
||||
@@ -420,8 +534,39 @@ public class BluetoothDevicePairingDetailBaseTest {
|
||||
Lifecycle lifecycle = mock(Lifecycle.class);
|
||||
when(lifecycle.getCurrentState()).thenReturn(Lifecycle.State.RESUMED);
|
||||
doReturn(lifecycle).when(mFragment).getLifecycle();
|
||||
mFragment.mShouldTriggerAudioSharingShareThenPairFlow =
|
||||
mFragment.shouldTriggerAudioSharingShareThenPairFlow();
|
||||
mFragment.mShouldTriggerShareThenPairFlow = mFragment.shouldTriggerShareThenPairFlow();
|
||||
}
|
||||
|
||||
private void setUpAudioSharingStates(boolean enabled, boolean needSetTempBondMetadata) {
|
||||
when(mLocalManager.getProfileManager()).thenReturn(mProfileManager);
|
||||
when(mProfileManager.getLeAudioBroadcastProfile()).thenReturn(mBroadcast);
|
||||
when(mProfileManager.getLeAudioBroadcastAssistantProfile()).thenReturn(mAssistant);
|
||||
when(mLocalManager.getCachedDeviceManager()).thenReturn(mDeviceManager);
|
||||
if (!enabled) {
|
||||
when(mBroadcast.isEnabled(null)).thenReturn(false);
|
||||
} else {
|
||||
when(mBroadcast.isEnabled(null)).thenReturn(true);
|
||||
when(mBroadcast.getLatestBroadcastId()).thenReturn(1);
|
||||
BluetoothDevice device1 = mock(BluetoothDevice.class);
|
||||
CachedBluetoothDevice cachedDevice1 = mock(CachedBluetoothDevice.class);
|
||||
when(mDeviceManager.findDevice(device1)).thenReturn(cachedDevice1);
|
||||
when(cachedDevice1.getGroupId()).thenReturn(1);
|
||||
when(cachedDevice1.getDevice()).thenReturn(device1);
|
||||
BluetoothLeBroadcastReceiveState state = mock(BluetoothLeBroadcastReceiveState.class);
|
||||
when(state.getBroadcastId()).thenReturn(1);
|
||||
when(mAssistant.getAllSources(any())).thenReturn(ImmutableList.of(state));
|
||||
if (needSetTempBondMetadata) {
|
||||
when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of(device1));
|
||||
} else {
|
||||
BluetoothDevice device2 = mock(BluetoothDevice.class);
|
||||
CachedBluetoothDevice cachedDevice2 = mock(CachedBluetoothDevice.class);
|
||||
when(mDeviceManager.findDevice(device2)).thenReturn(cachedDevice2);
|
||||
when(cachedDevice2.getGroupId()).thenReturn(2);
|
||||
when(cachedDevice2.getDevice()).thenReturn(device2);
|
||||
when(mAssistant.getAllConnectedDevices()).thenReturn(
|
||||
ImmutableList.of(device1, device2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class TestBluetoothDevicePairingDetailBase extends
|
||||
|
||||
@@ -15,6 +15,9 @@
|
||||
*/
|
||||
package com.android.settings.bluetooth;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
@@ -22,34 +25,72 @@ import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.BluetoothLeBroadcastReceiveState;
|
||||
import android.content.Context;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.settings.testutils.FakeFeatureFactory;
|
||||
import com.android.settings.testutils.shadow.ShadowBluetoothUtils;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
|
||||
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Answers;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.mockito.junit.MockitoJUnit;
|
||||
import org.mockito.junit.MockitoRule;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Config(shadows = {ShadowBluetoothUtils.class})
|
||||
public class UtilsTest {
|
||||
|
||||
private static final int METADATA_FAST_PAIR_CUSTOMIZED_FIELDS = 25;
|
||||
private static final String TEMP_BOND_METADATA =
|
||||
"<TEMP_BOND_TYPE>le_audio_sharing</TEMP_BOND_TYPE>";
|
||||
@Rule
|
||||
public final MockitoRule mMockitoRule = MockitoJUnit.rule();
|
||||
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
|
||||
private Context mContext;
|
||||
@Mock
|
||||
private LocalBluetoothManager mLocalBtManager;
|
||||
@Mock
|
||||
private LocalBluetoothProfileManager mProfileManager;
|
||||
@Mock
|
||||
private LocalBluetoothLeBroadcast mBroadcast;
|
||||
@Mock
|
||||
private LocalBluetoothLeBroadcastAssistant mAssistant;
|
||||
@Mock
|
||||
private CachedBluetoothDeviceManager mDeviceManager;
|
||||
|
||||
private MetricsFeatureProvider mMetricsFeatureProvider;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
mMetricsFeatureProvider = FakeFeatureFactory.setupForTest().getMetricsFeatureProvider();
|
||||
ShadowBluetoothUtils.sLocalBluetoothManager = mLocalBtManager;
|
||||
mLocalBtManager = Utils.getLocalBtManager(mContext);
|
||||
when(mLocalBtManager.getProfileManager()).thenReturn(mProfileManager);
|
||||
when(mLocalBtManager.getCachedDeviceManager()).thenReturn(mDeviceManager);
|
||||
when(mProfileManager.getLeAudioBroadcastProfile()).thenReturn(mBroadcast);
|
||||
when(mProfileManager.getLeAudioBroadcastAssistantProfile()).thenReturn(mAssistant);
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
ShadowBluetoothUtils.reset();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -60,4 +101,65 @@ public class UtilsTest {
|
||||
verify(mMetricsFeatureProvider).visible(eq(mContext), anyInt(),
|
||||
eq(MetricsEvent.ACTION_SETTINGS_BLUETOOTH_CONNECT_ERROR), anyInt());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldBlockPairingInAudioSharing_broadcastOff_returnFalse() {
|
||||
when(mBroadcast.isEnabled(null)).thenReturn(false);
|
||||
assertThat(Utils.shouldBlockPairingInAudioSharing(mLocalBtManager)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldBlockPairingInAudioSharing_singlePermanentBondSinkInSharing_returnFalse() {
|
||||
when(mBroadcast.isEnabled(null)).thenReturn(true);
|
||||
when(mBroadcast.getLatestBroadcastId()).thenReturn(1);
|
||||
BluetoothDevice device = mock(BluetoothDevice.class);
|
||||
CachedBluetoothDevice cachedDevice = mock(CachedBluetoothDevice.class);
|
||||
when(mDeviceManager.findDevice(device)).thenReturn(cachedDevice);
|
||||
when(cachedDevice.getGroupId()).thenReturn(1);
|
||||
when(cachedDevice.getDevice()).thenReturn(device);
|
||||
when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of(device));
|
||||
BluetoothLeBroadcastReceiveState state = mock(BluetoothLeBroadcastReceiveState.class);
|
||||
when(state.getBroadcastId()).thenReturn(1);
|
||||
when(mAssistant.getAllSources(device)).thenReturn(ImmutableList.of(state));
|
||||
assertThat(Utils.shouldBlockPairingInAudioSharing(mLocalBtManager)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldBlockPairingInAudioSharing_singleTempBondSinkInSharing_returnTrue() {
|
||||
when(mBroadcast.isEnabled(null)).thenReturn(true);
|
||||
when(mBroadcast.getLatestBroadcastId()).thenReturn(1);
|
||||
BluetoothDevice device = mock(BluetoothDevice.class);
|
||||
CachedBluetoothDevice cachedDevice = mock(CachedBluetoothDevice.class);
|
||||
when(mDeviceManager.findDevice(device)).thenReturn(cachedDevice);
|
||||
when(cachedDevice.getGroupId()).thenReturn(1);
|
||||
when(cachedDevice.getDevice()).thenReturn(device);
|
||||
when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of(device));
|
||||
BluetoothLeBroadcastReceiveState state = mock(BluetoothLeBroadcastReceiveState.class);
|
||||
when(state.getBroadcastId()).thenReturn(1);
|
||||
when(mAssistant.getAllSources(device)).thenReturn(ImmutableList.of(state));
|
||||
when(device.getMetadata(METADATA_FAST_PAIR_CUSTOMIZED_FIELDS))
|
||||
.thenReturn(TEMP_BOND_METADATA.getBytes());
|
||||
assertThat(Utils.shouldBlockPairingInAudioSharing(mLocalBtManager)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldBlockPairingInAudioSharing_twoSinksInSharing_returnTrue() {
|
||||
when(mBroadcast.isEnabled(null)).thenReturn(true);
|
||||
when(mBroadcast.getLatestBroadcastId()).thenReturn(1);
|
||||
BluetoothDevice device1 = mock(BluetoothDevice.class);
|
||||
BluetoothDevice device2 = mock(BluetoothDevice.class);
|
||||
CachedBluetoothDevice cachedDevice1 = mock(CachedBluetoothDevice.class);
|
||||
CachedBluetoothDevice cachedDevice2 = mock(CachedBluetoothDevice.class);
|
||||
when(mDeviceManager.findDevice(device1)).thenReturn(cachedDevice1);
|
||||
when(mDeviceManager.findDevice(device2)).thenReturn(cachedDevice2);
|
||||
when(cachedDevice1.getGroupId()).thenReturn(1);
|
||||
when(cachedDevice2.getGroupId()).thenReturn(2);
|
||||
when(cachedDevice1.getDevice()).thenReturn(device1);
|
||||
when(cachedDevice2.getDevice()).thenReturn(device2);
|
||||
when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of(device1, device2));
|
||||
BluetoothLeBroadcastReceiveState state = mock(BluetoothLeBroadcastReceiveState.class);
|
||||
when(state.getBroadcastId()).thenReturn(1);
|
||||
when(mAssistant.getAllSources(any())).thenReturn(ImmutableList.of(state));
|
||||
assertThat(Utils.shouldBlockPairingInAudioSharing(mLocalBtManager)).isTrue();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,19 +17,10 @@ package com.android.settings.connecteddevice.display;
|
||||
|
||||
import static android.view.Display.INVALID_DISPLAY;
|
||||
|
||||
import static com.android.settings.connecteddevice.display.ExternalDisplayPreferenceFragment.DISPLAYS_LIST_PREFERENCE_KEY;
|
||||
import static com.android.settings.connecteddevice.display.ExternalDisplayPreferenceFragment.EXTERNAL_DISPLAY_CHANGE_RESOLUTION_FOOTER_RESOURCE;
|
||||
import static com.android.settings.connecteddevice.display.ExternalDisplayPreferenceFragment.EXTERNAL_DISPLAY_NOT_FOUND_FOOTER_RESOURCE;
|
||||
import static com.android.settings.connecteddevice.display.ExternalDisplayPreferenceFragment.EXTERNAL_DISPLAY_RESOLUTION_PREFERENCE_KEY;
|
||||
import static com.android.settings.connecteddevice.display.ExternalDisplayPreferenceFragment.EXTERNAL_DISPLAY_RESOLUTION_TITLE_RESOURCE;
|
||||
import static com.android.settings.connecteddevice.display.ExternalDisplayPreferenceFragment.EXTERNAL_DISPLAY_ROTATION_KEY;
|
||||
import static com.android.settings.connecteddevice.display.ExternalDisplayPreferenceFragment.EXTERNAL_DISPLAY_ROTATION_TITLE_RESOURCE;
|
||||
import static com.android.settings.connecteddevice.display.ExternalDisplayPreferenceFragment.EXTERNAL_DISPLAY_SETTINGS_RESOURCE;
|
||||
import static com.android.settings.connecteddevice.display.ExternalDisplayPreferenceFragment.EXTERNAL_DISPLAY_SIZE_PREFERENCE_KEY;
|
||||
import static com.android.settings.connecteddevice.display.ExternalDisplayPreferenceFragment.EXTERNAL_DISPLAY_SIZE_SUMMARY_RESOURCE;
|
||||
import static com.android.settings.connecteddevice.display.ExternalDisplayPreferenceFragment.EXTERNAL_DISPLAY_SIZE_TITLE_RESOURCE;
|
||||
import static com.android.settings.connecteddevice.display.ExternalDisplayPreferenceFragment.EXTERNAL_DISPLAY_USE_PREFERENCE_KEY;
|
||||
import static com.android.settings.connecteddevice.display.ExternalDisplayPreferenceFragment.EXTERNAL_DISPLAY_USE_TITLE_RESOURCE;
|
||||
import static com.android.settings.connecteddevice.display.ExternalDisplayPreferenceFragment.PREVIOUSLY_SHOWN_LIST_KEY;
|
||||
import static com.android.settings.flags.Flags.FLAG_DISPLAY_SIZE_CONNECTED_DISPLAY_SETTING;
|
||||
import static com.android.settings.flags.Flags.FLAG_DISPLAY_TOPOLOGY_PANE_IN_DISPLAY_LIST;
|
||||
@@ -61,6 +52,7 @@ import androidx.test.annotation.UiThreadTest;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import com.android.settings.connecteddevice.display.ExternalDisplayPreferenceFragment.DisplayPreference;
|
||||
import com.android.settings.connecteddevice.display.ExternalDisplayPreferenceFragment.PrefBasics;
|
||||
import com.android.settingslib.widget.FooterPreference;
|
||||
import com.android.settingslib.widget.MainSwitchPreference;
|
||||
|
||||
@@ -97,23 +89,22 @@ public class ExternalDisplayPreferenceFragmentTest extends ExternalDisplayTestBa
|
||||
fragment.onSaveInstanceStateCallback(outState);
|
||||
assertThat(outState.getBoolean(PREVIOUSLY_SHOWN_LIST_KEY)).isFalse();
|
||||
assertThat(mHandler.getPendingMessages().size()).isEqualTo(1);
|
||||
PreferenceCategory pref = mPreferenceScreen.findPreference(DISPLAYS_LIST_PREFERENCE_KEY);
|
||||
PreferenceCategory pref = mPreferenceScreen.findPreference(PrefBasics.DISPLAYS_LIST.key);
|
||||
assertThat(pref).isNull();
|
||||
verify(mMockedInjector, never()).getAllDisplays();
|
||||
mHandler.flush();
|
||||
assertThat(mHandler.getPendingMessages().size()).isEqualTo(0);
|
||||
verify(mMockedInjector).getAllDisplays();
|
||||
pref = mPreferenceScreen.findPreference(DISPLAYS_LIST_PREFERENCE_KEY);
|
||||
pref = mPreferenceScreen.findPreference(PrefBasics.DISPLAYS_LIST.key);
|
||||
assertThat(pref).isNotNull();
|
||||
assertThat(pref.getPreferenceCount()).isEqualTo(2);
|
||||
fragment.onSaveInstanceStateCallback(outState);
|
||||
assertThat(outState.getBoolean(PREVIOUSLY_SHOWN_LIST_KEY)).isTrue();
|
||||
|
||||
pref = mPreferenceScreen.findPreference(DisplayTopologyKt.TOPOLOGY_PREFERENCE_KEY);
|
||||
pref = mPreferenceScreen.findPreference(PrefBasics.DISPLAY_TOPOLOGY.key);
|
||||
assertThat(pref).isNull();
|
||||
|
||||
pref = mPreferenceScreen.findPreference(
|
||||
ExternalDisplayPreferenceFragment.BUILTIN_DISPLAY_LIST_PREFERENCE_KEY);
|
||||
pref = mPreferenceScreen.findPreference(PrefBasics.BUILTIN_DISPLAY_LIST.key);
|
||||
assertThat(pref).isNull();
|
||||
}
|
||||
|
||||
@@ -126,56 +117,51 @@ public class ExternalDisplayPreferenceFragmentTest extends ExternalDisplayTestBa
|
||||
doReturn(new Display[] {mDisplays[1]}).when(mMockedInjector).getAllDisplays();
|
||||
mHandler.flush();
|
||||
|
||||
var pref = mPreferenceScreen.findPreference(DisplayTopologyKt.TOPOLOGY_PREFERENCE_KEY);
|
||||
var pref = mPreferenceScreen.findPreference(PrefBasics.DISPLAY_TOPOLOGY.key);
|
||||
assertThat(pref).isNotNull();
|
||||
pref = mPreferenceScreen.findPreference(MirroringKt.MIRROR_PREFERENCE_KEY);
|
||||
pref = mPreferenceScreen.findPreference(PrefBasics.MIRROR.key);
|
||||
assertThat(pref).isNotNull();
|
||||
|
||||
PreferenceCategory listPref =
|
||||
mPreferenceScreen.findPreference(DISPLAYS_LIST_PREFERENCE_KEY);
|
||||
assertThat(listPref).isNotNull();
|
||||
assertThat(listPref.getPreferenceCount()).isEqualTo(1);
|
||||
|
||||
listPref = mPreferenceScreen.findPreference(
|
||||
ExternalDisplayPreferenceFragment.BUILTIN_DISPLAY_LIST_PREFERENCE_KEY);
|
||||
assertThat(listPref).isNotNull();
|
||||
assertThat(listPref.getPreferenceCount()).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@UiThreadTest
|
||||
public void testShowDisplayListWithPane_NoExternalDisplays() {
|
||||
mFlags.setFlag(FLAG_DISPLAY_TOPOLOGY_PANE_IN_DISPLAY_LIST, true);
|
||||
|
||||
initFragment();
|
||||
doReturn(new Display[0]).when(mMockedInjector).getAllDisplays();
|
||||
mHandler.flush();
|
||||
|
||||
var pref = mPreferenceScreen.findPreference(DisplayTopologyKt.TOPOLOGY_PREFERENCE_KEY);
|
||||
assertThat(pref).isNotNull();
|
||||
pref = mPreferenceScreen.findPreference(MirroringKt.MIRROR_PREFERENCE_KEY);
|
||||
pref = mPreferenceScreen.findPreference(PrefBasics.DISPLAYS_LIST.key);
|
||||
assertThat(pref).isNull();
|
||||
|
||||
PreferenceCategory listPref =
|
||||
mPreferenceScreen.findPreference(DISPLAYS_LIST_PREFERENCE_KEY);
|
||||
assertThat(listPref).isNull();
|
||||
|
||||
listPref = mPreferenceScreen.findPreference(
|
||||
ExternalDisplayPreferenceFragment.BUILTIN_DISPLAY_LIST_PREFERENCE_KEY);
|
||||
assertThat(listPref).isNotNull();
|
||||
assertThat(listPref.getPreferenceCount()).isEqualTo(1);
|
||||
mPreferenceScreen.findPreference(PrefBasics.BUILTIN_DISPLAY_LIST.key);
|
||||
var builtinPref = listPref.getPreference(0);
|
||||
assertThat(builtinPref.getOnPreferenceClickListener().onPreferenceClick(builtinPref))
|
||||
.isTrue();
|
||||
assertThat(mLaunchedBuiltinSettings).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@UiThreadTest
|
||||
public void testDontShowDisplayListOrPane_NoExternalDisplays() {
|
||||
mFlags.setFlag(FLAG_DISPLAY_TOPOLOGY_PANE_IN_DISPLAY_LIST, true);
|
||||
|
||||
initFragment();
|
||||
doReturn(new Display[0]).when(mMockedInjector).getAllDisplays();
|
||||
mHandler.flush();
|
||||
|
||||
// When no external display is attached, interactive preferences are omitted.
|
||||
var pref = mPreferenceScreen.findPreference(PrefBasics.DISPLAY_TOPOLOGY.key);
|
||||
assertThat(pref).isNull();
|
||||
pref = mPreferenceScreen.findPreference(PrefBasics.MIRROR.key);
|
||||
assertThat(pref).isNull();
|
||||
|
||||
PreferenceCategory listPref =
|
||||
mPreferenceScreen.findPreference(PrefBasics.DISPLAYS_LIST.key);
|
||||
assertThat(listPref).isNull();
|
||||
|
||||
listPref = mPreferenceScreen.findPreference(PrefBasics.BUILTIN_DISPLAY_LIST.key);
|
||||
assertThat(listPref).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@UiThreadTest
|
||||
public void testLaunchDisplaySettingFromList() {
|
||||
initFragment();
|
||||
mHandler.flush();
|
||||
PreferenceCategory pref = mPreferenceScreen.findPreference(DISPLAYS_LIST_PREFERENCE_KEY);
|
||||
PreferenceCategory pref = mPreferenceScreen.findPreference(PrefBasics.DISPLAYS_LIST.key);
|
||||
assertThat(pref).isNotNull();
|
||||
var display1Category = (PreferenceCategory) pref.getPreference(0);
|
||||
var display1Pref = (DisplayPreference) display1Category.getPreference(0);
|
||||
@@ -204,7 +190,7 @@ public class ExternalDisplayPreferenceFragmentTest extends ExternalDisplayTestBa
|
||||
// Only one display available
|
||||
doReturn(new Display[] {mDisplays[1]}).when(mMockedInjector).getAllDisplays();
|
||||
mHandler.flush();
|
||||
PreferenceCategory pref = mPreferenceScreen.findPreference(DISPLAYS_LIST_PREFERENCE_KEY);
|
||||
PreferenceCategory pref = mPreferenceScreen.findPreference(PrefBasics.DISPLAYS_LIST.key);
|
||||
assertThat(pref).isNotNull();
|
||||
assertThat(pref.getPreferenceCount()).isEqualTo(1);
|
||||
}
|
||||
@@ -219,15 +205,15 @@ public class ExternalDisplayPreferenceFragmentTest extends ExternalDisplayTestBa
|
||||
// Init
|
||||
initFragment();
|
||||
mHandler.flush();
|
||||
PreferenceCategory list = mPreferenceScreen.findPreference(DISPLAYS_LIST_PREFERENCE_KEY);
|
||||
PreferenceCategory list = mPreferenceScreen.findPreference(PrefBasics.DISPLAYS_LIST.key);
|
||||
assertThat(list).isNull();
|
||||
var pref = mPreferenceScreen.findPreference(EXTERNAL_DISPLAY_RESOLUTION_PREFERENCE_KEY);
|
||||
var pref = mPreferenceScreen.findPreference(PrefBasics.EXTERNAL_DISPLAY_RESOLUTION.key);
|
||||
assertThat(pref).isNotNull();
|
||||
pref = mPreferenceScreen.findPreference(EXTERNAL_DISPLAY_ROTATION_KEY);
|
||||
pref = mPreferenceScreen.findPreference(PrefBasics.EXTERNAL_DISPLAY_ROTATION.key);
|
||||
assertThat(pref).isNotNull();
|
||||
var footerPref = (FooterPreference) mPreferenceScreen.findPreference(KEY_FOOTER);
|
||||
assertThat(footerPref).isNotNull();
|
||||
var sizePref = mPreferenceScreen.findPreference(EXTERNAL_DISPLAY_SIZE_PREFERENCE_KEY);
|
||||
var sizePref = mPreferenceScreen.findPreference(PrefBasics.EXTERNAL_DISPLAY_SIZE.key);
|
||||
assertThat(sizePref).isNull();
|
||||
verify(footerPref).setTitle(EXTERNAL_DISPLAY_CHANGE_RESOLUTION_FOOTER_RESOURCE);
|
||||
}
|
||||
@@ -241,15 +227,15 @@ public class ExternalDisplayPreferenceFragmentTest extends ExternalDisplayTestBa
|
||||
// Init
|
||||
initFragment();
|
||||
mHandler.flush();
|
||||
PreferenceCategory list = mPreferenceScreen.findPreference(DISPLAYS_LIST_PREFERENCE_KEY);
|
||||
PreferenceCategory list = mPreferenceScreen.findPreference(PrefBasics.DISPLAYS_LIST.key);
|
||||
assertThat(list).isNull();
|
||||
var pref = mPreferenceScreen.findPreference(EXTERNAL_DISPLAY_RESOLUTION_PREFERENCE_KEY);
|
||||
var pref = mPreferenceScreen.findPreference(PrefBasics.EXTERNAL_DISPLAY_RESOLUTION.key);
|
||||
assertThat(pref).isNotNull();
|
||||
pref = mPreferenceScreen.findPreference(EXTERNAL_DISPLAY_ROTATION_KEY);
|
||||
pref = mPreferenceScreen.findPreference(PrefBasics.EXTERNAL_DISPLAY_ROTATION.key);
|
||||
assertThat(pref).isNotNull();
|
||||
var footerPref = (FooterPreference) mPreferenceScreen.findPreference(KEY_FOOTER);
|
||||
assertThat(footerPref).isNotNull();
|
||||
var sizePref = mPreferenceScreen.findPreference(EXTERNAL_DISPLAY_SIZE_PREFERENCE_KEY);
|
||||
var sizePref = mPreferenceScreen.findPreference(PrefBasics.EXTERNAL_DISPLAY_SIZE.key);
|
||||
assertThat(sizePref).isNotNull();
|
||||
verify(footerPref).setTitle(EXTERNAL_DISPLAY_CHANGE_RESOLUTION_FOOTER_RESOURCE);
|
||||
}
|
||||
@@ -263,13 +249,13 @@ public class ExternalDisplayPreferenceFragmentTest extends ExternalDisplayTestBa
|
||||
verify(mMockedInjector, never()).getDisplay(anyInt());
|
||||
mHandler.flush();
|
||||
verify(mMockedInjector).getDisplay(mDisplayIdArg);
|
||||
var pref = mPreferenceScreen.findPreference(EXTERNAL_DISPLAY_RESOLUTION_PREFERENCE_KEY);
|
||||
var pref = mPreferenceScreen.findPreference(PrefBasics.EXTERNAL_DISPLAY_RESOLUTION.key);
|
||||
assertThat(pref).isNotNull();
|
||||
pref = mPreferenceScreen.findPreference(EXTERNAL_DISPLAY_ROTATION_KEY);
|
||||
pref = mPreferenceScreen.findPreference(PrefBasics.EXTERNAL_DISPLAY_ROTATION.key);
|
||||
assertThat(pref).isNotNull();
|
||||
var footerPref = (FooterPreference) mPreferenceScreen.findPreference(KEY_FOOTER);
|
||||
assertThat(footerPref).isNotNull();
|
||||
var sizePref = mPreferenceScreen.findPreference(EXTERNAL_DISPLAY_SIZE_PREFERENCE_KEY);
|
||||
var sizePref = mPreferenceScreen.findPreference(PrefBasics.EXTERNAL_DISPLAY_SIZE.key);
|
||||
assertThat(sizePref).isNotNull();
|
||||
verify(footerPref).setTitle(EXTERNAL_DISPLAY_CHANGE_RESOLUTION_FOOTER_RESOURCE);
|
||||
}
|
||||
@@ -283,20 +269,20 @@ public class ExternalDisplayPreferenceFragmentTest extends ExternalDisplayTestBa
|
||||
mHandler.flush();
|
||||
verify(mMockedInjector).getDisplay(mDisplayIdArg);
|
||||
var mainPref = (MainSwitchPreference) mPreferenceScreen.findPreference(
|
||||
EXTERNAL_DISPLAY_USE_PREFERENCE_KEY);
|
||||
PrefBasics.EXTERNAL_DISPLAY_USE.key);
|
||||
assertThat(mainPref).isNotNull();
|
||||
assertThat("" + mainPref.getTitle()).isEqualTo(
|
||||
getText(EXTERNAL_DISPLAY_USE_TITLE_RESOURCE));
|
||||
getText(PrefBasics.EXTERNAL_DISPLAY_USE.titleResource));
|
||||
assertThat(mainPref.isChecked()).isFalse();
|
||||
assertThat(mainPref.isEnabled()).isTrue();
|
||||
assertThat(mainPref.getOnPreferenceChangeListener()).isNotNull();
|
||||
var pref = mPreferenceScreen.findPreference(EXTERNAL_DISPLAY_RESOLUTION_PREFERENCE_KEY);
|
||||
var pref = mPreferenceScreen.findPreference(PrefBasics.EXTERNAL_DISPLAY_RESOLUTION.key);
|
||||
assertThat(pref).isNull();
|
||||
pref = mPreferenceScreen.findPreference(EXTERNAL_DISPLAY_ROTATION_KEY);
|
||||
pref = mPreferenceScreen.findPreference(PrefBasics.EXTERNAL_DISPLAY_ROTATION.key);
|
||||
assertThat(pref).isNull();
|
||||
var footerPref = (FooterPreference) mPreferenceScreen.findPreference(KEY_FOOTER);
|
||||
assertThat(footerPref).isNull();
|
||||
var sizePref = mPreferenceScreen.findPreference(EXTERNAL_DISPLAY_SIZE_PREFERENCE_KEY);
|
||||
var sizePref = mPreferenceScreen.findPreference(PrefBasics.EXTERNAL_DISPLAY_SIZE.key);
|
||||
assertThat(sizePref).isNull();
|
||||
}
|
||||
|
||||
@@ -307,10 +293,10 @@ public class ExternalDisplayPreferenceFragmentTest extends ExternalDisplayTestBa
|
||||
initFragment();
|
||||
mHandler.flush();
|
||||
var mainPref = (MainSwitchPreference) mPreferenceScreen.findPreference(
|
||||
EXTERNAL_DISPLAY_USE_PREFERENCE_KEY);
|
||||
PrefBasics.EXTERNAL_DISPLAY_USE.key);
|
||||
assertThat(mainPref).isNotNull();
|
||||
assertThat("" + mainPref.getTitle()).isEqualTo(
|
||||
getText(EXTERNAL_DISPLAY_USE_TITLE_RESOURCE));
|
||||
getText(PrefBasics.EXTERNAL_DISPLAY_USE.titleResource));
|
||||
assertThat(mainPref.isChecked()).isFalse();
|
||||
assertThat(mainPref.isEnabled()).isFalse();
|
||||
assertThat(mainPref.getOnPreferenceChangeListener()).isNull();
|
||||
@@ -327,9 +313,9 @@ public class ExternalDisplayPreferenceFragmentTest extends ExternalDisplayTestBa
|
||||
var fragment = initFragment();
|
||||
mHandler.flush();
|
||||
var pref = fragment.getRotationPreference(mContext);
|
||||
assertThat(pref.getKey()).isEqualTo(EXTERNAL_DISPLAY_ROTATION_KEY);
|
||||
assertThat(pref.getKey()).isEqualTo(PrefBasics.EXTERNAL_DISPLAY_ROTATION.key);
|
||||
assertThat("" + pref.getTitle()).isEqualTo(
|
||||
getText(EXTERNAL_DISPLAY_ROTATION_TITLE_RESOURCE));
|
||||
getText(PrefBasics.EXTERNAL_DISPLAY_ROTATION.titleResource));
|
||||
assertThat(pref.getEntries().length).isEqualTo(4);
|
||||
assertThat(pref.getEntryValues().length).isEqualTo(4);
|
||||
assertThat(pref.getEntryValues()[0].toString()).isEqualTo("0");
|
||||
@@ -359,9 +345,9 @@ public class ExternalDisplayPreferenceFragmentTest extends ExternalDisplayTestBa
|
||||
var fragment = initFragment();
|
||||
mHandler.flush();
|
||||
var pref = fragment.getResolutionPreference(mContext);
|
||||
assertThat(pref.getKey()).isEqualTo(EXTERNAL_DISPLAY_RESOLUTION_PREFERENCE_KEY);
|
||||
assertThat(pref.getKey()).isEqualTo(PrefBasics.EXTERNAL_DISPLAY_RESOLUTION.key);
|
||||
assertThat("" + pref.getTitle()).isEqualTo(
|
||||
getText(EXTERNAL_DISPLAY_RESOLUTION_TITLE_RESOURCE));
|
||||
getText(PrefBasics.EXTERNAL_DISPLAY_RESOLUTION.titleResource));
|
||||
assertThat("" + pref.getSummary()).isEqualTo("1920 x 1080");
|
||||
assertThat(pref.isEnabled()).isTrue();
|
||||
assertThat(pref.getOnPreferenceClickListener()).isNotNull();
|
||||
@@ -378,8 +364,9 @@ public class ExternalDisplayPreferenceFragmentTest extends ExternalDisplayTestBa
|
||||
var fragment = initFragment();
|
||||
mHandler.flush();
|
||||
var pref = fragment.getSizePreference(mContext);
|
||||
assertThat(pref.getKey()).isEqualTo(EXTERNAL_DISPLAY_SIZE_PREFERENCE_KEY);
|
||||
assertThat("" + pref.getTitle()).isEqualTo(getText(EXTERNAL_DISPLAY_SIZE_TITLE_RESOURCE));
|
||||
assertThat(pref.getKey()).isEqualTo(PrefBasics.EXTERNAL_DISPLAY_SIZE.key);
|
||||
assertThat("" + pref.getTitle())
|
||||
.isEqualTo(getText(PrefBasics.EXTERNAL_DISPLAY_SIZE.titleResource));
|
||||
assertThat("" + pref.getSummary())
|
||||
.isEqualTo(getText(EXTERNAL_DISPLAY_SIZE_SUMMARY_RESOURCE));
|
||||
assertThat(pref.isEnabled()).isTrue();
|
||||
@@ -398,8 +385,9 @@ public class ExternalDisplayPreferenceFragmentTest extends ExternalDisplayTestBa
|
||||
var fragment = initFragment();
|
||||
mHandler.flush();
|
||||
var pref = fragment.getUseDisplayPreference(mContext);
|
||||
assertThat(pref.getKey()).isEqualTo(EXTERNAL_DISPLAY_USE_PREFERENCE_KEY);
|
||||
assertThat("" + pref.getTitle()).isEqualTo(getText(EXTERNAL_DISPLAY_USE_TITLE_RESOURCE));
|
||||
assertThat(pref.getKey()).isEqualTo(PrefBasics.EXTERNAL_DISPLAY_USE.key);
|
||||
assertThat("" + pref.getTitle())
|
||||
.isEqualTo(getText(PrefBasics.EXTERNAL_DISPLAY_USE.titleResource));
|
||||
assertThat(pref.isEnabled()).isTrue();
|
||||
assertThat(pref.isChecked()).isTrue();
|
||||
assertThat(pref.getOnPreferenceChangeListener()).isNotNull();
|
||||
|
||||
@@ -40,6 +40,7 @@ import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.PersistableBundle;
|
||||
import android.telephony.CarrierConfigManager;
|
||||
import android.telephony.ServiceState;
|
||||
@@ -67,9 +68,9 @@ import org.mockito.MockitoAnnotations;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class SimStatusDialogControllerTest {
|
||||
@@ -95,6 +96,7 @@ public class SimStatusDialogControllerTest {
|
||||
|
||||
private SimStatusDialogController mController;
|
||||
private Context mContext;
|
||||
private PackageManager mPackageManager;
|
||||
@Mock
|
||||
private LifecycleOwner mLifecycleOwner;
|
||||
private Lifecycle mLifecycle;
|
||||
@@ -112,6 +114,12 @@ public class SimStatusDialogControllerTest {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mContext = spy(ApplicationProvider.getApplicationContext());
|
||||
when(mDialog.getContext()).thenReturn(mContext);
|
||||
mPackageManager = spy(mContext.getPackageManager());
|
||||
when(mContext.getPackageManager()).thenReturn(mPackageManager);
|
||||
when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS))
|
||||
.thenReturn(true);
|
||||
when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY_CALLING))
|
||||
.thenReturn(true);
|
||||
mLifecycle = new Lifecycle(mLifecycleOwner);
|
||||
|
||||
mTelephonyManager = spy(mContext.getSystemService(TelephonyManager.class));
|
||||
|
||||
@@ -31,7 +31,6 @@ import static org.mockito.Mockito.when;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
import android.platform.test.flag.junit.SetFlagsRule;
|
||||
import android.safetycenter.SafetyCenterManager;
|
||||
import android.telephony.TelephonyManager;
|
||||
|
||||
@@ -42,11 +41,8 @@ import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import androidx.test.platform.app.InstrumentationRegistry;
|
||||
|
||||
import com.android.internal.telephony.flags.Flags;
|
||||
|
||||
import org.junit.Assume;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
@@ -54,8 +50,6 @@ import org.mockito.MockitoAnnotations;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public final class CellularSecurityPreferenceControllerTest {
|
||||
@Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
|
||||
|
||||
@Mock
|
||||
private TelephonyManager mTelephonyManager;
|
||||
private Preference mPreference;
|
||||
@@ -91,9 +85,6 @@ public final class CellularSecurityPreferenceControllerTest {
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_hardwareSupported_shouldReturnTrue() {
|
||||
// Enable telephony API flags for testing
|
||||
enableFlags(true);
|
||||
|
||||
// Hardware support is enabled
|
||||
doReturn(true).when(mTelephonyManager).isNullCipherNotificationsEnabled();
|
||||
doReturn(true).when(mTelephonyManager)
|
||||
@@ -120,9 +111,6 @@ public final class CellularSecurityPreferenceControllerTest {
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_noHardwareSupport_shouldReturnFalse() {
|
||||
// Enable telephony API flags for testing
|
||||
enableFlags(true);
|
||||
|
||||
// Hardware support is disabled
|
||||
doThrow(new UnsupportedOperationException("test")).when(mTelephonyManager)
|
||||
.isNullCipherNotificationsEnabled();
|
||||
@@ -133,11 +121,4 @@ public final class CellularSecurityPreferenceControllerTest {
|
||||
|
||||
assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
|
||||
}
|
||||
|
||||
private void enableFlags(boolean enabled) {
|
||||
if (enabled) {
|
||||
} else {
|
||||
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_MODEM_CIPHER_TRANSPARENCY_UNSOL_EVENTS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,6 @@ import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.platform.test.flag.junit.SetFlagsRule;
|
||||
import android.safetycenter.SafetyCenterManager;
|
||||
import android.telephony.TelephonyManager;
|
||||
|
||||
@@ -39,11 +38,8 @@ import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import androidx.test.platform.app.InstrumentationRegistry;
|
||||
|
||||
import com.android.internal.telephony.flags.Flags;
|
||||
|
||||
import org.junit.Assume;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
@@ -51,8 +47,6 @@ import org.mockito.MockitoAnnotations;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class CellularSecurityNotificationsDividerControllerTest {
|
||||
@Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
|
||||
|
||||
@Mock
|
||||
private TelephonyManager mTelephonyManager;
|
||||
private Preference mPreference;
|
||||
@@ -86,9 +80,6 @@ public class CellularSecurityNotificationsDividerControllerTest {
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_hardwareSupported_shouldReturnTrue() {
|
||||
// Enable telephony API flags for testing
|
||||
enableFlags(true);
|
||||
|
||||
// Hardware support is enabled
|
||||
doReturn(true).when(mTelephonyManager).isNullCipherNotificationsEnabled();
|
||||
doReturn(true).when(mTelephonyManager)
|
||||
@@ -99,9 +90,6 @@ public class CellularSecurityNotificationsDividerControllerTest {
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_noHardwareSupport_shouldReturnFalse() {
|
||||
// Enable telephony API flags for testing
|
||||
enableFlags(true);
|
||||
|
||||
// Hardware support is disabled
|
||||
doThrow(new UnsupportedOperationException("test")).when(mTelephonyManager)
|
||||
.isNullCipherNotificationsEnabled();
|
||||
@@ -110,12 +98,4 @@ public class CellularSecurityNotificationsDividerControllerTest {
|
||||
|
||||
assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
|
||||
}
|
||||
|
||||
private void enableFlags(boolean enabled) {
|
||||
if (enabled) {
|
||||
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_MODEM_CIPHER_TRANSPARENCY_UNSOL_EVENTS);
|
||||
} else {
|
||||
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_MODEM_CIPHER_TRANSPARENCY_UNSOL_EVENTS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,6 @@ import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.platform.test.flag.junit.SetFlagsRule;
|
||||
import android.safetycenter.SafetyCenterManager;
|
||||
import android.telephony.TelephonyManager;
|
||||
|
||||
@@ -40,11 +39,8 @@ import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import androidx.test.platform.app.InstrumentationRegistry;
|
||||
|
||||
import com.android.internal.telephony.flags.Flags;
|
||||
|
||||
import org.junit.Assume;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
@@ -52,8 +48,6 @@ import org.mockito.MockitoAnnotations;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class CellularSecurityNotificationsPreferenceControllerTest {
|
||||
@Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
|
||||
|
||||
@Mock
|
||||
private TelephonyManager mTelephonyManager;
|
||||
private Preference mPreference;
|
||||
@@ -87,9 +81,6 @@ public class CellularSecurityNotificationsPreferenceControllerTest {
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_hardwareSupported_shouldReturnTrue() {
|
||||
// All flags enabled
|
||||
enableFlags(true);
|
||||
|
||||
// Hardware support is enabled
|
||||
doReturn(true).when(mTelephonyManager).isNullCipherNotificationsEnabled();
|
||||
doReturn(true).when(mTelephonyManager)
|
||||
@@ -100,9 +91,6 @@ public class CellularSecurityNotificationsPreferenceControllerTest {
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_noHardwareSupport_shouldReturnFalse() {
|
||||
// All flags enabled
|
||||
enableFlags(true);
|
||||
|
||||
// Hardware support is disabled
|
||||
doThrow(new UnsupportedOperationException("test")).when(mTelephonyManager)
|
||||
.isNullCipherNotificationsEnabled();
|
||||
@@ -114,8 +102,6 @@ public class CellularSecurityNotificationsPreferenceControllerTest {
|
||||
|
||||
@Test
|
||||
public void setChecked_shouldReturnTrue() {
|
||||
enableFlags(true);
|
||||
|
||||
// Hardware support is enabled, enabling the feature
|
||||
doNothing().when(mTelephonyManager).setNullCipherNotificationsEnabled(true);
|
||||
doNothing().when(mTelephonyManager)
|
||||
@@ -140,8 +126,6 @@ public class CellularSecurityNotificationsPreferenceControllerTest {
|
||||
|
||||
@Test
|
||||
public void isChecked_hardwareUnsupported_shouldReturnFalse() {
|
||||
enableFlags(true);
|
||||
|
||||
// Hardware support is disabled
|
||||
doThrow(new UnsupportedOperationException("test")).when(mTelephonyManager)
|
||||
.isNullCipherNotificationsEnabled();
|
||||
@@ -153,8 +137,6 @@ public class CellularSecurityNotificationsPreferenceControllerTest {
|
||||
|
||||
@Test
|
||||
public void isChecked_notificationsDisabled_shouldReturnFalse() {
|
||||
enableFlags(true);
|
||||
|
||||
// Hardware support is enabled, but APIs are disabled
|
||||
doReturn(false).when(mTelephonyManager).isNullCipherNotificationsEnabled();
|
||||
doReturn(false).when(mTelephonyManager)
|
||||
@@ -165,12 +147,4 @@ public class CellularSecurityNotificationsPreferenceControllerTest {
|
||||
doReturn(true).when(mTelephonyManager).isNullCipherNotificationsEnabled();
|
||||
assertThat(mController.isChecked()).isFalse();
|
||||
}
|
||||
|
||||
private void enableFlags(boolean enabled) {
|
||||
if (enabled) {
|
||||
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_MODEM_CIPHER_TRANSPARENCY_UNSOL_EVENTS);
|
||||
} else {
|
||||
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_MODEM_CIPHER_TRANSPARENCY_UNSOL_EVENTS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user