Snap for 12651823 from b29b9b1b11 to 25Q1-release

Change-Id: Ifa207c095f83bbf430e5d91457b2e4ca6ce97d7e
This commit is contained in:
Android Build Coastguard Worker
2024-11-14 00:16:55 +00:00
52 changed files with 652 additions and 910 deletions

View File

@@ -1,25 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2024 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="@dimen/accessibility_icon_foreground_size"
android:height="@dimen/accessibility_icon_foreground_size"
android:viewportWidth="960"
android:viewportHeight="960">
<path
android:fillColor="@android:color/white"
android:pathData="M312,640L376,640L408,548L554,548L586,640L648,640L512,280L448,280L312,640ZM426,496L478,346L482,346L534,496L426,496ZM480,932L346,800L160,800L160,614L28,480L160,346L160,160L346,160L480,28L614,160L800,160L800,346L932,480L800,614L800,800L614,800L480,932ZM480,820L580,720L720,720L720,580L820,480L720,380L720,240L580,240L480,140L380,240L240,240L240,380L140,480L240,580L240,720L380,720L480,820ZM480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Z"/>
</vector>

View File

@@ -1,25 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2024 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="@dimen/accessibility_icon_foreground_size"
android:height="@dimen/accessibility_icon_foreground_size"
android:viewportWidth="960"
android:viewportHeight="960">
<path
android:fillColor="@android:color/white"
android:pathData="M480,932L346,800L160,800L160,614L28,480L160,346L160,160L346,160L480,28L614,160L800,160L800,346L932,480L800,614L800,800L614,800L480,932ZM480,680Q563,680 621.5,621.5Q680,563 680,480Q680,397 621.5,338.5Q563,280 480,280L480,680ZM480,820L580,720L720,720L720,580L820,480L720,380L720,240L580,240L480,140L380,240L240,240L240,380L140,480L240,580L240,720L380,720L480,820ZM480,480L480,480L480,480L480,480L480,480L480,480L480,480L480,480L480,480L480,480L480,480L480,480L480,480L480,480L480,480L480,480L480,480Z"/>
</vector>

View File

@@ -21,6 +21,15 @@
android:height="@dimen/accessibility_icon_size"
android:color="@color/accessibility_feature_background"/>
</item>
<item android:gravity="center"
android:drawable="@drawable/ic_brightness_auto"/>
<item android:gravity="center">
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="@dimen/accessibility_icon_foreground_size"
android:height="@dimen/accessibility_icon_foreground_size"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M2 15V13H5V15H2ZM6.35 9.75L4.225 7.625L5.625 6.225L7.75 8.35L6.35 9.75ZM7 18V15H17V18H7ZM11 7V4H13V7H11ZM17.65 9.775L16.25 8.35L18.375 6.225L19.775 7.65L17.65 9.775ZM19 15V13H22V15H19Z"/>
</vector>
</item>
</layer-list>

View File

@@ -21,6 +21,15 @@
android:height="@dimen/accessibility_icon_size"
android:color="@color/accessibility_feature_background"/>
</item>
<item android:gravity="center"
android:drawable="@drawable/ic_brightness_medium"/>
<item android:gravity="center">
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="@dimen/accessibility_icon_foreground_size"
android:height="@dimen/accessibility_icon_foreground_size"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M9 14.5V13H15V14.5H9ZM8 11.5V10H16V11.5H8ZM7 23C6.45 23 5.975 22.8083 5.575 22.425C5.19167 22.025 5 21.55 5 21V3C5 2.45 5.19167 1.98333 5.575 1.6C5.975 1.2 6.45 0.999999 7 0.999999H17C17.55 0.999999 18.0167 1.2 18.4 1.6C18.8 1.98333 19 2.45 19 3V21C19 21.55 18.8 22.025 18.4 22.425C18.0167 22.8083 17.55 23 17 23H7ZM7 20V21H17V20H7ZM7 18H17V6H7V18ZM7 4H17V3H7V4ZM7 4V3V4ZM7 20V21V20Z"/>
</vector>
</item>
</layer-list>

View File

@@ -2869,16 +2869,12 @@
<string name="brightness">Brightness level</string>
<!-- Sound & display settings screen, setting option name to enable adaptive brightness [CHAR LIMIT=30] -->
<string name="auto_brightness_title">Adaptive brightness</string>
<!-- Note: The content description title is only applied in adaptive brightness detailed page in setup wizard flow, to make the consistency with other accessibility suw pages. -->
<!-- ContentDescription title for adaptive brightness detailed page footer. [CHAR LIMIT=60] -->
<string name="auto_brightness_content_description_title">About adaptive brightness</string>
<!-- Description about the feature adaptive brightness -->
<string name="auto_brightness_description">Your screen brightness will automatically adjust to your environment and activities. You can move the slider manually to help adaptive brightness learn your preferences.</string>
<!-- Setting option summary when adaptive brightness is on [CHAR LIMIT=NONE] -->
<string name="auto_brightness_summary_on">On</string>
<!-- Setting option summary when adaptive brightness is off [CHAR LIMIT=NONE] -->
<string name="auto_brightness_summary_off">Off</string>
<!-- Display settings screen, display white balance settings title [CHAR LIMIT=30] -->
<string name="display_white_balance_title">Display white balance</string>
<!-- Display settings screen, display white balance settings summary [CHAR LIMIT=NONE] -->

View File

@@ -37,11 +37,10 @@
settings:useAdminDisabledSummary="true"
settings:userRestriction="no_config_brightness"/>
<com.android.settingslib.PrimarySwitchPreference
<com.android.settingslib.RestrictedSwitchPreference
android:key="@string/preference_key_auto_brightness"
android:icon="@drawable/ic_suw_brightness_auto"
android:title="@string/auto_brightness_title"
android:fragment="com.android.settings.accessibility.AutoBrightnessPreferenceFragmentForSetupWizard"
settings:useAdminDisabledSummary="true"
settings:userRestriction="no_config_brightness"
settings:controller="com.android.settings.display.AutoBrightnessPreferenceControllerForSetupWizard"/>

View File

@@ -1,177 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2008 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
android:title="@string/apn_edit">
<EditTextPreference
android:title="@string/apn_name"
android:dialogTitle="@string/apn_name"
android:key="apn_name"
android:singleLine="true"
android:inputType="text"
android:persistent="false"
/>
<EditTextPreference
android:title="@string/apn_apn"
android:dialogTitle="@string/apn_apn"
android:key="apn_apn"
android:singleLine="true"
android:inputType="textEmailAddress"
android:persistent="false"
/>
<EditTextPreference
android:title="@string/apn_http_proxy"
android:dialogTitle="@string/apn_http_proxy"
android:key="apn_http_proxy"
android:singleLine="true"
android:inputType="textUri"
android:persistent="false"
/>
<EditTextPreference
android:title="@string/apn_http_port"
android:dialogTitle="@string/apn_http_port"
android:key="apn_http_port"
android:singleLine="true"
android:inputType="number"
android:persistent="false"
/>
<EditTextPreference
android:title="@string/apn_user"
android:dialogTitle="@string/apn_user"
android:key="apn_user"
android:singleLine="true"
android:inputType="textEmailAddress"
android:persistent="false"
/>
<EditTextPreference
android:title="@string/apn_password"
android:dialogTitle="@string/apn_password"
android:key="apn_password"
android:singleLine="true"
android:inputType="textPassword"
android:persistent="false"
/>
<EditTextPreference
android:title="@string/apn_server"
android:dialogTitle="@string/apn_server"
android:key="apn_server"
android:singleLine="true"
android:inputType="textUri"
android:persistent="false"
/>
<EditTextPreference
android:title="@string/apn_mmsc"
android:dialogTitle="@string/apn_mmsc"
android:key="apn_mmsc"
android:singleLine="true"
android:inputType="textUri"
android:persistent="false"
/>
<EditTextPreference
android:title="@string/apn_mms_proxy"
android:dialogTitle="@string/apn_mms_proxy"
android:key="apn_mms_proxy"
android:singleLine="true"
android:inputType="textUri"
android:persistent="false"
/>
<EditTextPreference
android:title="@string/apn_mms_port"
android:dialogTitle="@string/apn_mms_port"
android:key="apn_mms_port"
android:singleLine="true"
android:inputType="number"
android:persistent="false"
/>
<EditTextPreference
android:title="@string/apn_mcc"
android:dialogTitle="@string/apn_mcc"
android:key="apn_mcc"
android:singleLine="true"
android:inputType="number"
android:persistent="false"
/>
<EditTextPreference
android:title="@string/apn_mnc"
android:dialogTitle="@string/apn_mnc"
android:key="apn_mnc"
android:singleLine="true"
android:inputType="number"
android:persistent="false"
/>
<ListPreference
android:title="@string/apn_auth_type"
android:key="auth_type"
android:entries="@array/apn_auth_entries"
android:entryValues="@array/apn_auth_values"
android:persistent="false"
/>
<EditTextPreference
android:title="@string/apn_type"
android:dialogTitle="@string/apn_type"
android:key="apn_type"
android:singleLine="true"
android:inputType="textNoSuggestions"
android:persistent="false"
/>
<ListPreference
android:title="@string/apn_protocol"
android:dialogTitle="@string/apn_protocol"
android:key="apn_protocol"
android:entries="@array/apn_protocol_entries"
android:entryValues="@array/apn_protocol_values"
android:persistent="false"
/>
<ListPreference
android:title="@string/apn_roaming_protocol"
android:dialogTitle="@string/apn_roaming_protocol"
android:key="apn_roaming_protocol"
android:entries="@array/apn_protocol_entries"
android:entryValues="@array/apn_protocol_values"
android:persistent="false"
/>
<SwitchPreferenceCompat
android:title="@string/carrier_enabled"
android:key="carrier_enabled"
android:enabled="false"
android:summaryOn="@string/carrier_enabled_summaryOn"
android:summaryOff="@string/carrier_enabled_summaryOff"
android:persistent="false"
/>
<MultiSelectListPreference
android:title="@string/bearer"
android:key="bearer_multi"
android:entries="@array/bearer_entries"
android:entryValues="@array/bearer_values"
android:persistent="false"
style="@style/SettingsMultiSelectListPreference"
/>
<ListPreference
android:title="@string/mvno_type"
android:key="mvno_type"
android:entries="@array/mvno_type_entries"
android:entryValues="@array/mvno_type_values"
android:persistent="false"
/>
<EditTextPreference
android:title="@string/mvno_match_data"
android:dialogTitle="@string/mvno_match_data"
android:key="mvno_match_data"
android:singleLine="true"
android:inputType="text"
android:persistent="false"
/>
</PreferenceScreen>

View File

@@ -1,98 +0,0 @@
/*
* Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.accessibility;
import static android.app.Activity.RESULT_CANCELED;
import android.app.settings.SettingsEnums;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.preference.PreferenceScreen;
import androidx.recyclerview.widget.RecyclerView;
import com.android.settings.R;
import com.android.settings.display.AutoBrightnessSettings;
import com.android.settingslib.Utils;
import com.android.settingslib.widget.FooterPreference;
import com.google.android.setupcompat.template.FooterBarMixin;
import com.google.android.setupdesign.GlifPreferenceLayout;
/**
* Fragment for adaptive brightness settings in the SetupWizard.
*/
public class AutoBrightnessPreferenceFragmentForSetupWizard extends AutoBrightnessSettings {
private static final String FOOTER_PREFERENCE_KEY = "auto_brightness_footer";
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
updateFooterContentDescription();
if (view instanceof GlifPreferenceLayout) {
final GlifPreferenceLayout layout = (GlifPreferenceLayout) view;
final String title = getContext().getString(
R.string.auto_brightness_title);
final Drawable icon = getContext().getDrawable(R.drawable.ic_accessibility_visibility);
icon.setTintList(Utils.getColorAttr(getContext(), android.R.attr.colorPrimary));
AccessibilitySetupWizardUtils.updateGlifPreferenceLayout(getContext(), layout, title,
/* description= */ null, icon);
final FooterBarMixin mixin = layout.getMixin(FooterBarMixin.class);
AccessibilitySetupWizardUtils.setPrimaryButton(getContext(), mixin, R.string.done,
() -> {
setResult(RESULT_CANCELED);
finish();
});
}
}
@NonNull
@Override
public RecyclerView onCreateRecyclerView(@NonNull LayoutInflater inflater,
@NonNull ViewGroup parent, @Nullable Bundle savedInstanceState) {
if (parent instanceof GlifPreferenceLayout) {
final GlifPreferenceLayout layout = (GlifPreferenceLayout) parent;
return layout.onCreateRecyclerView(inflater, parent, savedInstanceState);
}
return super.onCreateRecyclerView(inflater, parent, savedInstanceState);
}
@Override
public int getMetricsCategory() {
return SettingsEnums.SUW_ACCESSIBILITY_AUTO_BRIGHTNESS;
}
private void updateFooterContentDescription() {
final PreferenceScreen screen = getPreferenceScreen();
final FooterPreference footerPreference = screen.findPreference(FOOTER_PREFERENCE_KEY);
if (footerPreference != null) {
String title = getString(R.string.auto_brightness_content_description_title);
final StringBuilder sb = new StringBuilder();
sb.append(title).append("\n\n").append(footerPreference.getTitle());
footerPreference.setContentDescription(sb);
}
}
}

View File

@@ -87,6 +87,12 @@ public class BluetoothDetailsCompanionAppsController extends BluetoothDetailsCon
mProfilesContainer.setLayoutResource(R.layout.preference_companion_app);
}
@Override
public boolean isAvailable() {
// Do not show this preference for now. More details in b/191992001#comment7
return false;
}
private List<AssociationInfo> getAssociations(String address) {
return filter(
mCompanionDeviceManager.getAllAssociations(),

View File

@@ -110,7 +110,10 @@ public class AudioSharingCallAudioPreferenceController extends AudioSharingBaseP
@Override
public void onSourceAdded(
@NonNull BluetoothDevice sink, int sourceId, int reason) {}
@NonNull BluetoothDevice sink, int sourceId, int reason) {
Log.d(TAG, "onSourceAdded: updateSummary");
updateSummary();
}
@Override
public void onSourceAddFailed(
@@ -138,12 +141,7 @@ public class AudioSharingCallAudioPreferenceController extends AudioSharingBaseP
public void onReceiveStateChanged(
@NonNull BluetoothDevice sink,
int sourceId,
@NonNull BluetoothLeBroadcastReceiveState state) {
if (BluetoothUtils.isConnected(state)) {
Log.d(TAG, "onReceiveStateChanged: synced, updateSummary");
updateSummary();
}
}
@NonNull BluetoothLeBroadcastReceiveState state) {}
};
public AudioSharingCallAudioPreferenceController(Context context) {

View File

@@ -116,7 +116,18 @@ public class AudioSharingDevicePreferenceController extends BasePreferenceContro
@Override
public void onSourceAdded(
@NonNull BluetoothDevice sink, int sourceId, int reason) {}
@NonNull BluetoothDevice sink, int sourceId, int reason) {
Log.d(TAG, "onSourceAdded: update sharing device list.");
if (mBluetoothDeviceUpdater != null) {
mBluetoothDeviceUpdater.forceUpdate();
}
if (mDeviceManager != null && mDialogHandler != null) {
CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(sink);
if (cachedDevice != null) {
mDialogHandler.closeOpeningDialogsForLeaDevice(cachedDevice);
}
}
}
@Override
public void onSourceAddFailed(
@@ -173,20 +184,7 @@ public class AudioSharingDevicePreferenceController extends BasePreferenceContro
public void onReceiveStateChanged(
@NonNull BluetoothDevice sink,
int sourceId,
@NonNull BluetoothLeBroadcastReceiveState state) {
if (BluetoothUtils.isConnected(state)) {
Log.d(TAG, "onSourceAdded: update sharing device list.");
if (mBluetoothDeviceUpdater != null) {
mBluetoothDeviceUpdater.forceUpdate();
}
if (mDeviceManager != null && mDialogHandler != null) {
CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(sink);
if (cachedDevice != null) {
mDialogHandler.closeOpeningDialogsForLeaDevice(cachedDevice);
}
}
}
}
@NonNull BluetoothLeBroadcastReceiveState state) {}
};
public AudioSharingDevicePreferenceController(Context context) {

View File

@@ -132,7 +132,12 @@ public class AudioSharingDeviceVolumeGroupController extends AudioSharingBasePre
@Override
public void onSourceAdded(
@NonNull BluetoothDevice sink, int sourceId, int reason) {}
@NonNull BluetoothDevice sink, int sourceId, int reason) {
Log.d(TAG, "onSourceAdded: update volume list.");
if (mBluetoothDeviceUpdater != null) {
mBluetoothDeviceUpdater.forceUpdate();
}
}
@Override
public void onSourceAddFailed(
@@ -165,14 +170,7 @@ public class AudioSharingDeviceVolumeGroupController extends AudioSharingBasePre
public void onReceiveStateChanged(
@NonNull BluetoothDevice sink,
int sourceId,
@NonNull BluetoothLeBroadcastReceiveState state) {
if (BluetoothUtils.isConnected(state)) {
Log.d(TAG, "onReceiveStateChanged: synced, update volume list.");
if (mBluetoothDeviceUpdater != null) {
mBluetoothDeviceUpdater.forceUpdate();
}
}
}
@NonNull BluetoothLeBroadcastReceiveState state) {}
};
public AudioSharingDeviceVolumeGroupController(Context context) {

View File

@@ -177,6 +177,20 @@ public class AudioSharingSwitchBarController extends BasePreferenceController
+ broadcastId
+ ", metadata = "
+ metadata.getBroadcastName());
if (mAssistant == null
|| mAssistant.getAllConnectedDevices().stream()
.anyMatch(
device -> BluetoothUtils
.hasActiveLocalBroadcastSourceForBtDevice(
device, mBtManager))) {
Log.d(
TAG,
"Skip handleOnBroadcastReady: null assistant or "
+ "sink has active local source.");
cleanUpStatesForStartSharing();
return;
}
handleOnBroadcastReady();
}
@Override
@@ -221,20 +235,6 @@ public class AudioSharingSwitchBarController extends BasePreferenceController
+ reason
+ ", broadcastId = "
+ broadcastId);
if (mAssistant == null
|| mAssistant.getAllConnectedDevices().stream()
.anyMatch(
device -> BluetoothUtils
.hasActiveLocalBroadcastSourceForBtDevice(
device, mBtManager))) {
Log.d(
TAG,
"Skip handleOnBroadcastReady: null assistant or "
+ "sink has active local source.");
cleanUpStatesForStartSharing();
return;
}
handleOnBroadcastReady();
}
@Override
@@ -261,7 +261,30 @@ public class AudioSharingSwitchBarController extends BasePreferenceController
@Override
public void onSourceAdded(
@NonNull BluetoothDevice sink, int sourceId, int reason) {}
@NonNull BluetoothDevice sink, int sourceId, int reason) {
if (mSinksInAdding.contains(sink)) {
mSinksInAdding.remove(sink);
}
dismissProgressDialogIfNeeded();
Log.d(TAG, "onSourceAdded(), sink = " + sink + ", remaining sinks = "
+ mSinksInAdding);
if (mSinksToWaitFor.contains(sink)) {
mSinksToWaitFor.remove(sink);
if (mSinksToWaitFor.isEmpty()) {
// To avoid users advance to share then pair flow before the
// primary/active sinks successfully join the audio sharing,
// popup dialog till adding source complete for mSinksToWaitFor.
Pair<Integer, Object>[] eventData =
AudioSharingUtils.buildAudioSharingDialogEventData(
SettingsEnums.AUDIO_SHARING_SETTINGS,
SettingsEnums.DIALOG_AUDIO_SHARING_ADD_DEVICE,
/* userTriggered= */ false,
/* deviceCountInSharing= */ 1,
/* candidateDeviceCount= */ 0);
showAudioSharingDialog(eventData);
}
}
}
@Override
public void onSourceAddFailed(
@@ -307,34 +330,9 @@ public class AudioSharingSwitchBarController extends BasePreferenceController
@NonNull BluetoothDevice sink,
int sourceId,
@NonNull BluetoothLeBroadcastReceiveState state) {
if (mStoppingSharing.get()) {
Log.d(TAG, "Skip onReceiveStateChanged, stopping broadcast");
return;
}
if (BluetoothUtils.isConnected(state)) {
if (mSinksInAdding.contains(sink)) {
mSinksInAdding.remove(sink);
}
dismissProgressDialogIfNeeded();
Log.d(TAG, "onReceiveStateChanged() connected, sink = " + sink
+ ", remaining sinks = " + mSinksInAdding);
if (mSinksToWaitFor.contains(sink)) {
mSinksToWaitFor.remove(sink);
if (mSinksToWaitFor.isEmpty()) {
// To avoid users advance to share then pair flow before the
// primary/active sinks successfully join the audio sharing,
// popup dialog till adding source complete for mSinksToWaitFor.
Pair<Integer, Object>[] eventData =
AudioSharingUtils.buildAudioSharingDialogEventData(
SettingsEnums.AUDIO_SHARING_SETTINGS,
SettingsEnums.DIALOG_AUDIO_SHARING_ADD_DEVICE,
/* userTriggered= */ false,
/* deviceCountInSharing= */ 1,
/* candidateDeviceCount= */ 0);
showAudioSharingDialog(eventData);
}
}
}
Log.d(TAG,
"onReceiveStateChanged(), sink = " + sink + ", sourceId = " + sourceId
+ ", state = " + state);
}
};

View File

@@ -46,7 +46,6 @@ import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
import com.android.settingslib.bluetooth.VolumeControlProfile;
import com.android.settingslib.flags.Flags;
import java.util.ArrayList;
import java.util.Comparator;
@@ -222,8 +221,8 @@ public class AudioSharingUtils {
Log.d(TAG, "hasActiveConnectedLeadDevice return false due to null device manager.");
return false;
}
return deviceManager.getCachedDevicesCopy().stream().anyMatch(
BluetoothUtils::isActiveMediaDevice);
return deviceManager.getCachedDevicesCopy().stream()
.anyMatch(BluetoothUtils::isActiveMediaDevice);
}
/** Build {@link AudioSharingDeviceItem} from {@link CachedBluetoothDevice}. */
@@ -348,14 +347,15 @@ public class AudioSharingUtils {
}
/** Set {@link CachedBluetoothDevice} as primary device for call audio */
public static void setPrimary(@NonNull Context context,
@Nullable CachedBluetoothDevice cachedDevice) {
public static void setPrimary(
@NonNull Context context, @Nullable CachedBluetoothDevice cachedDevice) {
if (cachedDevice == null) return;
cachedDevice.setActive();
if (Flags.audioSharingHysteresisModeFix()) {
if (BluetoothUtils.isAudioSharingHysteresisModeFixAvailable(context)) {
int groupId = BluetoothUtils.getGroupId(cachedDevice);
// TODO: use real key name in SettingsProvider
int userPreferredId = Settings.Secure.getInt(
int userPreferredId =
Settings.Secure.getInt(
context.getContentResolver(),
BLUETOOTH_LE_BROADCAST_PRIMARY_DEVICE_GROUP_ID,
BluetoothCsipSetCoordinator.GROUP_ID_INVALID);

View File

@@ -16,8 +16,6 @@
package com.android.settings.connecteddevice.audiosharing.audiostreams;
import static com.android.settingslib.flags.Flags.audioSharingHysteresisModeFix;
import android.app.settings.SettingsEnums;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothLeBroadcastAssistant;
@@ -38,6 +36,7 @@ import com.android.settings.R;
import com.android.settings.bluetooth.Utils;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.bluetooth.BluetoothUtils;
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
import com.android.settingslib.utils.ThreadUtils;
@@ -77,7 +76,7 @@ public class AudioStreamButtonController extends BasePreferenceController
BluetoothLeBroadcastReceiveState state) {
super.onReceiveStateChanged(sink, sourceId, state);
boolean shouldUpdateButton =
audioSharingHysteresisModeFix()
BluetoothUtils.isAudioSharingHysteresisModeFixAvailable(mContext)
? AudioStreamsHelper.hasSourcePresent(state)
: AudioStreamsHelper.isConnected(state);
if (shouldUpdateButton) {
@@ -157,7 +156,7 @@ public class AudioStreamButtonController extends BasePreferenceController
}
List<BluetoothLeBroadcastReceiveState> sources =
audioSharingHysteresisModeFix()
BluetoothUtils.isAudioSharingHysteresisModeFixAvailable(mContext)
? mAudioStreamsHelper.getAllPresentSources()
: mAudioStreamsHelper.getAllConnectedSources();
boolean isConnected =

View File

@@ -37,6 +37,7 @@ import com.android.settings.bluetooth.Utils;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.widget.EntityHeaderController;
import com.android.settingslib.bluetooth.BluetoothUtils;
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant;
import com.android.settingslib.utils.ThreadUtils;
import com.android.settingslib.widget.LayoutPreference;
@@ -86,7 +87,7 @@ public class AudioStreamHeaderController extends BasePreferenceController
updateSummary();
mAudioStreamsHelper.startMediaService(
mContext, mBroadcastId, mBroadcastName);
} else if (audioSharingHysteresisModeFix()
} else if (BluetoothUtils.isAudioSharingHysteresisModeFixAvailable(mContext)
&& AudioStreamsHelper.hasSourcePresent(state)) {
// if source present but not connected, only update the summary
updateSummary();

View File

@@ -18,8 +18,6 @@ package com.android.settings.connecteddevice.audiosharing.audiostreams;
import static android.text.Spanned.SPAN_EXCLUSIVE_INCLUSIVE;
import static com.android.settingslib.flags.Flags.audioSharingHysteresisModeFix;
import android.os.Handler;
import android.os.Looper;
import android.text.SpannableString;
@@ -98,7 +96,8 @@ class AudioStreamStateHandler {
newState
== AudioStreamsProgressCategoryController
.AudioStreamState.SOURCE_ADDED
|| (audioSharingHysteresisModeFix()
|| (BluetoothUtils.isAudioSharingHysteresisModeFixAvailable(
preference.getContext())
&& newState
== AudioStreamsProgressCategoryController
.AudioStreamState.SOURCE_PRESENT));

View File

@@ -31,7 +31,6 @@ import com.android.settingslib.bluetooth.BluetoothCallback;
import com.android.settingslib.bluetooth.BluetoothUtils;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.flags.Flags;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
@@ -80,13 +79,6 @@ public class AudioStreamsCategoryController extends AudioSharingBasePreferenceCo
}
}
@Override
public int getAvailabilityStatus() {
return Flags.enableLeAudioQrCodePrivateBroadcastSharing()
? AVAILABLE
: UNSUPPORTED_ON_DEVICE;
}
@Override
public void updateVisibility() {
if (mPreference == null) return;

View File

@@ -19,7 +19,6 @@ package com.android.settings.connecteddevice.audiosharing.audiostreams;
import static com.android.settings.connecteddevice.audiosharing.audiostreams.AudioStreamMediaService.BROADCAST_ID;
import static com.android.settings.connecteddevice.audiosharing.audiostreams.AudioStreamMediaService.BROADCAST_TITLE;
import static com.android.settings.connecteddevice.audiosharing.audiostreams.AudioStreamMediaService.DEVICES;
import static com.android.settingslib.flags.Flags.audioSharingHysteresisModeFix;
import static java.util.Collections.emptyList;
@@ -271,7 +270,8 @@ public class AudioStreamsHelper {
List<BluetoothLeBroadcastReceiveState> sourceList =
assistant.getAllSources(cachedDevice.getDevice());
if (!sourceList.isEmpty()
&& (audioSharingHysteresisModeFix()
&& (BluetoothUtils.isAudioSharingHysteresisModeFixAvailable(
localBtManager.getContext())
|| sourceList.stream().anyMatch(AudioStreamsHelper::isConnected))) {
Log.d(
TAG,
@@ -284,7 +284,8 @@ public class AudioStreamsHelper {
List<BluetoothLeBroadcastReceiveState> list =
assistant.getAllSources(device.getDevice());
if (!list.isEmpty()
&& (audioSharingHysteresisModeFix()
&& (BluetoothUtils.isAudioSharingHysteresisModeFixAvailable(
localBtManager.getContext())
|| list.stream().anyMatch(AudioStreamsHelper::isConnected))) {
Log.d(
TAG,

View File

@@ -16,19 +16,24 @@
package com.android.settings.connecteddevice.audiosharing.audiostreams;
import static com.android.settingslib.flags.Flags.audioSharingHysteresisModeFix;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothLeBroadcastMetadata;
import android.bluetooth.BluetoothLeBroadcastReceiveState;
import android.content.Context;
import com.android.settingslib.bluetooth.BluetoothUtils;
public class AudioStreamsProgressCategoryCallback extends AudioStreamsBroadcastAssistantCallback {
private static final String TAG = "AudioStreamsProgressCategoryCallback";
private final Context mContext;
private final AudioStreamsProgressCategoryController mCategoryController;
public AudioStreamsProgressCategoryCallback(
Context context,
AudioStreamsProgressCategoryController audioStreamsProgressCategoryController) {
mContext = context;
mCategoryController = audioStreamsProgressCategoryController;
}
@@ -41,7 +46,8 @@ public class AudioStreamsProgressCategoryCallback extends AudioStreamsBroadcastA
mCategoryController.handleSourceConnected(state);
} else if (AudioStreamsHelper.isBadCode(state)) {
mCategoryController.handleSourceConnectBadCode(state);
} else if (audioSharingHysteresisModeFix() && AudioStreamsHelper.hasSourcePresent(state)) {
} else if (BluetoothUtils.isAudioSharingHysteresisModeFixAvailable(mContext)
&& AudioStreamsHelper.hasSourcePresent(state)) {
// Keep this check as the last, source might also present in above states
mCategoryController.handleSourcePresent(state);
}

View File

@@ -16,8 +16,6 @@
package com.android.settings.connecteddevice.audiosharing.audiostreams;
import static com.android.settingslib.flags.Flags.audioSharingHysteresisModeFix;
import static java.util.Collections.emptyList;
import android.app.AlertDialog;
@@ -101,7 +99,7 @@ public class AudioStreamsProgressCategoryController extends BasePreferenceContro
(p.getAudioStreamState()
== AudioStreamsProgressCategoryController
.AudioStreamState.SOURCE_ADDED
|| (audioSharingHysteresisModeFix()
|| (isAudioSharingHysteresisModeFixAvailable(mContext)
&& p.getAudioStreamState()
== AudioStreamsProgressCategoryController
.AudioStreamState
@@ -147,7 +145,7 @@ public class AudioStreamsProgressCategoryController extends BasePreferenceContro
mAudioStreamsHelper = new AudioStreamsHelper(mBluetoothManager);
mMediaControlHelper = new MediaControlHelper(mContext, mBluetoothManager);
mLeBroadcastAssistant = mAudioStreamsHelper.getLeBroadcastAssistant();
mBroadcastAssistantCallback = new AudioStreamsProgressCategoryCallback(this);
mBroadcastAssistantCallback = new AudioStreamsProgressCategoryCallback(context, this);
}
@Override
@@ -258,7 +256,7 @@ public class AudioStreamsProgressCategoryController extends BasePreferenceContro
// change it's state.
existingPreference.setAudioStreamMetadata(source);
if (fromState != AudioStreamState.SOURCE_ADDED
&& (!audioSharingHysteresisModeFix()
&& (!isAudioSharingHysteresisModeFixAvailable(mContext)
|| fromState != AudioStreamState.SOURCE_PRESENT)) {
Log.w(
TAG,
@@ -364,7 +362,7 @@ public class AudioStreamsProgressCategoryController extends BasePreferenceContro
// not, means the source is removed from the sink, we move back the preference to SYNCED
// state.
if ((preference.getAudioStreamState() == AudioStreamState.SOURCE_ADDED
|| (audioSharingHysteresisModeFix()
|| (isAudioSharingHysteresisModeFixAvailable(mContext)
&& preference.getAudioStreamState()
== AudioStreamState.SOURCE_PRESENT))
&& mAudioStreamsHelper.getAllConnectedSources().stream()
@@ -600,7 +598,7 @@ public class AudioStreamsProgressCategoryController extends BasePreferenceContro
// Handle QR code scan, display currently connected streams then start scanning
// sequentially
handleSourceFromQrCodeIfExists();
if (audioSharingHysteresisModeFix()) {
if (isAudioSharingHysteresisModeFixAvailable(mContext)) {
// With hysteresis mode, we prioritize showing connected sources first.
// If no connected sources are found, we then show present sources.
List<BluetoothLeBroadcastReceiveState> sources =
@@ -702,4 +700,8 @@ public class AudioStreamsProgressCategoryController extends BasePreferenceContro
dialog.dismiss();
});
}
private static boolean isAudioSharingHysteresisModeFixAvailable(Context context) {
return BluetoothUtils.isAudioSharingHysteresisModeFixAvailable(context);
}
}

View File

@@ -28,7 +28,6 @@ import com.android.settings.accessibility.AccessibilityDetailsSettingsFragment;
import com.android.settings.accessibility.AccessibilityHearingAidsFragment;
import com.android.settings.accessibility.AccessibilitySettings;
import com.android.settings.accessibility.AccessibilitySettingsForSetupWizard;
import com.android.settings.accessibility.AutoBrightnessPreferenceFragmentForSetupWizard;
import com.android.settings.accessibility.CaptioningPropertiesFragment;
import com.android.settings.accessibility.ColorAndMotionFragment;
import com.android.settings.accessibility.HearingDevicePairingFragment;
@@ -268,7 +267,6 @@ public class SettingsGateway {
EditShortcutsPreferenceFragment.class.getName(),
TextReadingPreferenceFragment.class.getName(),
TextReadingPreferenceFragmentForSetupWizard.class.getName(),
AutoBrightnessPreferenceFragmentForSetupWizard.class.getName(),
CaptioningPropertiesFragment.class.getName(),
ToggleDaltonizerPreferenceFragment.class.getName(),
ToggleColorInversionPreferenceFragment.class.getName(),

View File

@@ -41,4 +41,9 @@ public class AutoBrightnessPreferenceControllerForSetupWizard
}
return super.getAvailabilityStatus();
}
@Override
public CharSequence getSummary() {
return "";
}
}

View File

@@ -19,35 +19,43 @@ package com.android.settings.network
import android.content.Context
import android.net.wifi.WifiManager
import android.provider.Settings.Secure.ADAPTIVE_CONNECTIVITY_ENABLED
import androidx.preference.Preference
import com.android.settings.R
import com.android.settingslib.datastore.KeyValueStore
import com.android.settingslib.datastore.KeyedObservableDelegate
import com.android.settingslib.datastore.SettingsSecureStore
import com.android.settingslib.datastore.SettingsStore
import com.android.settingslib.metadata.MainSwitchPreference
import com.android.settingslib.metadata.PreferenceMetadata
import com.android.settingslib.preference.MainSwitchPreferenceBinding
// LINT.IfChange
class AdaptiveConnectivityTogglePreference :
MainSwitchPreference(
ADAPTIVE_CONNECTIVITY_ENABLED,
R.string.adaptive_connectivity_main_switch_title,
),
MainSwitchPreferenceBinding,
Preference.OnPreferenceChangeListener {
MainSwitchPreference(KEY, R.string.adaptive_connectivity_main_switch_title) {
override fun storage(context: Context) = SettingsSecureStore.get(context)
override fun storage(context: Context): KeyValueStore =
AdaptiveConnectivityToggleStorage(context, SettingsSecureStore.get(context))
override fun bind(preference: Preference, metadata: PreferenceMetadata) {
super.bind(preference, metadata)
preference.onPreferenceChangeListener = this
@Suppress("UNCHECKED_CAST")
private class AdaptiveConnectivityToggleStorage(
private val context: Context,
private val settingsStore: SettingsStore,
) : KeyedObservableDelegate<String>(settingsStore), KeyValueStore {
override fun contains(key: String) = settingsStore.contains(KEY)
override fun <T : Any> getDefaultValue(key: String, valueType: Class<T>) =
DEFAULT_VALUE as T
override fun <T : Any> getValue(key: String, valueType: Class<T>) =
(settingsStore.getBoolean(key) ?: DEFAULT_VALUE) as T
override fun <T : Any> setValue(key: String, valueType: Class<T>, value: T?) {
settingsStore.setBoolean(key, value as Boolean)
context.getSystemService(WifiManager::class.java)?.setWifiScoringEnabled(value)
}
}
override fun onPreferenceChange(preference: Preference, newValue: Any): Boolean {
val isChecked = newValue as Boolean
preference.context
.getSystemService(WifiManager::class.java)
?.setWifiScoringEnabled(isChecked)
return true
companion object {
const val KEY = ADAPTIVE_CONNECTIVITY_ENABLED
const val DEFAULT_VALUE = true
}
}
// LINT.ThenChange(AdaptiveConnectivityTogglePreferenceController.java)

View File

@@ -23,88 +23,21 @@ import android.app.settings.SettingsEnums;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.PersistableBundle;
import android.os.UserManager;
import android.provider.Telephony;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
import android.util.Log;
import androidx.annotation.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.spa.SpaActivity;
import java.util.Arrays;
import java.util.List;
/** Use to edit apn settings. */
public class ApnEditor extends SettingsPreferenceFragment {
private static final String TAG = ApnEditor.class.getSimpleName();
/**
* APN types for data connections. These are usage categories for an APN
* entry. One APN entry may support multiple APN types, eg, a single APN
* may service regular internet traffic ("default") as well as MMS-specific
* connections.<br/>
* APN_TYPE_ALL is a special type to indicate that this APN entry can
* service all data connections.
*/
public static final String APN_TYPE_ALL = "*";
/** APN type for default data traffic */
public static final String APN_TYPE_DEFAULT = "default";
/** APN type for MMS traffic */
public static final String APN_TYPE_MMS = "mms";
/** APN type for SUPL assisted GPS */
public static final String APN_TYPE_SUPL = "supl";
/** APN type for DUN traffic */
public static final String APN_TYPE_DUN = "dun";
/** APN type for HiPri traffic */
public static final String APN_TYPE_HIPRI = "hipri";
/** APN type for FOTA */
public static final String APN_TYPE_FOTA = "fota";
/** APN type for IMS */
public static final String APN_TYPE_IMS = "ims";
/** APN type for CBS */
public static final String APN_TYPE_CBS = "cbs";
/** APN type for IA Initial Attach APN */
public static final String APN_TYPE_IA = "ia";
/** APN type for Emergency PDN. This is not an IA apn, but is used
* for access to carrier services in an emergency call situation. */
public static final String APN_TYPE_EMERGENCY = "emergency";
/** APN type for Mission Critical Services */
public static final String APN_TYPE_MCX = "mcx";
/** APN type for XCAP */
public static final String APN_TYPE_XCAP = "xcap";
/** APN type for OEM_PAID networks (Automotive PANS) */
public static final String APN_TYPE_OEM_PAID = "oem_paid";
/** APN type for OEM_PRIVATE networks (Automotive PANS) */
public static final String APN_TYPE_OEM_PRIVATE = "oem_private";
/** Array of all APN types */
public static final String[] APN_TYPES = {APN_TYPE_DEFAULT,
APN_TYPE_MMS,
APN_TYPE_SUPL,
APN_TYPE_DUN,
APN_TYPE_HIPRI,
APN_TYPE_FOTA,
APN_TYPE_IMS,
APN_TYPE_CBS,
APN_TYPE_IA,
APN_TYPE_EMERGENCY,
APN_TYPE_MCX,
APN_TYPE_XCAP,
APN_TYPE_OEM_PAID,
APN_TYPE_OEM_PRIVATE,
};
/** Array of APN types that are never user-editable */
private static final String[] ALWAYS_READ_ONLY_APN_TYPES = new String[] {
APN_TYPE_OEM_PAID,
APN_TYPE_OEM_PRIVATE,
};
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
@@ -143,43 +76,6 @@ public class ApnEditor extends SettingsPreferenceFragment {
}
}
/**
* Fetch complete list of read only APN types.
*
* The list primarily comes from carrier config, but is also supplied by APN types which are
* always read only.
*/
static String[] getReadOnlyApnTypes(PersistableBundle b) {
String[] carrierReadOnlyApnTypes = b.getStringArray(
CarrierConfigManager.KEY_READ_ONLY_APN_TYPES_STRING_ARRAY);
return ArrayUtils.concat(String.class, carrierReadOnlyApnTypes, ALWAYS_READ_ONLY_APN_TYPES);
}
/**
* Check if passed in array of APN types indicates all APN types
* @param apnTypes array of APN types. "*" indicates all types.
* @return true if all apn types are included in the array, false otherwise
*/
static boolean hasAllApns(String[] apnTypes) {
if (ArrayUtils.isEmpty(apnTypes)) {
return false;
}
final List apnList = Arrays.asList(apnTypes);
if (apnList.contains(APN_TYPE_ALL)) {
Log.d(TAG, "hasAllApns: true because apnList.contains(APN_TYPE_ALL)");
return true;
}
for (String apn : APN_TYPES) {
if (!apnList.contains(apn)) {
return false;
}
}
Log.d(TAG, "hasAllApns: true");
return true;
}
@Override
public int getMetricsCategory() {
return SettingsEnums.APN_EDITOR;

View File

@@ -23,7 +23,6 @@ import android.app.Dialog;
import android.app.ProgressDialog;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
@@ -34,7 +33,6 @@ import android.provider.Telephony;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
import android.telephony.data.ApnSetting;
import android.text.TextUtils;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
@@ -51,7 +49,6 @@ import androidx.preference.PreferenceGroup;
import com.android.settings.R;
import com.android.settings.RestrictedSettingsFragment;
import com.android.settings.flags.Flags;
import com.android.settings.network.telephony.SubscriptionRepository;
import com.android.settings.spa.SpaActivity;
import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
@@ -59,6 +56,7 @@ import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
import kotlin.Unit;
import java.util.ArrayList;
import java.util.List;
/** Handle each different apn setting. */
public class ApnSettings extends RestrictedSettingsFragment
@@ -68,16 +66,12 @@ public class ApnSettings extends RestrictedSettingsFragment
public static final String APN_ID = "apn_id";
public static final String APN_LIST = "apn_list";
public static final String SUB_ID = "sub_id";
public static final String MVNO_TYPE = "mvno_type";
public static final String MVNO_MATCH_DATA = "mvno_match_data";
private static final String[] CARRIERS_PROJECTION = new String[] {
Telephony.Carriers._ID,
Telephony.Carriers.NAME,
Telephony.Carriers.APN,
Telephony.Carriers.TYPE,
Telephony.Carriers.MVNO_TYPE,
Telephony.Carriers.MVNO_MATCH_DATA,
Telephony.Carriers.EDITED_STATUS,
};
@@ -85,9 +79,7 @@ public class ApnSettings extends RestrictedSettingsFragment
private static final int NAME_INDEX = 1;
private static final int APN_INDEX = 2;
private static final int TYPES_INDEX = 3;
private static final int MVNO_TYPE_INDEX = 4;
private static final int MVNO_MATCH_DATA_INDEX = 5;
private static final int EDITED_INDEX = 6;
private static final int EDITED_INDEX = 4;
private static final int MENU_NEW = Menu.FIRST;
private static final int MENU_RESTORE = Menu.FIRST + 1;
@@ -101,8 +93,6 @@ public class ApnSettings extends RestrictedSettingsFragment
private PreferredApnRepository mPreferredApnRepository;
@Nullable
private String mPreferredApnKey;
private String mMvnoType;
private String mMvnoMatchData;
private boolean mUnavailable;
@@ -135,9 +125,9 @@ public class ApnSettings extends RestrictedSettingsFragment
mHideImsApn = b.getBoolean(CarrierConfigManager.KEY_HIDE_IMS_APN_BOOL);
mAllowAddingApns = b.getBoolean(CarrierConfigManager.KEY_ALLOW_ADDING_APNS_BOOL);
if (mAllowAddingApns) {
final String[] readOnlyApnTypes = ApnEditor.getReadOnlyApnTypes(b);
final List<String> readOnlyApnTypes = ApnTypes.getReadOnlyApnTypes(b);
// if no apn type can be edited, do not allow adding APNs
if (ApnEditor.hasAllApns(readOnlyApnTypes)) {
if (ApnTypes.hasAllApnTypes(readOnlyApnTypes)) {
Log.d(TAG, "not allowing adding APN because all APN types are read only");
mAllowAddingApns = false;
}
@@ -241,8 +231,6 @@ public class ApnSettings extends RestrictedSettingsFragment
final String key = cursor.getString(ID_INDEX);
final String type = cursor.getString(TYPES_INDEX);
final int edited = cursor.getInt(EDITED_INDEX);
mMvnoType = cursor.getString(MVNO_TYPE_INDEX);
mMvnoMatchData = cursor.getString(MVNO_MATCH_DATA_INDEX);
final ApnPreference pref = new ApnPreference(getPrefContext());
@@ -310,20 +298,9 @@ public class ApnSettings extends RestrictedSettingsFragment
}
private void addNewApn() {
if (Flags.newApnPageEnabled()) {
String route = ApnEditPageProvider.INSTANCE.getRoute(
INSERT_URL, Telephony.Carriers.CONTENT_URI, mSubId);
SpaActivity.startSpaActivity(getContext(), route);
} else {
final Intent intent = new Intent(Intent.ACTION_INSERT, Telephony.Carriers.CONTENT_URI);
intent.putExtra(SUB_ID, mSubId);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
if (!TextUtils.isEmpty(mMvnoType) && !TextUtils.isEmpty(mMvnoMatchData)) {
intent.putExtra(MVNO_TYPE, mMvnoType);
intent.putExtra(MVNO_MATCH_DATA, mMvnoMatchData);
}
startActivity(intent);
}
}
@Override

View File

@@ -25,6 +25,7 @@ import android.telephony.CarrierConfigManager
import android.util.Log
import com.android.settings.R
import com.android.settings.network.apn.ApnTypes.getPreSelectedApnType
import com.android.settings.network.apn.ApnTypes.getReadOnlyApnTypes
private const val TAG = "ApnStatus"
@@ -204,7 +205,7 @@ fun getCarrierCustomizedConfig(
CarrierConfigManager.KEY_ALLOW_ADDING_APNS_BOOL
)
val customizedConfig = CustomizedConfig(
readOnlyApnTypes = ApnEditor.getReadOnlyApnTypes(b)?.toList() ?: emptyList(),
readOnlyApnTypes = b.getReadOnlyApnTypes(),
readOnlyApnFields = b.getStringArray(
CarrierConfigManager.KEY_READ_ONLY_APN_FIELDS_STRING_ARRAY
)?.toList() ?: emptyList(),

View File

@@ -17,6 +17,8 @@
package com.android.settings.network.apn
import android.content.Context
import android.os.PersistableBundle
import android.telephony.CarrierConfigManager
import android.telephony.data.ApnSetting
import android.util.Log
import android.widget.Toast
@@ -51,9 +53,7 @@ object ApnTypes {
private fun splitToList(apnType: String): List<String> {
val types = apnType.split(',').map { it.trim().toLowerCase(Locale.current) }
if (ApnSetting.TYPE_ALL_STRING in types || APN_TYPES.all { it in types }) {
return listOf(ApnSetting.TYPE_ALL_STRING)
}
if (hasAllApnTypes(types)) return listOf(ApnSetting.TYPE_ALL_STRING)
return APN_TYPES.filter { it in types }
}
@@ -132,4 +132,32 @@ object ApnTypes {
private fun defaultPreSelectedApnTypes(readOnlyApnTypes: List<String>) =
if (ApnSetting.TYPE_ALL_STRING in readOnlyApnTypes) emptyList()
else PreSelectedTypes.filterNot { it in readOnlyApnTypes }
/** Array of APN types that are never user-editable */
private val ALWAYS_READ_ONLY_APN_TYPES =
arrayOf(ApnSetting.TYPE_OEM_PAID_STRING, ApnSetting.TYPE_OEM_PRIVATE_STRING)
/**
* Fetch complete list of read only APN types.
*
* The list primarily comes from carrier config, but is also supplied by APN types which are
* always read only.
*/
@JvmStatic
fun PersistableBundle.getReadOnlyApnTypes(): List<String> {
val carrierReadOnlyApnTypes =
getStringArray(CarrierConfigManager.KEY_READ_ONLY_APN_TYPES_STRING_ARRAY)?.toList()
?: emptyList()
return carrierReadOnlyApnTypes + ALWAYS_READ_ONLY_APN_TYPES
}
/**
* Check if passed in array of APN types indicates all APN types
*
* @param apnTypes array of APN types. "*" indicates all types.
* @return true if all apn types are included in the array, false otherwise
*/
@JvmStatic
fun hasAllApnTypes(apnTypes: List<String>): Boolean =
ApnSetting.TYPE_ALL_STRING in apnTypes || APN_TYPES.all { it in apnTypes }
}

View File

@@ -101,6 +101,8 @@ public class SoundPreferenceController extends NotificationPreferenceController
public boolean handlePreferenceTreeClick(Preference preference) {
if (KEY_SOUND.equals(preference.getKey()) && mFragment != null) {
NotificationSoundPreference pref = (NotificationSoundPreference) preference;
// default to notification
pref.setRingtoneType(RingtoneManager.TYPE_NOTIFICATION);
if (mChannel != null && mChannel.getAudioAttributes() != null) {
if (USAGE_ALARM == mChannel.getAudioAttributes().getUsage()) {
pref.setRingtoneType(RingtoneManager.TYPE_ALARM);

View File

@@ -18,6 +18,7 @@ package com.android.settings.notification.modes;
import android.annotation.Nullable;
import android.app.INotificationManager;
import android.app.ZenBypassingApp;
import android.content.ContentProvider;
import android.content.Context;
import android.content.pm.ParceledListSlice;
@@ -30,6 +31,7 @@ import android.os.UserManager;
import android.provider.ContactsContract;
import android.provider.ContactsContract.Contacts;
import android.service.notification.ConversationChannelWrapper;
import android.util.ArrayMap;
import android.util.Log;
import androidx.annotation.NonNull;
@@ -41,8 +43,9 @@ import com.google.common.collect.ImmutableList;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
/**
@@ -76,16 +79,20 @@ class ZenHelperBackend {
}
/**
* Returns all of a user's packages that have at least one channel that will bypass DND
* Returns a mapping between a user's packages that have at least one channel that will
* bypass DND, and a Boolean indicating whether all of the package's channels bypass.
*/
List<String> getPackagesBypassingDnd(int userId,
boolean includeConversationChannels) {
Map<String, Boolean> getPackagesBypassingDnd(int userId) {
Map<String, Boolean> bypassingAppsMap = new HashMap<>();
try {
return mInm.getPackagesBypassingDnd(userId, includeConversationChannels);
List<ZenBypassingApp> bypassingApps = mInm.getPackagesBypassingDnd(userId).getList();
for (ZenBypassingApp zba : bypassingApps) {
bypassingAppsMap.put(zba.getPkg(), zba.doAllChannelsBypass());
}
} catch (Exception e) {
Log.w(TAG, "Error calling NoMan", e);
return new ArrayList<>();
}
return bypassingAppsMap;
}
/** Returns all conversation channels for profiles of the current user. */

View File

@@ -22,7 +22,9 @@ import android.content.Context;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.UserHandle;
import android.os.UserManager;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import androidx.core.text.BidiFormatter;
@@ -35,7 +37,6 @@ import com.android.settings.R;
import com.android.settings.applications.AppInfoBase;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settings.core.SubSettingLauncher;
import com.android.settings.notification.NotificationBackend;
import com.android.settings.notification.app.AppChannelsBypassingDndSettings;
import com.android.settingslib.applications.AppUtils;
import com.android.settingslib.applications.ApplicationsState;
@@ -44,7 +45,9 @@ import com.android.settingslib.utils.ThreadUtils;
import com.android.settingslib.widget.AppPreference;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Adds a preference to the PreferenceScreen for each notification channel that can bypass DND.
@@ -54,7 +57,8 @@ public class ZenModeAllBypassingAppsPreferenceController extends AbstractPrefere
public static final String KEY_NO_APPS = "all_none";
private static final String KEY = "zen_mode_bypassing_apps_list";
@Nullable private final NotificationBackend mNotificationBackend;
@Nullable private final ZenHelperBackend mHelperBackend;
private final UserManager mUserManager;
@Nullable @VisibleForTesting ApplicationsState mApplicationsState;
@VisibleForTesting PreferenceCategory mPreferenceCategory;
@@ -64,18 +68,18 @@ public class ZenModeAllBypassingAppsPreferenceController extends AbstractPrefere
@Nullable private Fragment mHostFragment;
public ZenModeAllBypassingAppsPreferenceController(Context context, @Nullable Application app,
@Nullable Fragment host, @Nullable NotificationBackend notificationBackend) {
this(context, app == null ? null : ApplicationsState.getInstance(app), host,
notificationBackend);
@Nullable Fragment host, @Nullable ZenHelperBackend helperBackend) {
this(context, app == null ? null : ApplicationsState.getInstance(app), host, helperBackend);
}
private ZenModeAllBypassingAppsPreferenceController(Context context,
@Nullable ApplicationsState appState, @Nullable Fragment host,
@Nullable NotificationBackend notificationBackend) {
@Nullable ZenHelperBackend helperBackend) {
super(context);
mNotificationBackend = notificationBackend;
mApplicationsState = appState;
mHostFragment = host;
mHelperBackend = helperBackend;
mUserManager = context.getSystemService(UserManager.class);
if (mApplicationsState != null && host != null) {
mAppSession = mApplicationsState.newSession(mAppSessionCallbacks, host.getLifecycle());
@@ -140,19 +144,25 @@ public class ZenModeAllBypassingAppsPreferenceController extends AbstractPrefere
}
boolean doAnyAppsPassCriteria = false;
Map<Integer, Map<String, Boolean>> packagesBypassingDndByUser = new HashMap<>();
for (UserHandle userHandle : mUserManager.getUserProfiles()) {
packagesBypassingDndByUser.put(userHandle.getIdentifier(),
mHelperBackend.getPackagesBypassingDnd(userHandle.getIdentifier()));
}
for (ApplicationsState.AppEntry app : apps) {
String pkg = app.info.packageName;
final String key = getKey(pkg, app.info.uid);
final int appChannels = mNotificationBackend.getChannelCount(pkg, app.info.uid);
final int appChannelsBypassingDnd = mNotificationBackend
.getNotificationChannelsBypassingDnd(pkg, app.info.uid).getList().size();
if (appChannelsBypassingDnd > 0) {
boolean doesAppBypassDnd = false;
int userId = UserHandle.getUserId(app.info.uid);
Map<String, Boolean> packagesBypassingDnd =
packagesBypassingDndByUser.getOrDefault(userId, new HashMap<>());
if (packagesBypassingDnd.containsKey(pkg)) {
doAnyAppsPassCriteria = true;
doesAppBypassDnd = true;
}
Preference pref = mPreferenceCategory.findPreference(key);
if (pref == null) {
if (appChannelsBypassingDnd > 0) {
if (doesAppBypassDnd) {
// does not exist but should
pref = new AppPreference(mPrefContext);
pref.setKey(key);
@@ -172,14 +182,14 @@ public class ZenModeAllBypassingAppsPreferenceController extends AbstractPrefere
});
pref.setTitle(BidiFormatter.getInstance().unicodeWrap(app.label));
updateIcon(pref, app);
if (appChannels > appChannelsBypassingDnd) {
pref.setSummary(R.string.zen_mode_bypassing_apps_summary_some);
} else {
if (packagesBypassingDnd.get(pkg)) {
pref.setSummary(R.string.zen_mode_bypassing_apps_summary_all);
} else {
pref.setSummary(R.string.zen_mode_bypassing_apps_summary_some);
}
mPreferenceCategory.addPreference(pref);
}
} else if (appChannelsBypassingDnd == 0) {
} else if (!doesAppBypassDnd) {
// exists but shouldn't anymore
mPreferenceCategory.removePreference(pref);
}

View File

@@ -161,8 +161,7 @@ class ZenModeAppsLinkPreferenceController extends AbstractZenModePreferenceContr
Multimap<Integer, String> packagesBypassingDnd = HashMultimap.create();
for (UserHandle userHandle : mUserManager.getUserProfiles()) {
packagesBypassingDnd.putAll(userHandle.getIdentifier(),
mHelperBackend.getPackagesBypassingDnd(userHandle.getIdentifier(),
/* includeConversationChannels= */ false));
mHelperBackend.getPackagesBypassingDnd(userHandle.getIdentifier()).keySet());
}
return ImmutableList.copyOf(

View File

@@ -48,15 +48,17 @@ public class ZenModeSelectBypassingAppsFragment extends ZenModeFragmentBase impl
} else {
app = null;
}
return buildPreferenceControllers(context, app, this, new NotificationBackend());
return buildPreferenceControllers(context, app, this, new NotificationBackend(),
new ZenHelperBackend(context));
}
private static List<AbstractPreferenceController> buildPreferenceControllers(Context context,
@Nullable Application app, @Nullable Fragment host,
@Nullable NotificationBackend notificationBackend) {
@Nullable NotificationBackend notificationBackend,
@Nullable ZenHelperBackend zenHelperBackend) {
final List<AbstractPreferenceController> controllers = new ArrayList<>();
controllers.add(new ZenModeAllBypassingAppsPreferenceController(context, app, host,
notificationBackend));
zenHelperBackend));
controllers.add(new ZenModeAddBypassingAppsPreferenceController(context, app, host,
notificationBackend));
return controllers;
@@ -86,7 +88,7 @@ public class ZenModeSelectBypassingAppsFragment extends ZenModeFragmentBase impl
@Override
public List<AbstractPreferenceController> createPreferenceControllers(
Context context) {
return buildPreferenceControllers(context, null, null, null);
return buildPreferenceControllers(context, null, null, null, null);
}
};
}

View File

@@ -15,6 +15,8 @@
*/
package com.android.settings.notification.modes;
import static com.android.settings.Utils.createAccessibleSequence;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.widget.TextView;
@@ -28,6 +30,7 @@ import com.android.settingslib.RestrictedPreference;
import com.android.settingslib.Utils;
import com.android.settingslib.notification.modes.ZenIconLoader;
import com.android.settingslib.notification.modes.ZenMode;
import com.android.settingslib.notification.modes.ZenModeDescriptions;
import com.google.common.base.Strings;
@@ -42,6 +45,7 @@ class ZenModesListItemPreference extends RestrictedPreference {
private final Context mContext;
private final ZenIconLoader mIconLoader;
private final Executor mUiExecutor;
private final ZenModeDescriptions mDescriptions;
private ZenMode mZenMode;
private TextView mTitleView;
@@ -58,6 +62,7 @@ class ZenModesListItemPreference extends RestrictedPreference {
mContext = context;
mIconLoader = iconLoader;
mUiExecutor = uiExecutor;
mDescriptions = new ZenModeDescriptions(context);
setZenMode(zenMode);
setKey(zenMode.getId());
}
@@ -89,20 +94,17 @@ class ZenModesListItemPreference extends RestrictedPreference {
}
setTitle(mZenMode.getName());
String dynamicDescription = zenMode.getDynamicDescription(mContext);
CharSequence statusText = switch (mZenMode.getStatus()) {
case ENABLED_AND_ACTIVE ->
Strings.isNullOrEmpty(dynamicDescription)
? mContext.getString(R.string.zen_mode_active_text)
: mContext.getString(
R.string.zen_mode_format_status_and_trigger,
mContext.getString(R.string.zen_mode_active_text),
dynamicDescription);
case ENABLED -> dynamicDescription;
case DISABLED_BY_USER -> mContext.getString(R.string.zen_mode_disabled_by_user);
case DISABLED_BY_OTHER -> mContext.getString(R.string.zen_mode_disabled_needs_setup);
};
ZenMode.Status status = zenMode.getStatus();
String statusText = getStatusText(status, mDescriptions.getTriggerDescription(zenMode));
String triggerDescriptionForA11y = mDescriptions.getTriggerDescriptionForAccessibility(
zenMode);
if (triggerDescriptionForA11y != null) {
setSummary(createAccessibleSequence(statusText,
getStatusText(status, triggerDescriptionForA11y)));
} else {
setSummary(statusText);
}
setIconSize(ICON_SIZE_SMALL);
FutureUtil.whenDone(
@@ -116,6 +118,21 @@ class ZenModesListItemPreference extends RestrictedPreference {
updateTextColor(zenMode);
}
private String getStatusText(ZenMode.Status status, String triggerDescription) {
return switch (status) {
case ENABLED_AND_ACTIVE ->
Strings.isNullOrEmpty(triggerDescription)
? mContext.getString(R.string.zen_mode_active_text)
: mContext.getString(
R.string.zen_mode_format_status_and_trigger,
mContext.getString(R.string.zen_mode_active_text),
triggerDescription);
case ENABLED -> Strings.nullToEmpty(triggerDescription);
case DISABLED_BY_USER -> mContext.getString(R.string.zen_mode_disabled_by_user);
case DISABLED_BY_OTHER -> mContext.getString(R.string.zen_mode_disabled_needs_setup);
};
}
private void updateTextColor(@Nullable ZenMode zenMode) {
boolean isActive = zenMode != null && zenMode.isActive();
if (mTitleView != null) {

View File

@@ -1,119 +0,0 @@
/*
* Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.accessibility;
import static com.google.common.truth.Truth.assertThat;
import android.app.settings.SettingsEnums;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import androidx.fragment.app.FragmentFactory;
import androidx.fragment.app.testing.FragmentScenario;
import androidx.lifecycle.Lifecycle;
import androidx.preference.Preference;
import com.android.settings.R;
import com.android.settingslib.widget.FooterPreference;
import com.google.android.setupcompat.template.FooterBarMixin;
import com.google.android.setupdesign.GlifLayout;
import com.google.android.setupdesign.GlifPreferenceLayout;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
/** Tests for {@link AutoBrightnessPreferenceFragmentForSetupWizard}. */
@RunWith(RobolectricTestRunner.class)
public class AutoBrightnessPreferenceFragmentForSetupWizardTest {
// Same as AutoBrightnessPreferenceFragmentForSetupWizard#FOOTER_PREFERENCE_KEY
private static final String FOOTER_PREFERENCE_KEY = "auto_brightness_footer";
private FragmentScenario<AutoBrightnessPreferenceFragmentForSetupWizard> mFragmentScenario;
private AutoBrightnessPreferenceFragmentForSetupWizard mFragment;
private GlifLayout mGlifLayout;
@Before
public void setUp() {
mFragmentScenario = FragmentScenario
.launch(
AutoBrightnessPreferenceFragmentForSetupWizard.class,
/* fragmentArgs= */ (Bundle) null,
R.style.GlifTheme,
/* factory= */ (FragmentFactory) null)
.moveToState(Lifecycle.State.RESUMED);
mFragmentScenario.onFragment(fragment -> mFragment = fragment);
View view = mFragment.getView();
assertThat(view).isInstanceOf(GlifPreferenceLayout.class);
mGlifLayout = (GlifLayout) view;
}
@After
public void tearDown() {
mFragmentScenario.close();
}
@Test
public void onViewCreated_verifyGlifHerderText() {
assertThat(mGlifLayout.getHeaderText())
.isEqualTo(mFragment.getString(R.string.auto_brightness_title));
}
@Test
public void onViewCreated_verifyGlifFooter() {
FooterBarMixin footerMixin = mGlifLayout.getMixin(FooterBarMixin.class);
assertThat(footerMixin).isNotNull();
Button footerButton = footerMixin.getPrimaryButtonView();
assertThat(footerButton).isNotNull();
assertThat(footerButton.getText().toString()).isEqualTo(mFragment.getString(R.string.done));
footerButton.performClick();
assertThat(mFragment.getActivity().isFinishing()).isTrue();
}
@Test
public void onViewCreated_verifyFooterPreference() {
Preference pref = mFragment.findPreference(FOOTER_PREFERENCE_KEY);
assertThat(pref).isInstanceOf(FooterPreference.class);
FooterPreference footerPref = (FooterPreference) pref;
String exactTitle = footerPref.getTitle().toString();
assertThat(exactTitle).isEqualTo(mFragment.getString(R.string.auto_brightness_description));
// Ensure that footer content description has "About XXX" prefix for consistency with other
// accessibility suw pages
String expectedContentDescription =
mFragment.getString(R.string.auto_brightness_content_description_title)
+ "\n\n" + exactTitle;
assertThat(footerPref.getContentDescription().toString())
.isEqualTo(expectedContentDescription);
}
@Test
public void getMetricsCategory_returnsCorrectCategory() {
assertThat(mFragment.getMetricsCategory()).isEqualTo(
SettingsEnums.SUW_ACCESSIBILITY_AUTO_BRIGHTNESS);
}
}

View File

@@ -527,12 +527,12 @@ public class AudioSharingCallAudioPreferenceControllerTest {
shadowOf(Looper.getMainLooper()).idle();
assertThat(mPreference.getSummary().toString()).isEmpty();
// onReceiveStateChanged will update summary
// onSourceAdded will update summary
Settings.Secure.putInt(mContentResolver, TEST_SETTINGS_KEY, TEST_DEVICE_GROUP_ID1);
when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of(mDevice1));
when(mAssistant.getAllSources(any())).thenReturn(ImmutableList.of(mState));
mController.mBroadcastAssistantCallback.onReceiveStateChanged(
mDevice1, /* sourceId= */ 1, mState);
mController.mBroadcastAssistantCallback.onSourceAdded(mDevice1, /* sourceId= */
1, /* reason= */ 1);
shadowOf(Looper.getMainLooper()).idle();
assertThat(mPreference.getSummary().toString())
.isEqualTo(
@@ -557,8 +557,6 @@ public class AudioSharingCallAudioPreferenceControllerTest {
mController.mBroadcastAssistantCallback.onSearchStartFailed(/* reason= */ 1);
mController.mBroadcastAssistantCallback.onSearchStopped(/* reason= */ 1);
mController.mBroadcastAssistantCallback.onSearchStopFailed(/* reason= */ 1);
mController.mBroadcastAssistantCallback.onSourceAdded(
mDevice1, /* sourceId= */ 1, /* reason= */ 1);
mController.mBroadcastAssistantCallback.onSourceAddFailed(
mDevice1, mSource, /* reason= */ 1);
mController.mBroadcastAssistantCallback.onSourceRemoved(
@@ -572,6 +570,8 @@ public class AudioSharingCallAudioPreferenceControllerTest {
mController.mBroadcastAssistantCallback.onSourceFound(mSource);
mController.mBroadcastAssistantCallback.onSourceLost(/* broadcastId= */ 1);
shadowOf(Looper.getMainLooper()).idle();
mController.mBroadcastAssistantCallback.onReceiveStateChanged(mDevice1, /* sourceId= */ 1,
mState);
// Above callbacks won't update summary.
assertThat(mPreference.getSummary().toString()).isEmpty();

View File

@@ -521,21 +521,9 @@ public class AudioSharingDevicePreferenceControllerTest {
@Test
public void testBluetoothLeBroadcastAssistantCallbacks_updateGroup() {
// onReceiveStateChanged with unconnected state will do nothing
when(mState.getBisSyncState()).thenReturn(new ArrayList<>());
mController.mBroadcastAssistantCallback.onReceiveStateChanged(
mDevice, /* sourceId= */ 1, mState);
shadowOf(Looper.getMainLooper()).idle();
verify(mBluetoothDeviceUpdater, never()).forceUpdate();
verify(mDialogHandler, never()).closeOpeningDialogsForLeaDevice(mCachedDevice);
// onReceiveStateChanged with connected state will update group preference and handle
// stale dialogs
List<Long> bisSyncState = new ArrayList<>();
bisSyncState.add(1L);
when(mState.getBisSyncState()).thenReturn(bisSyncState);
mController.mBroadcastAssistantCallback.onReceiveStateChanged(
mDevice, /* sourceId= */ 1, mState);
// onSourceAdded will update group preference and handle stale dialogs
mController.mBroadcastAssistantCallback.onSourceAdded(mDevice, /* sourceId= */
1, /* reason= */ 1);
shadowOf(Looper.getMainLooper()).idle();
verify(mBluetoothDeviceUpdater).forceUpdate();
verify(mDialogHandler).closeOpeningDialogsForLeaDevice(mCachedDevice);
@@ -572,8 +560,13 @@ public class AudioSharingDevicePreferenceControllerTest {
mController.mBroadcastAssistantCallback.onSearchStartFailed(/* reason= */ 1);
mController.mBroadcastAssistantCallback.onSearchStopped(/* reason= */ 1);
mController.mBroadcastAssistantCallback.onSearchStopFailed(/* reason= */ 1);
mController.mBroadcastAssistantCallback.onSourceAdded(
mDevice, /* sourceId= */ 1, /* reason= */ 1);
List<Long> bisSyncState = new ArrayList<>();
bisSyncState.add(1L);
when(mState.getBisSyncState()).thenReturn(bisSyncState);
when(mBroadcast.getLatestBroadcastId()).thenReturn(1);
when(mState.getBroadcastId()).thenReturn(1);
mController.mBroadcastAssistantCallback.onReceiveStateChanged(mDevice, /* sourceId= */ 1,
mState);
mController.mBroadcastAssistantCallback.onSourceModified(
mDevice, /* sourceId= */ 1, /* reason= */ 1);
mController.mBroadcastAssistantCallback.onSourceModifyFailed(

View File

@@ -461,18 +461,9 @@ public class AudioSharingDeviceVolumeGroupControllerTest {
@Test
public void testBluetoothLeBroadcastAssistantCallbacks_updateGroup() {
when(mState.getBisSyncState()).thenReturn(new ArrayList<>());
// onReceiveStateChanged with unconnected state will do nothing
mController.mBroadcastAssistantCallback.onReceiveStateChanged(
mDevice1, /* sourceId= */ 1, mState);
verify(mDeviceUpdater, never()).forceUpdate();
// onReceiveStateChanged with connected state will update group preference
List<Long> bisSyncState = new ArrayList<>();
bisSyncState.add(1L);
when(mState.getBisSyncState()).thenReturn(bisSyncState);
mController.mBroadcastAssistantCallback.onReceiveStateChanged(
mDevice1, /* sourceId= */ 1, mState);
// onSourceAdded will update group preference
mController.mBroadcastAssistantCallback.onSourceAdded(mDevice1, /* sourceId= */
1, /* reason= */ 1);
verify(mDeviceUpdater).forceUpdate();
// onSourceRemoved will update group preference
@@ -487,8 +478,13 @@ public class AudioSharingDeviceVolumeGroupControllerTest {
mController.mBroadcastAssistantCallback.onSearchStartFailed(/* reason= */ 1);
mController.mBroadcastAssistantCallback.onSearchStopped(/* reason= */ 1);
mController.mBroadcastAssistantCallback.onSearchStopFailed(/* reason= */ 1);
mController.mBroadcastAssistantCallback.onSourceAdded(
mDevice1, /* sourceId= */ 1, /* reason= */ 1);
List<Long> bisSyncState = new ArrayList<>();
bisSyncState.add(1L);
when(mState.getBisSyncState()).thenReturn(bisSyncState);
when(mBroadcast.getLatestBroadcastId()).thenReturn(1);
when(mState.getBroadcastId()).thenReturn(1);
mController.mBroadcastAssistantCallback.onReceiveStateChanged(mDevice1, /* sourceId= */ 1,
mState);
mController.mBroadcastAssistantCallback.onSourceAddFailed(
mDevice1, mSource, /* reason= */ 1);
mController.mBroadcastAssistantCallback.onSourceRemoveFailed(

View File

@@ -476,7 +476,7 @@ public class AudioSharingSwitchBarControllerTest {
}
@Test
public void onPlaybackStarted_notInit_noDialog() {
public void onBroadcastMetadataChanged_notInit_noDialog() {
FeatureFlagUtils.setEnabled(
mContext, FeatureFlagUtils.SETTINGS_NEED_CONNECTED_BLE_DEVICE_FOR_BROADCAST, true);
when(mBtnView.isEnabled()).thenReturn(true);
@@ -503,7 +503,7 @@ public class AudioSharingSwitchBarControllerTest {
// No progress dialog.
assertThat(childFragments).isEmpty();
mController.mBroadcastCallback.onPlaybackStarted(0, 0);
mController.mBroadcastCallback.onBroadcastMetadataChanged(/* reason= */ 1, mMetadata);
shadowOf(Looper.getMainLooper()).idle();
verify(mFeatureFactory.metricsFeatureProvider)
@@ -515,7 +515,7 @@ public class AudioSharingSwitchBarControllerTest {
}
@Test
public void onPlaybackStarted_hasLocalSource_noDialog() {
public void onBroadcastMetadataChanged_hasLocalSource_noDialog() {
FeatureFlagUtils.setEnabled(
mContext, FeatureFlagUtils.SETTINGS_NEED_CONNECTED_BLE_DEVICE_FOR_BROADCAST, true);
when(mBtnView.isEnabled()).thenReturn(true);
@@ -533,7 +533,7 @@ public class AudioSharingSwitchBarControllerTest {
assertThat(childFragments).comparingElementsUsing(CLAZZNAME_EQUALS).containsExactly(
AudioSharingProgressDialogFragment.class.getName());
mController.mBroadcastCallback.onPlaybackStarted(0, 0);
mController.mBroadcastCallback.onBroadcastMetadataChanged(/* reason= */ 1, mMetadata);
shadowOf(Looper.getMainLooper()).idle();
verify(mAssistant, never()).addSource(any(), any(), anyBoolean());
@@ -549,7 +549,7 @@ public class AudioSharingSwitchBarControllerTest {
}
@Test
public void onPlaybackStarted_singleActiveDevice_showJoinAudioSharingDialog() {
public void onBroadcastMetadataChanged_singleActiveDevice_showJoinAudioSharingDialog() {
FeatureFlagUtils.setEnabled(
mContext, FeatureFlagUtils.SETTINGS_NEED_CONNECTED_BLE_DEVICE_FOR_BROADCAST, true);
when(mBtnView.isEnabled()).thenReturn(true);
@@ -566,15 +566,15 @@ public class AudioSharingSwitchBarControllerTest {
when(mBroadcast.isEnabled(null)).thenReturn(true);
when(mBroadcast.getLatestBluetoothLeBroadcastMetadata()).thenReturn(mMetadata);
mController.mBroadcastCallback.onPlaybackStarted(0, 0);
mController.mBroadcastCallback.onBroadcastMetadataChanged(/* reason= */ 1, mMetadata);
shadowOf(Looper.getMainLooper()).idle();
verify(mFeatureFactory.metricsFeatureProvider)
.action(any(Context.class), eq(SettingsEnums.ACTION_AUTO_JOIN_AUDIO_SHARING));
when(mState.getBisSyncState()).thenReturn(ImmutableList.of(1L));
mController.mBroadcastAssistantCallback.onReceiveStateChanged(mDevice2, /* sourceId= */ 1,
mState);
mController.mBroadcastAssistantCallback.onSourceAdded(mDevice2, /* sourceId= */
1, /* reason= */ 1);
shadowOf(Looper.getMainLooper()).idle();
childFragments = mParentFragment.getChildFragmentManager().getFragments();
@@ -613,7 +613,7 @@ public class AudioSharingSwitchBarControllerTest {
}
@Test
public void onPlaybackStarted_oneActiveOnConnected_showJoinAudioSharingDialog() {
public void onBroadcastMetadataChanged_oneActiveOnConnected_showJoinAudioSharingDialog() {
FeatureFlagUtils.setEnabled(
mContext, FeatureFlagUtils.SETTINGS_NEED_CONNECTED_BLE_DEVICE_FOR_BROADCAST, true);
when(mBtnView.isEnabled()).thenReturn(true);
@@ -635,7 +635,7 @@ public class AudioSharingSwitchBarControllerTest {
when(mBroadcast.isEnabled(null)).thenReturn(true);
when(mBroadcast.getLatestBluetoothLeBroadcastMetadata()).thenReturn(mMetadata);
mController.mBroadcastCallback.onPlaybackStarted(0, 0);
mController.mBroadcastCallback.onBroadcastMetadataChanged(/* reason= */ 1, mMetadata);
shadowOf(Looper.getMainLooper()).idle();
verify(mFeatureFactory.metricsFeatureProvider)
@@ -681,7 +681,7 @@ public class AudioSharingSwitchBarControllerTest {
}
@Test
public void onPlaybackStarted_oneActiveOnConnected_clickShareBtnOnDialog_addSource() {
public void onBroadcastMetadataChanged_oneActiveOnConnected_clickShareBtnOnDialog_addSource() {
FeatureFlagUtils.setEnabled(
mContext, FeatureFlagUtils.SETTINGS_NEED_CONNECTED_BLE_DEVICE_FOR_BROADCAST, true);
when(mBtnView.isEnabled()).thenReturn(true);
@@ -694,7 +694,7 @@ public class AudioSharingSwitchBarControllerTest {
verify(mBroadcast).startPrivateBroadcast();
when(mBroadcast.isEnabled(null)).thenReturn(true);
when(mBroadcast.getLatestBluetoothLeBroadcastMetadata()).thenReturn(mMetadata);
mController.mBroadcastCallback.onPlaybackStarted(0, 0);
mController.mBroadcastCallback.onBroadcastMetadataChanged(/* reason= */ 1, mMetadata);
shadowOf(Looper.getMainLooper()).idle();
verify(mAssistant).addSource(mDevice2, mMetadata, /* isGroupOp= */ false);
@@ -722,7 +722,7 @@ public class AudioSharingSwitchBarControllerTest {
}
@Test
public void onPlaybackStarted_oneActiveOnConnected_clickCancelBtnOnDialog_doNothing() {
public void onBroadcastMetadataChanged_oneActiveOnConnected_clickCancelBtnOnDialog_doNothing() {
FeatureFlagUtils.setEnabled(
mContext, FeatureFlagUtils.SETTINGS_NEED_CONNECTED_BLE_DEVICE_FOR_BROADCAST, true);
when(mBtnView.isEnabled()).thenReturn(true);
@@ -735,7 +735,7 @@ public class AudioSharingSwitchBarControllerTest {
verify(mBroadcast).startPrivateBroadcast();
when(mBroadcast.isEnabled(null)).thenReturn(true);
when(mBroadcast.getLatestBluetoothLeBroadcastMetadata()).thenReturn(mMetadata);
mController.mBroadcastCallback.onPlaybackStarted(0, 0);
mController.mBroadcastCallback.onBroadcastMetadataChanged(/* reason= */ 1, mMetadata);
shadowOf(Looper.getMainLooper()).idle();
verify(mAssistant).addSource(mDevice2, mMetadata, /* isGroupOp= */ false);
@@ -835,7 +835,7 @@ public class AudioSharingSwitchBarControllerTest {
when(mBroadcast.isEnabled(null)).thenReturn(true);
when(mBroadcast.getLatestBluetoothLeBroadcastMetadata()).thenReturn(mMetadata);
mController.mBroadcastCallback.onPlaybackStarted(0, 0);
mController.mBroadcastCallback.onBroadcastMetadataChanged(/* reason= */ 1, mMetadata);
shadowOf(Looper.getMainLooper()).idle();
verify(mAssistant).addSource(mDevice2, mMetadata, /* isGroupOp= */ false);
@@ -868,16 +868,15 @@ public class AudioSharingSwitchBarControllerTest {
}
@Test
public void testAssistantCallbacks_onReceiveStateChanged_dismissProgressDialog() {
public void testAssistantCallbacks_onSourceAdded_dismissProgressDialog() {
AudioSharingProgressDialogFragment.show(mParentFragment, TEST_DEVICE_NAME1);
shadowOf(Looper.getMainLooper()).idle();
List<Fragment> childFragments = mParentFragment.getChildFragmentManager().getFragments();
assertThat(childFragments).comparingElementsUsing(CLAZZNAME_EQUALS).containsExactly(
AudioSharingProgressDialogFragment.class.getName());
when(mState.getBisSyncState()).thenReturn(ImmutableList.of(1L));
mController.mBroadcastAssistantCallback.onReceiveStateChanged(mDevice1, /* sourceId= */ 1,
mState);
mController.mBroadcastAssistantCallback.onSourceAdded(mDevice1, /* sourceId= */
1, /* reason= */ 1);
shadowOf(Looper.getMainLooper()).idle();
childFragments = mParentFragment.getChildFragmentManager().getFragments();
assertThat(childFragments).isEmpty();
@@ -892,8 +891,6 @@ public class AudioSharingSwitchBarControllerTest {
mController.mBroadcastAssistantCallback.onSearchStartFailed(/* reason= */ 1);
mController.mBroadcastAssistantCallback.onSearchStopped(/* reason= */ 1);
mController.mBroadcastAssistantCallback.onSearchStopFailed(/* reason= */ 1);
mController.mBroadcastAssistantCallback.onSourceAdded(
mDevice1, /* sourceId= */ 1, /* reason= */ 1);
mController.mBroadcastAssistantCallback.onSourceRemoved(
mDevice1, /* sourceId= */ 1, /* reason= */ 1);
mController.mBroadcastAssistantCallback.onSourceRemoveFailed(
@@ -1013,7 +1010,7 @@ public class AudioSharingSwitchBarControllerTest {
shadowOf(Looper.getMainLooper()).idle();
verify(mBroadcast).startPrivateBroadcast();
mController.mBroadcastCallback.onPlaybackStarted(0, 0);
mController.mBroadcastCallback.onBroadcastMetadataChanged(/* reason= */ 1, mMetadata);
shadowOf(Looper.getMainLooper()).idle();
verify(mFeatureFactory.metricsFeatureProvider)

View File

@@ -17,6 +17,7 @@
package com.android.settings.connecteddevice.audiosharing.audiostreams;
import static com.android.settingslib.flags.Flags.FLAG_AUDIO_SHARING_HYSTERESIS_MODE_FIX;
import static com.android.settingslib.flags.Flags.FLAG_ENABLE_LE_AUDIO_SHARING;
import static com.google.common.truth.Truth.assertThat;
@@ -31,10 +32,12 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.settings.SettingsEnums;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothLeBroadcastAssistant;
import android.bluetooth.BluetoothLeBroadcastMetadata;
import android.bluetooth.BluetoothLeBroadcastReceiveState;
import android.bluetooth.BluetoothStatusCodes;
import android.content.Context;
import android.platform.test.flag.junit.SetFlagsRule;
import android.view.View;
@@ -46,6 +49,7 @@ import androidx.test.core.app.ApplicationProvider;
import com.android.settings.R;
import com.android.settings.connecteddevice.audiosharing.audiostreams.testshadows.ShadowAudioStreamsHelper;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
import com.android.settings.testutils.shadow.ShadowThreadUtils;
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant;
import com.android.settingslib.core.lifecycle.Lifecycle;
@@ -62,6 +66,7 @@ import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
import org.robolectric.shadow.api.Shadow;
import java.util.ArrayList;
import java.util.Collections;
@@ -73,6 +78,7 @@ import java.util.concurrent.Executor;
shadows = {
ShadowThreadUtils.class,
ShadowAudioStreamsHelper.class,
ShadowBluetoothAdapter.class,
})
public class AudioStreamButtonControllerTest {
@Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
@@ -95,6 +101,13 @@ public class AudioStreamButtonControllerTest {
@Before
public void setUp() {
mSetFlagsRule.disableFlags(FLAG_AUDIO_SHARING_HYSTERESIS_MODE_FIX);
ShadowBluetoothAdapter shadowBluetoothAdapter = Shadow.extract(
BluetoothAdapter.getDefaultAdapter());
shadowBluetoothAdapter.setEnabled(true);
shadowBluetoothAdapter.setIsLeAudioBroadcastSourceSupported(
BluetoothStatusCodes.FEATURE_SUPPORTED);
shadowBluetoothAdapter.setIsLeAudioBroadcastAssistantSupported(
BluetoothStatusCodes.FEATURE_SUPPORTED);
ShadowAudioStreamsHelper.setUseMock(mAudioStreamsHelper);
when(mAudioStreamsHelper.getLeBroadcastAssistant()).thenReturn(mAssistant);
mFeatureFactory = FakeFeatureFactory.setupForTest();
@@ -261,6 +274,7 @@ public class AudioStreamButtonControllerTest {
@Test
public void testCallback_onReceiveStateChangedWithSourcePresent_updateButton() {
mSetFlagsRule.enableFlags(FLAG_ENABLE_LE_AUDIO_SHARING);
mSetFlagsRule.enableFlags(FLAG_AUDIO_SHARING_HYSTERESIS_MODE_FIX);
String address = "11:22:33:44:55:66";

View File

@@ -20,6 +20,7 @@ import static com.android.settings.connecteddevice.audiosharing.audiostreams.Aud
import static com.android.settings.connecteddevice.audiosharing.audiostreams.AudioStreamHeaderController.AUDIO_STREAM_HEADER_NOT_LISTENING_SUMMARY;
import static com.android.settings.connecteddevice.audiosharing.audiostreams.AudioStreamHeaderController.AUDIO_STREAM_HEADER_PRESENT_NOW_SUMMARY;
import static com.android.settingslib.flags.Flags.FLAG_AUDIO_SHARING_HYSTERESIS_MODE_FIX;
import static com.android.settingslib.flags.Flags.FLAG_ENABLE_LE_AUDIO_SHARING;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
@@ -28,9 +29,11 @@ import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothLeBroadcastAssistant;
import android.bluetooth.BluetoothLeBroadcastReceiveState;
import android.bluetooth.BluetoothStatusCodes;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.platform.test.flag.junit.SetFlagsRule;
@@ -41,6 +44,7 @@ import androidx.test.core.app.ApplicationProvider;
import com.android.settings.connecteddevice.audiosharing.audiostreams.testshadows.ShadowAudioStreamsHelper;
import com.android.settings.connecteddevice.audiosharing.audiostreams.testshadows.ShadowEntityHeaderController;
import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
import com.android.settings.testutils.shadow.ShadowThreadUtils;
import com.android.settings.widget.EntityHeaderController;
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant;
@@ -57,6 +61,7 @@ import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
import org.robolectric.shadow.api.Shadow;
import java.util.ArrayList;
import java.util.Collections;
@@ -69,6 +74,7 @@ import java.util.concurrent.Executor;
ShadowEntityHeaderController.class,
ShadowThreadUtils.class,
ShadowAudioStreamsHelper.class,
ShadowBluetoothAdapter.class,
})
public class AudioStreamHeaderControllerTest {
@Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
@@ -93,6 +99,13 @@ public class AudioStreamHeaderControllerTest {
@Before
public void setUp() {
mSetFlagsRule.disableFlags(FLAG_AUDIO_SHARING_HYSTERESIS_MODE_FIX);
ShadowBluetoothAdapter shadowBluetoothAdapter = Shadow.extract(
BluetoothAdapter.getDefaultAdapter());
shadowBluetoothAdapter.setEnabled(true);
shadowBluetoothAdapter.setIsLeAudioBroadcastSourceSupported(
BluetoothStatusCodes.FEATURE_SUPPORTED);
shadowBluetoothAdapter.setIsLeAudioBroadcastAssistantSupported(
BluetoothStatusCodes.FEATURE_SUPPORTED);
ShadowEntityHeaderController.setUseMock(mHeaderController);
ShadowAudioStreamsHelper.setUseMock(mAudioStreamsHelper);
@@ -260,6 +273,7 @@ public class AudioStreamHeaderControllerTest {
@Test
public void testCallback_onReceiveStateChangedWithSourcePresent_updateButton() {
mSetFlagsRule.enableFlags(FLAG_ENABLE_LE_AUDIO_SHARING);
mSetFlagsRule.enableFlags(FLAG_AUDIO_SHARING_HYSTERESIS_MODE_FIX);
String address = "11:22:33:44:55:66";

View File

@@ -17,6 +17,7 @@
package com.android.settings.connecteddevice.audiosharing.audiostreams;
import static com.android.settingslib.flags.Flags.FLAG_AUDIO_SHARING_HYSTERESIS_MODE_FIX;
import static com.android.settingslib.flags.Flags.FLAG_ENABLE_LE_AUDIO_SHARING;
import static com.google.common.truth.Truth.assertThat;
@@ -31,6 +32,8 @@ import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothStatusCodes;
import android.content.Context;
import android.platform.test.flag.junit.SetFlagsRule;
import android.text.SpannableString;
@@ -38,6 +41,8 @@ import android.text.SpannableString;
import androidx.preference.Preference;
import androidx.test.core.app.ApplicationProvider;
import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -47,8 +52,14 @@ import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
import org.robolectric.shadow.api.Shadow;
@RunWith(RobolectricTestRunner.class)
@Config(
shadows = {
ShadowBluetoothAdapter.class,
})
public class AudioStreamStateHandlerTest {
@Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
@Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
@@ -64,6 +75,13 @@ public class AudioStreamStateHandlerTest {
@Before
public void setUp() {
mSetFlagsRule.disableFlags(FLAG_AUDIO_SHARING_HYSTERESIS_MODE_FIX);
ShadowBluetoothAdapter shadowBluetoothAdapter = Shadow.extract(
BluetoothAdapter.getDefaultAdapter());
shadowBluetoothAdapter.setEnabled(true);
shadowBluetoothAdapter.setIsLeAudioBroadcastSourceSupported(
BluetoothStatusCodes.FEATURE_SUPPORTED);
shadowBluetoothAdapter.setIsLeAudioBroadcastAssistantSupported(
BluetoothStatusCodes.FEATURE_SUPPORTED);
mHandler = spy(new AudioStreamStateHandler());
}
@@ -109,6 +127,7 @@ public class AudioStreamStateHandlerTest {
@Test
public void testHandleStateChange_setNewState_sourcePresent() {
mSetFlagsRule.enableFlags(FLAG_ENABLE_LE_AUDIO_SHARING);
mSetFlagsRule.enableFlags(FLAG_AUDIO_SHARING_HYSTERESIS_MODE_FIX);
when(mHandler.getStateEnum())

View File

@@ -135,47 +135,47 @@ public class AudioStreamsCategoryControllerTest {
@Test
public void getAvailabilityStatus_flagOn() {
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_QR_CODE_PRIVATE_BROADCAST_SHARING);
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
}
@Test
public void getAvailabilityStatus_flagOff() {
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_QR_CODE_PRIVATE_BROADCAST_SHARING);
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
}
@Test
public void onStart_flagOff_doNothing() {
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_QR_CODE_PRIVATE_BROADCAST_SHARING);
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
mController.onStart(mLifecycleOwner);
verify(mBluetoothEventManager, never()).registerCallback(any());
}
@Test
public void onStart_flagOn_registerCallback() {
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_QR_CODE_PRIVATE_BROADCAST_SHARING);
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
mController.onStart(mLifecycleOwner);
verify(mBluetoothEventManager).registerCallback(any());
}
@Test
public void onStop_flagOff_doNothing() {
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_QR_CODE_PRIVATE_BROADCAST_SHARING);
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
mController.onStop(mLifecycleOwner);
verify(mBluetoothEventManager, never()).unregisterCallback(any());
}
@Test
public void onStop_flagOn_unregisterCallback() {
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_QR_CODE_PRIVATE_BROADCAST_SHARING);
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
mController.onStop(mLifecycleOwner);
verify(mBluetoothEventManager).unregisterCallback(any());
}
@Test
public void updateVisibility_flagOff_invisible() {
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_QR_CODE_PRIVATE_BROADCAST_SHARING);
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
mController.updateVisibility();
shadowOf(Looper.getMainLooper()).idle();
assertThat(mPreference.isVisible()).isFalse();
@@ -183,7 +183,7 @@ public class AudioStreamsCategoryControllerTest {
@Test
public void updateVisibility_noConnectedLe_invisible() {
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_QR_CODE_PRIVATE_BROADCAST_SHARING);
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
mController.updateVisibility();
shadowOf(Looper.getMainLooper()).idle();
assertThat(mPreference.isVisible()).isFalse();
@@ -191,7 +191,7 @@ public class AudioStreamsCategoryControllerTest {
@Test
public void updateVisibility_isNotProfileReady_invisible() {
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_QR_CODE_PRIVATE_BROADCAST_SHARING);
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
ShadowAudioStreamsHelper.setCachedBluetoothDeviceInSharingOrLeConnected(
mCachedBluetoothDevice);
when(mVolumeControl.isProfileReady()).thenReturn(false);
@@ -202,7 +202,7 @@ public class AudioStreamsCategoryControllerTest {
@Test
public void updateVisibility_isBroadcasting_invisible() {
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_QR_CODE_PRIVATE_BROADCAST_SHARING);
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
ShadowAudioStreamsHelper.setCachedBluetoothDeviceInSharingOrLeConnected(
mCachedBluetoothDevice);
when(mBroadcast.isEnabled(any())).thenReturn(true);
@@ -213,7 +213,7 @@ public class AudioStreamsCategoryControllerTest {
@Test
public void updateVisibility_isBluetoothOff_invisible() {
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_QR_CODE_PRIVATE_BROADCAST_SHARING);
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
ShadowAudioStreamsHelper.setCachedBluetoothDeviceInSharingOrLeConnected(
mCachedBluetoothDevice);
mShadowBluetoothAdapter.setEnabled(false);
@@ -224,7 +224,7 @@ public class AudioStreamsCategoryControllerTest {
@Test
public void updateVisibility_visible() {
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_QR_CODE_PRIVATE_BROADCAST_SHARING);
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
ShadowAudioStreamsHelper.setCachedBluetoothDeviceInSharingOrLeConnected(
mCachedBluetoothDevice);
mController.displayPreference(mScreen);
@@ -235,7 +235,7 @@ public class AudioStreamsCategoryControllerTest {
@Test
public void onProfileConnectionStateChanged_updateVisibility() {
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_QR_CODE_PRIVATE_BROADCAST_SHARING);
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
ArgumentCaptor<BluetoothCallback> argumentCaptor =
ArgumentCaptor.forClass(BluetoothCallback.class);
mController.onStart(mLifecycleOwner);

View File

@@ -20,6 +20,7 @@ import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static com.android.settingslib.flags.Flags.FLAG_AUDIO_SHARING_HYSTERESIS_MODE_FIX;
import static com.android.settingslib.flags.Flags.FLAG_ENABLE_LE_AUDIO_SHARING;
import static com.google.common.truth.Truth.assertThat;
@@ -33,9 +34,11 @@ import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothLeBroadcastMetadata;
import android.bluetooth.BluetoothLeBroadcastReceiveState;
import android.bluetooth.BluetoothStatusCodes;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
@@ -45,6 +48,7 @@ import androidx.fragment.app.FragmentActivity;
import androidx.test.core.app.ApplicationProvider;
import com.android.settings.R;
import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
import com.android.settings.testutils.shadow.ShadowThreadUtils;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
@@ -65,6 +69,7 @@ import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
import org.robolectric.shadow.api.Shadow;
import java.util.ArrayList;
import java.util.Collections;
@@ -74,6 +79,7 @@ import java.util.List;
@Config(
shadows = {
ShadowThreadUtils.class,
ShadowBluetoothAdapter.class,
})
public class AudioStreamsHelperTest {
@Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
@@ -97,6 +103,13 @@ public class AudioStreamsHelperTest {
@Before
public void setUp() {
mSetFlagsRule.disableFlags(FLAG_AUDIO_SHARING_HYSTERESIS_MODE_FIX);
ShadowBluetoothAdapter shadowBluetoothAdapter = Shadow.extract(
BluetoothAdapter.getDefaultAdapter());
shadowBluetoothAdapter.setEnabled(true);
shadowBluetoothAdapter.setIsLeAudioBroadcastSourceSupported(
BluetoothStatusCodes.FEATURE_SUPPORTED);
shadowBluetoothAdapter.setIsLeAudioBroadcastAssistantSupported(
BluetoothStatusCodes.FEATURE_SUPPORTED);
when(mLocalBluetoothManager.getProfileManager()).thenReturn(mLocalBluetoothProfileManager);
when(mLocalBluetoothManager.getCachedDeviceManager()).thenReturn(mDeviceManager);
when(mLocalBluetoothProfileManager.getLeAudioBroadcastAssistantProfile())
@@ -229,6 +242,7 @@ public class AudioStreamsHelperTest {
@Test
public void getAllPresentSources_noSource() {
mSetFlagsRule.enableFlags(FLAG_ENABLE_LE_AUDIO_SHARING);
mSetFlagsRule.enableFlags(FLAG_AUDIO_SHARING_HYSTERESIS_MODE_FIX);
List<BluetoothDevice> devices = new ArrayList<>();
@@ -251,6 +265,7 @@ public class AudioStreamsHelperTest {
@Test
public void getAllPresentSources_returnSource() {
mSetFlagsRule.enableFlags(FLAG_ENABLE_LE_AUDIO_SHARING);
mSetFlagsRule.enableFlags(FLAG_AUDIO_SHARING_HYSTERESIS_MODE_FIX);
String address = "11:22:33:44:55:66";

View File

@@ -17,6 +17,7 @@
package com.android.settings.connecteddevice.audiosharing.audiostreams;
import static com.android.settingslib.flags.Flags.FLAG_AUDIO_SHARING_HYSTERESIS_MODE_FIX;
import static com.android.settingslib.flags.Flags.FLAG_ENABLE_LE_AUDIO_SHARING;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
@@ -24,11 +25,18 @@ import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothLeBroadcastMetadata;
import android.bluetooth.BluetoothLeBroadcastReceiveState;
import android.bluetooth.BluetoothStatusCodes;
import android.content.Context;
import android.platform.test.flag.junit.SetFlagsRule;
import androidx.test.core.app.ApplicationProvider;
import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -37,15 +45,21 @@ import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
import org.robolectric.shadow.api.Shadow;
import java.util.ArrayList;
import java.util.List;
@RunWith(RobolectricTestRunner.class)
@Config(
shadows = {
ShadowBluetoothAdapter.class,
})
public class AudioStreamsProgressCategoryCallbackTest {
@Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
@Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
private final Context mContext = ApplicationProvider.getApplicationContext();
@Mock private AudioStreamsProgressCategoryController mController;
@Mock private BluetoothDevice mDevice;
@Mock private BluetoothLeBroadcastReceiveState mState;
@@ -56,7 +70,14 @@ public class AudioStreamsProgressCategoryCallbackTest {
@Before
public void setUp() {
mSetFlagsRule.disableFlags(FLAG_AUDIO_SHARING_HYSTERESIS_MODE_FIX);
mCallback = new AudioStreamsProgressCategoryCallback(mController);
ShadowBluetoothAdapter shadowBluetoothAdapter = Shadow.extract(
BluetoothAdapter.getDefaultAdapter());
shadowBluetoothAdapter.setEnabled(true);
shadowBluetoothAdapter.setIsLeAudioBroadcastSourceSupported(
BluetoothStatusCodes.FEATURE_SUPPORTED);
shadowBluetoothAdapter.setIsLeAudioBroadcastAssistantSupported(
BluetoothStatusCodes.FEATURE_SUPPORTED);
mCallback = new AudioStreamsProgressCategoryCallback(mContext, mController);
}
@Test
@@ -71,6 +92,7 @@ public class AudioStreamsProgressCategoryCallbackTest {
@Test
public void testOnReceiveStateChanged_sourcePresent() {
mSetFlagsRule.enableFlags(FLAG_ENABLE_LE_AUDIO_SHARING);
mSetFlagsRule.enableFlags(FLAG_AUDIO_SHARING_HYSTERESIS_MODE_FIX);
String address = "11:22:33:44:55:66";

View File

@@ -26,6 +26,7 @@ import static com.android.settings.connecteddevice.audiosharing.audiostreams.Aud
import static com.android.settings.connecteddevice.audiosharing.audiostreams.AudioStreamsProgressCategoryController.UNSET_BROADCAST_ID;
import static com.android.settings.core.BasePreferenceController.AVAILABLE;
import static com.android.settingslib.flags.Flags.FLAG_AUDIO_SHARING_HYSTERESIS_MODE_FIX;
import static com.android.settingslib.flags.Flags.FLAG_ENABLE_LE_AUDIO_SHARING;
import static com.google.common.truth.Truth.assertThat;
@@ -48,6 +49,7 @@ import android.bluetooth.BluetoothLeAudioContentMetadata;
import android.bluetooth.BluetoothLeBroadcastMetadata;
import android.bluetooth.BluetoothLeBroadcastReceiveState;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothStatusCodes;
import android.content.Context;
import android.os.Looper;
import android.platform.test.flag.junit.SetFlagsRule;
@@ -62,6 +64,7 @@ import androidx.test.core.app.ApplicationProvider;
import com.android.settings.R;
import com.android.settings.connecteddevice.audiosharing.audiostreams.testshadows.ShadowAudioStreamsHelper;
import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
import com.android.settings.testutils.shadow.ShadowBluetoothUtils;
import com.android.settings.testutils.shadow.ShadowThreadUtils;
import com.android.settingslib.bluetooth.BluetoothEventManager;
@@ -84,6 +87,7 @@ import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
import org.robolectric.shadow.api.Shadow;
import org.robolectric.shadows.ShadowAlertDialog;
import org.robolectric.shadows.androidx.fragment.FragmentController;
@@ -97,6 +101,7 @@ import java.util.List;
ShadowAudioStreamsHelper.class,
ShadowThreadUtils.class,
ShadowAlertDialog.class,
ShadowBluetoothAdapter.class,
})
public class AudioStreamsProgressCategoryControllerTest {
@Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
@@ -129,6 +134,13 @@ public class AudioStreamsProgressCategoryControllerTest {
@Before
public void setUp() {
ShadowBluetoothAdapter shadowBluetoothAdapter = Shadow.extract(
BluetoothAdapter.getDefaultAdapter());
shadowBluetoothAdapter.setEnabled(true);
shadowBluetoothAdapter.setIsLeAudioBroadcastSourceSupported(
BluetoothStatusCodes.FEATURE_SUPPORTED);
shadowBluetoothAdapter.setIsLeAudioBroadcastAssistantSupported(
BluetoothStatusCodes.FEATURE_SUPPORTED);
ShadowAudioStreamsHelper.setUseMock(mAudioStreamsHelper);
when(mAudioStreamsHelper.getLeBroadcastAssistant()).thenReturn(mLeBroadcastAssistant);
when(mAudioStreamsHelper.getAllConnectedSources()).thenReturn(emptyList());
@@ -292,6 +304,7 @@ public class AudioStreamsProgressCategoryControllerTest {
@Test
public void testOnStart_initHasDevice_getPresentSources() {
mSetFlagsRule.enableFlags(FLAG_ENABLE_LE_AUDIO_SHARING);
mSetFlagsRule.enableFlags(FLAG_AUDIO_SHARING_HYSTERESIS_MODE_FIX);
// Setup a device

View File

@@ -17,68 +17,90 @@
package com.android.settings.network
import android.content.Context
import android.content.ContextWrapper
import android.net.wifi.WifiManager
import android.platform.test.flag.junit.SetFlagsRule
import android.provider.Settings
import android.provider.Settings.Secure.ADAPTIVE_CONNECTIVITY_ENABLED
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.settingslib.preference.createAndBindWidget
import com.android.settingslib.widget.MainSwitchPreference
import com.google.common.truth.Truth.assertThat
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.kotlin.atLeastOnce
import org.mockito.kotlin.mock
import org.mockito.kotlin.spy
import org.mockito.kotlin.verify
import org.mockito.kotlin.whenever
// LINT.IfChange
@RunWith(AndroidJUnit4::class)
class AdaptiveConnectivityTogglePreferenceTest {
@get:Rule
val setFlagsRule = SetFlagsRule()
private val mockWifiManager = mock<WifiManager>()
private val appContext: Context = spy(ApplicationProvider.getApplicationContext()){}
private val mockWifiManager: WifiManager = mock()
private val context: Context =
object : ContextWrapper(ApplicationProvider.getApplicationContext()) {
override fun getSystemService(name: String): Any? =
when {
name == getSystemServiceName(WifiManager::class.java) -> mockWifiManager
else -> super.getSystemService(name)
}
}
private val adaptiveConnectivityTogglePreference = AdaptiveConnectivityTogglePreference()
@Before
fun setUp() {
whenever(appContext.getSystemService(WifiManager::class.java)).thenReturn(mockWifiManager)
@Test
fun switchClick_defaultDisabled_returnFalse() {
setAdaptiveConnectivityEnabled(false)
assertThat(getMainSwitchPreference().isChecked).isFalse()
}
@Test
fun setChecked_withTrue_shouldUpdateSetting() {
Settings.Secure.putInt(
appContext.contentResolver,
Settings.Secure.ADAPTIVE_CONNECTIVITY_ENABLED, 0
)
fun switchClick_defaultEnabled_returnTrue() {
setAdaptiveConnectivityEnabled(true)
val mainSwitchPreference = getMainSwitchPreferenceCompat().apply { performClick() }
assertThat(mainSwitchPreference.isChecked).isTrue()
verify(mockWifiManager, atLeastOnce()).setWifiScoringEnabled(true)
assertThat(getMainSwitchPreference().isChecked).isTrue()
}
@Test
fun setChecked_withFalse_shouldUpdateSetting() {
Settings.Secure.putInt(
appContext.contentResolver,
Settings.Secure.ADAPTIVE_CONNECTIVITY_ENABLED, 1
)
fun setChecked_defaultEnabled_updatesCorrectly() {
val preference = getMainSwitchPreference()
assertThat(preference.isChecked).isTrue()
val mainSwitchPreference = getMainSwitchPreferenceCompat().apply { performClick() }
preference.performClick()
assertThat(mainSwitchPreference.isChecked).isFalse()
assertThat(preference.isChecked).isFalse()
preference.performClick()
assertThat(preference.isChecked).isTrue()
}
@Test
fun storeSetTrue_wifiManagerSetWifiScoringEnabled() {
setAdaptiveConnectivityEnabled(true)
assertThat(getAdaptiveConnectivityEnabled()).isTrue()
verify(mockWifiManager).setWifiScoringEnabled(true)
}
@Test
fun storeSetFalse_wifiManagerSetWifiScoringDisabled() {
setAdaptiveConnectivityEnabled(false)
assertThat(getAdaptiveConnectivityEnabled()).isFalse()
verify(mockWifiManager).setWifiScoringEnabled(false)
}
private fun getMainSwitchPreferenceCompat(): MainSwitchPreference =
adaptiveConnectivityTogglePreference.createAndBindWidget(appContext)
private fun getMainSwitchPreference(): MainSwitchPreference =
adaptiveConnectivityTogglePreference.createAndBindWidget(context)
private fun setAdaptiveConnectivityEnabled(enabled: Boolean) =
adaptiveConnectivityTogglePreference
.storage(context)
.setValue(ADAPTIVE_CONNECTIVITY_ENABLED, Boolean::class.javaObjectType, enabled)
private fun getAdaptiveConnectivityEnabled() =
adaptiveConnectivityTogglePreference
.storage(context)
.getValue(ADAPTIVE_CONNECTIVITY_ENABLED, Boolean::class.javaObjectType)
}
// LINT.ThenChange(AdaptiveConnectivityTogglePreferenceControllerTest.java)

View File

@@ -302,6 +302,26 @@ public class SoundPreferenceControllerTest {
RingtoneManager.EXTRA_RINGTONE_TYPE, 0));
}
@Test
public void testOnPreferenceTreeClick_noAudioAttributes() {
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH);
channel.setSound(null, null);
mController.onResume(appRow, channel, null, null, null, null, null);
AttributeSet attributeSet = Robolectric.buildAttributeSet().build();
NotificationSoundPreference pref =
spy(new NotificationSoundPreference(mContext, attributeSet));
pref.setKey(mController.getPreferenceKey());
mController.handlePreferenceTreeClick(pref);
ArgumentCaptor<Intent> intentArgumentCaptor = ArgumentCaptor.forClass(Intent.class);
verify(pref, times(1)).onPrepareRingtonePickerIntent(intentArgumentCaptor.capture());
assertEquals(RingtoneManager.TYPE_NOTIFICATION,
intentArgumentCaptor.getValue().getIntExtra(
RingtoneManager.EXTRA_RINGTONE_TYPE, 0));
}
@Test
public void testOnActivityResult() {
NotificationSoundPreference pref = mock(NotificationSoundPreference.class);

View File

@@ -20,7 +20,6 @@ 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.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
@@ -28,10 +27,8 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.Flags;
import android.app.NotificationChannel;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.ParceledListSlice;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
@@ -39,7 +36,6 @@ import androidx.fragment.app.Fragment;
import androidx.preference.Preference;
import androidx.preference.PreferenceCategory;
import com.android.settings.notification.NotificationBackend;
import com.android.settingslib.applications.ApplicationsState;
import org.junit.Before;
@@ -54,6 +50,7 @@ import org.robolectric.RuntimeEnvironment;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@RunWith(RobolectricTestRunner.class)
@EnableFlags(Flags.FLAG_MODES_UI)
@@ -66,7 +63,7 @@ public class ZenModeAllBypassingAppsPreferenceControllerTest {
private Context mContext;
@Mock
private NotificationBackend mBackend;
private ZenHelperBackend mBackend;
@Mock
private PreferenceCategory mPreferenceCategory;
@Mock
@@ -102,18 +99,25 @@ public class ZenModeAllBypassingAppsPreferenceControllerTest {
entry2.info.packageName = "test2";
entry2.info.uid = 0;
ApplicationsState.AppEntry entry3= mock(ApplicationsState.AppEntry.class);
entry3.info = new ApplicationInfo();
entry3.info.packageName = "test3";
entry3.info.uid = 0;
List<ApplicationsState.AppEntry> appEntries = new ArrayList<>();
appEntries.add(entry1);
appEntries.add(entry2);
List<NotificationChannel> channelsBypassing = new ArrayList<>();
channelsBypassing.add(mock(NotificationChannel.class));
channelsBypassing.add(mock(NotificationChannel.class));
when(mBackend.getNotificationChannelsBypassingDnd(anyString(),
anyInt())).thenReturn(new ParceledListSlice<>(channelsBypassing));
appEntries.add(entry3);
when(mBackend.getPackagesBypassingDnd(anyInt())).thenReturn(
Map.of("test", true, "test2", false));
// THEN there's are two preferences
mController.updateAppList(appEntries);
verify(mPreferenceCategory, times(2)).addPreference(any());
ArgumentCaptor<Preference> captor = ArgumentCaptor.forClass(Preference.class);
verify(mPreferenceCategory, times(2)).addPreference(captor.capture());
List<Preference> prefs = captor.getAllValues();
assertThat(prefs.get(0).getSummary().toString()).isEqualTo("All notifications");
assertThat(prefs.get(1).getSummary().toString()).isEqualTo("Some notifications");
}
@Test

View File

@@ -77,6 +77,7 @@ import org.robolectric.RuntimeEnvironment;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Random;
@RunWith(RobolectricTestRunner.class)
@@ -200,8 +201,8 @@ public final class ZenModeAppsLinkPreferenceControllerTest {
ApplicationsState.AppEntry app2 = createAppEntry("app2", mContext.getUserId());
List<ApplicationsState.AppEntry> allApps = List.of(app1, app2);
when(mHelperBackend.getPackagesBypassingDnd(mContext.getUserId(),
false)).thenReturn(List.of("app1"));
when(mHelperBackend.getPackagesBypassingDnd(mContext.getUserId())).thenReturn(
Map.of("app1", true));
assertThat(mController.getAppsBypassingDndSortedByName(allApps)).containsExactly(app1);
}
@@ -213,8 +214,8 @@ public final class ZenModeAppsLinkPreferenceControllerTest {
ApplicationsState.AppEntry appB = createAppEntry("B", mContext.getUserId());
List<ApplicationsState.AppEntry> allApps = List.of(appC, appA, appB);
when(mHelperBackend.getPackagesBypassingDnd(eq(mContext.getUserId()), anyBoolean()))
.thenReturn(List.of("B", "C", "A"));
when(mHelperBackend.getPackagesBypassingDnd(eq(mContext.getUserId())))
.thenReturn(Map.of("B", true, "C", false, "A", true));
assertThat(mController.getAppsBypassingDndSortedByName(allApps))
.containsExactly(appA, appB, appC).inOrder();
@@ -234,10 +235,10 @@ public final class ZenModeAppsLinkPreferenceControllerTest {
List<ApplicationsState.AppEntry> allApps = List.of(workCopy, personalCopy, otherPersonal,
otherWork);
when(mHelperBackend.getPackagesBypassingDnd(eq(mContext.getUserId()), anyBoolean()))
.thenReturn(List.of("app", "p2"));
when(mHelperBackend.getPackagesBypassingDnd(eq(10), anyBoolean()))
.thenReturn(List.of("app"));
when(mHelperBackend.getPackagesBypassingDnd(eq(mContext.getUserId())))
.thenReturn(Map.of("app", true, "p2", true));
when(mHelperBackend.getPackagesBypassingDnd(eq(10)))
.thenReturn(Map.of("app", false));
// Personal copy before work copy (names match).
assertThat(mController.getAppsBypassingDndSortedByName(allApps))
@@ -253,7 +254,7 @@ public final class ZenModeAppsLinkPreferenceControllerTest {
mController.updateState(mPreference, zenMode);
verifyNoMoreInteractions(mSession);
verify(mHelperBackend, never()).getPackagesBypassingDnd(anyInt(), anyBoolean());
verify(mHelperBackend, never()).getPackagesBypassingDnd(anyInt());
assertThat(String.valueOf(mPreference.getSummary())).isEqualTo("None");
}
@@ -266,9 +267,8 @@ public final class ZenModeAppsLinkPreferenceControllerTest {
ArrayList<ApplicationsState.AppEntry> appEntries = new ArrayList<>();
appEntries.add(createAppEntry("test", mContext.getUserId()));
when(mHelperBackend.getPackagesBypassingDnd(
mContext.getUserId(), false))
.thenReturn(List.of("test"));
when(mHelperBackend.getPackagesBypassingDnd(mContext.getUserId()))
.thenReturn(Map.of("test", false));
// Updates the preference with the zen mode. We expect that this causes the app session
// to trigger a rebuild (and display a temporary text in the meantime).
@@ -286,8 +286,8 @@ public final class ZenModeAppsLinkPreferenceControllerTest {
ZenMode zenMode = createPriorityChannelsZenMode();
mController.updateState(mPreference, zenMode);
when(mHelperBackend.getPackagesBypassingDnd(anyInt(), anyBoolean()))
.thenReturn(ImmutableList.of("test1", "test2"));
when(mHelperBackend.getPackagesBypassingDnd(anyInt()))
.thenReturn(Map.of("test1", false, "test2", false));
ArrayList<ApplicationsState.AppEntry> appEntries = new ArrayList<>();
appEntries.add(createAppEntry("test1", mContext.getUserId()));
appEntries.add(createAppEntry("test2", mContext.getUserId()));
@@ -328,8 +328,8 @@ public final class ZenModeAppsLinkPreferenceControllerTest {
.build();
ArrayList<ApplicationsState.AppEntry> appEntries = new ArrayList<>();
appEntries.add(createAppEntry("test", mContext.getUserId()));
when(mHelperBackend.getPackagesBypassingDnd(mContext.getUserId(), false))
.thenReturn(List.of("test"));
when(mHelperBackend.getPackagesBypassingDnd(mContext.getUserId()))
.thenReturn(Map.of("test", true));
mController.updateState(mPreference, zenModeWithNone);
@@ -355,8 +355,8 @@ public final class ZenModeAppsLinkPreferenceControllerTest {
.build();
ArrayList<ApplicationsState.AppEntry> appEntries = new ArrayList<>();
appEntries.add(createAppEntry("test", mContext.getUserId()));
when(mHelperBackend.getPackagesBypassingDnd(mContext.getUserId(), false))
.thenReturn(List.of("test"));
when(mHelperBackend.getPackagesBypassingDnd(mContext.getUserId()))
.thenReturn(Map.of("test", true));
mController.updateState(mPreference, zenModeWithPriority);

View File

@@ -16,12 +16,19 @@
package com.android.settings.notification.modes;
import static android.app.AutomaticZenRule.TYPE_SCHEDULE_TIME;
import static android.service.notification.SystemZenRules.PACKAGE_ANDROID;
import static com.google.common.truth.Truth.assertThat;
import android.app.Flags;
import android.content.Context;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
import android.service.notification.SystemZenRules;
import android.service.notification.ZenModeConfig;
import android.text.Spanned;
import android.text.style.TtsSpan;
import com.android.settingslib.notification.modes.TestModeBuilder;
import com.android.settingslib.notification.modes.ZenIconLoader;
@@ -37,6 +44,8 @@ import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import java.util.Calendar;
@RunWith(RobolectricTestRunner.class)
@EnableFlags(Flags.FLAG_MODES_UI)
public class ZenModesListItemPreferenceTest {
@@ -122,6 +131,31 @@ public class ZenModesListItemPreferenceTest {
assertThat(preference.getIcon()).isNotNull();
}
@Test
public void setZenMode_scheduleTime_hasCustomTtsInSummary() {
ZenModeConfig.ScheduleInfo scheduleInfo = new ZenModeConfig.ScheduleInfo();
scheduleInfo.days = new int[] { Calendar.MONDAY, Calendar.TUESDAY, Calendar.WEDNESDAY };
scheduleInfo.startHour = 11;
scheduleInfo.endHour = 15;
ZenMode mode = new TestModeBuilder()
.setPackage(PACKAGE_ANDROID)
.setType(TYPE_SCHEDULE_TIME)
.setConditionId(ZenModeConfig.toScheduleConditionId(scheduleInfo))
.setTriggerDescription(
SystemZenRules.getTriggerDescriptionForScheduleTime(mContext, scheduleInfo))
.build();
ZenModesListItemPreference preference = newPreference(mode);
assertThat(preference.getSummary()).isInstanceOf(Spanned.class);
Spanned summary = (Spanned) preference.getSummary();
TtsSpan[] ttsSpans = summary.getSpans(0, summary.length(), TtsSpan.class);
assertThat(ttsSpans).hasLength(1);
assertThat(ttsSpans[0].getType()).isEqualTo(TtsSpan.TYPE_TEXT);
assertThat(ttsSpans[0].getArgs().getString(TtsSpan.ARG_TEXT)).isEqualTo(
"Monday to Wednesday, 11:00 AM - 3:00 PM");
}
private ZenModesListItemPreference newPreference(ZenMode zenMode) {
return new ZenModesListItemPreference(mContext, mIconLoader, MoreExecutors.directExecutor(),
zenMode);

View File

@@ -91,6 +91,68 @@ class ApnTypesTest {
assertThat(apnType).isEqualTo("default,mms,supl,hipri,fota,cbs,xcap")
}
@Test
fun hasAllApnTypes_allString() {
val apnTypes = listOf(ApnSetting.TYPE_ALL_STRING)
val hasAllApnTypes = ApnTypes.hasAllApnTypes(apnTypes)
assertThat(hasAllApnTypes).isTrue()
}
@Test
fun hasAllApnTypes_allTypes() {
val apnTypes = listOf(
ApnSetting.TYPE_DEFAULT_STRING,
ApnSetting.TYPE_MMS_STRING,
ApnSetting.TYPE_SUPL_STRING,
ApnSetting.TYPE_DUN_STRING,
ApnSetting.TYPE_HIPRI_STRING,
ApnSetting.TYPE_FOTA_STRING,
ApnSetting.TYPE_IMS_STRING,
ApnSetting.TYPE_CBS_STRING,
ApnSetting.TYPE_IA_STRING,
ApnSetting.TYPE_EMERGENCY_STRING,
ApnSetting.TYPE_MCX_STRING,
ApnSetting.TYPE_XCAP_STRING,
ApnSetting.TYPE_VSIM_STRING,
ApnSetting.TYPE_BIP_STRING,
ApnSetting.TYPE_ENTERPRISE_STRING,
ApnSetting.TYPE_OEM_PAID_STRING,
ApnSetting.TYPE_OEM_PRIVATE_STRING,
)
val hasAllApnTypes = ApnTypes.hasAllApnTypes(apnTypes)
assertThat(hasAllApnTypes).isTrue()
}
@Test
fun hasAllApnTypes_allTypesExceptDefault() {
val apnTypes = listOf(
ApnSetting.TYPE_MMS_STRING,
ApnSetting.TYPE_SUPL_STRING,
ApnSetting.TYPE_DUN_STRING,
ApnSetting.TYPE_HIPRI_STRING,
ApnSetting.TYPE_FOTA_STRING,
ApnSetting.TYPE_IMS_STRING,
ApnSetting.TYPE_CBS_STRING,
ApnSetting.TYPE_IA_STRING,
ApnSetting.TYPE_EMERGENCY_STRING,
ApnSetting.TYPE_MCX_STRING,
ApnSetting.TYPE_XCAP_STRING,
ApnSetting.TYPE_VSIM_STRING,
ApnSetting.TYPE_BIP_STRING,
ApnSetting.TYPE_ENTERPRISE_STRING,
ApnSetting.TYPE_OEM_PAID_STRING,
ApnSetting.TYPE_OEM_PRIVATE_STRING,
)
val hasAllApnTypes = ApnTypes.hasAllApnTypes(apnTypes)
assertThat(hasAllApnTypes).isFalse()
}
private companion object {
const val APN_TYPE = "type"
}