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:height="@dimen/accessibility_icon_size"
android:color="@color/accessibility_feature_background"/> android:color="@color/accessibility_feature_background"/>
</item> </item>
<item android:gravity="center" <item android:gravity="center">
android:drawable="@drawable/ic_brightness_auto"/> <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> </layer-list>

View File

@@ -21,6 +21,15 @@
android:height="@dimen/accessibility_icon_size" android:height="@dimen/accessibility_icon_size"
android:color="@color/accessibility_feature_background"/> android:color="@color/accessibility_feature_background"/>
</item> </item>
<item android:gravity="center" <item android:gravity="center">
android:drawable="@drawable/ic_brightness_medium"/> <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> </layer-list>

View File

@@ -2869,16 +2869,12 @@
<string name="brightness">Brightness level</string> <string name="brightness">Brightness level</string>
<!-- Sound & display settings screen, setting option name to enable adaptive brightness [CHAR LIMIT=30] --> <!-- Sound & display settings screen, setting option name to enable adaptive brightness [CHAR LIMIT=30] -->
<string name="auto_brightness_title">Adaptive brightness</string> <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 --> <!-- 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> <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] --> <!-- Setting option summary when adaptive brightness is on [CHAR LIMIT=NONE] -->
<string name="auto_brightness_summary_on">On</string> <string name="auto_brightness_summary_on">On</string>
<!-- Setting option summary when adaptive brightness is off [CHAR LIMIT=NONE] --> <!-- Setting option summary when adaptive brightness is off [CHAR LIMIT=NONE] -->
<string name="auto_brightness_summary_off">Off</string> <string name="auto_brightness_summary_off">Off</string>
<!-- Display settings screen, display white balance settings title [CHAR LIMIT=30] --> <!-- Display settings screen, display white balance settings title [CHAR LIMIT=30] -->
<string name="display_white_balance_title">Display white balance</string> <string name="display_white_balance_title">Display white balance</string>
<!-- Display settings screen, display white balance settings summary [CHAR LIMIT=NONE] --> <!-- Display settings screen, display white balance settings summary [CHAR LIMIT=NONE] -->

View File

@@ -37,11 +37,10 @@
settings:useAdminDisabledSummary="true" settings:useAdminDisabledSummary="true"
settings:userRestriction="no_config_brightness"/> settings:userRestriction="no_config_brightness"/>
<com.android.settingslib.PrimarySwitchPreference <com.android.settingslib.RestrictedSwitchPreference
android:key="@string/preference_key_auto_brightness" android:key="@string/preference_key_auto_brightness"
android:icon="@drawable/ic_suw_brightness_auto" android:icon="@drawable/ic_suw_brightness_auto"
android:title="@string/auto_brightness_title" android:title="@string/auto_brightness_title"
android:fragment="com.android.settings.accessibility.AutoBrightnessPreferenceFragmentForSetupWizard"
settings:useAdminDisabledSummary="true" settings:useAdminDisabledSummary="true"
settings:userRestriction="no_config_brightness" settings:userRestriction="no_config_brightness"
settings:controller="com.android.settings.display.AutoBrightnessPreferenceControllerForSetupWizard"/> 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); 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) { private List<AssociationInfo> getAssociations(String address) {
return filter( return filter(
mCompanionDeviceManager.getAllAssociations(), mCompanionDeviceManager.getAllAssociations(),

View File

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

View File

@@ -116,7 +116,18 @@ public class AudioSharingDevicePreferenceController extends BasePreferenceContro
@Override @Override
public void onSourceAdded( 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 @Override
public void onSourceAddFailed( public void onSourceAddFailed(
@@ -173,20 +184,7 @@ public class AudioSharingDevicePreferenceController extends BasePreferenceContro
public void onReceiveStateChanged( public void onReceiveStateChanged(
@NonNull BluetoothDevice sink, @NonNull BluetoothDevice sink,
int sourceId, int sourceId,
@NonNull BluetoothLeBroadcastReceiveState state) { @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);
}
}
}
}
}; };
public AudioSharingDevicePreferenceController(Context context) { public AudioSharingDevicePreferenceController(Context context) {

View File

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

View File

@@ -177,6 +177,20 @@ public class AudioSharingSwitchBarController extends BasePreferenceController
+ broadcastId + broadcastId
+ ", metadata = " + ", metadata = "
+ metadata.getBroadcastName()); + 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 @Override
@@ -221,20 +235,6 @@ public class AudioSharingSwitchBarController extends BasePreferenceController
+ reason + reason
+ ", broadcastId = " + ", broadcastId = "
+ 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 @Override
@@ -261,7 +261,30 @@ public class AudioSharingSwitchBarController extends BasePreferenceController
@Override @Override
public void onSourceAdded( 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 @Override
public void onSourceAddFailed( public void onSourceAddFailed(
@@ -307,34 +330,9 @@ public class AudioSharingSwitchBarController extends BasePreferenceController
@NonNull BluetoothDevice sink, @NonNull BluetoothDevice sink,
int sourceId, int sourceId,
@NonNull BluetoothLeBroadcastReceiveState state) { @NonNull BluetoothLeBroadcastReceiveState state) {
if (mStoppingSharing.get()) { Log.d(TAG,
Log.d(TAG, "Skip onReceiveStateChanged, stopping broadcast"); "onReceiveStateChanged(), sink = " + sink + ", sourceId = " + sourceId
return; + ", state = " + state);
}
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);
}
}
}
} }
}; };

View File

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

View File

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

View File

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

View File

@@ -18,8 +18,6 @@ package com.android.settings.connecteddevice.audiosharing.audiostreams;
import static android.text.Spanned.SPAN_EXCLUSIVE_INCLUSIVE; import static android.text.Spanned.SPAN_EXCLUSIVE_INCLUSIVE;
import static com.android.settingslib.flags.Flags.audioSharingHysteresisModeFix;
import android.os.Handler; import android.os.Handler;
import android.os.Looper; import android.os.Looper;
import android.text.SpannableString; import android.text.SpannableString;
@@ -98,7 +96,8 @@ class AudioStreamStateHandler {
newState newState
== AudioStreamsProgressCategoryController == AudioStreamsProgressCategoryController
.AudioStreamState.SOURCE_ADDED .AudioStreamState.SOURCE_ADDED
|| (audioSharingHysteresisModeFix() || (BluetoothUtils.isAudioSharingHysteresisModeFixAvailable(
preference.getContext())
&& newState && newState
== AudioStreamsProgressCategoryController == AudioStreamsProgressCategoryController
.AudioStreamState.SOURCE_PRESENT)); .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.BluetoothUtils;
import com.android.settingslib.bluetooth.CachedBluetoothDevice; import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.LocalBluetoothManager; import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.flags.Flags;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.concurrent.Executors; 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 @Override
public void updateVisibility() { public void updateVisibility() {
if (mPreference == null) return; 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_ID;
import static com.android.settings.connecteddevice.audiosharing.audiostreams.AudioStreamMediaService.BROADCAST_TITLE; 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.settings.connecteddevice.audiosharing.audiostreams.AudioStreamMediaService.DEVICES;
import static com.android.settingslib.flags.Flags.audioSharingHysteresisModeFix;
import static java.util.Collections.emptyList; import static java.util.Collections.emptyList;
@@ -271,7 +270,8 @@ public class AudioStreamsHelper {
List<BluetoothLeBroadcastReceiveState> sourceList = List<BluetoothLeBroadcastReceiveState> sourceList =
assistant.getAllSources(cachedDevice.getDevice()); assistant.getAllSources(cachedDevice.getDevice());
if (!sourceList.isEmpty() if (!sourceList.isEmpty()
&& (audioSharingHysteresisModeFix() && (BluetoothUtils.isAudioSharingHysteresisModeFixAvailable(
localBtManager.getContext())
|| sourceList.stream().anyMatch(AudioStreamsHelper::isConnected))) { || sourceList.stream().anyMatch(AudioStreamsHelper::isConnected))) {
Log.d( Log.d(
TAG, TAG,
@@ -284,7 +284,8 @@ public class AudioStreamsHelper {
List<BluetoothLeBroadcastReceiveState> list = List<BluetoothLeBroadcastReceiveState> list =
assistant.getAllSources(device.getDevice()); assistant.getAllSources(device.getDevice());
if (!list.isEmpty() if (!list.isEmpty()
&& (audioSharingHysteresisModeFix() && (BluetoothUtils.isAudioSharingHysteresisModeFixAvailable(
localBtManager.getContext())
|| list.stream().anyMatch(AudioStreamsHelper::isConnected))) { || list.stream().anyMatch(AudioStreamsHelper::isConnected))) {
Log.d( Log.d(
TAG, TAG,

View File

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

View File

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

View File

@@ -41,4 +41,9 @@ public class AutoBrightnessPreferenceControllerForSetupWizard
} }
return super.getAvailabilityStatus(); 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.content.Context
import android.net.wifi.WifiManager import android.net.wifi.WifiManager
import android.provider.Settings.Secure.ADAPTIVE_CONNECTIVITY_ENABLED import android.provider.Settings.Secure.ADAPTIVE_CONNECTIVITY_ENABLED
import androidx.preference.Preference
import com.android.settings.R 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.SettingsSecureStore
import com.android.settingslib.datastore.SettingsStore
import com.android.settingslib.metadata.MainSwitchPreference import com.android.settingslib.metadata.MainSwitchPreference
import com.android.settingslib.metadata.PreferenceMetadata
import com.android.settingslib.preference.MainSwitchPreferenceBinding
// LINT.IfChange // LINT.IfChange
class AdaptiveConnectivityTogglePreference : class AdaptiveConnectivityTogglePreference :
MainSwitchPreference( MainSwitchPreference(KEY, R.string.adaptive_connectivity_main_switch_title) {
ADAPTIVE_CONNECTIVITY_ENABLED,
R.string.adaptive_connectivity_main_switch_title,
),
MainSwitchPreferenceBinding,
Preference.OnPreferenceChangeListener {
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) { @Suppress("UNCHECKED_CAST")
super.bind(preference, metadata) private class AdaptiveConnectivityToggleStorage(
preference.onPreferenceChangeListener = this 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 { companion object {
val isChecked = newValue as Boolean const val KEY = ADAPTIVE_CONNECTIVITY_ENABLED
preference.context const val DEFAULT_VALUE = true
.getSystemService(WifiManager::class.java)
?.setWifiScoringEnabled(isChecked)
return true
} }
} }
// LINT.ThenChange(AdaptiveConnectivityTogglePreferenceController.java) // LINT.ThenChange(AdaptiveConnectivityTogglePreferenceController.java)

View File

@@ -23,88 +23,21 @@ import android.app.settings.SettingsEnums;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.os.PersistableBundle;
import android.os.UserManager; import android.os.UserManager;
import android.provider.Telephony; import android.provider.Telephony;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager; import android.telephony.SubscriptionManager;
import android.util.Log; import android.util.Log;
import androidx.annotation.VisibleForTesting; import androidx.annotation.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
import com.android.settings.SettingsPreferenceFragment; import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.spa.SpaActivity; import com.android.settings.spa.SpaActivity;
import java.util.Arrays;
import java.util.List;
/** Use to edit apn settings. */ /** Use to edit apn settings. */
public class ApnEditor extends SettingsPreferenceFragment { public class ApnEditor extends SettingsPreferenceFragment {
private static final String TAG = ApnEditor.class.getSimpleName(); 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 @Override
public void onCreate(Bundle icicle) { public void onCreate(Bundle icicle) {
super.onCreate(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 @Override
public int getMetricsCategory() { public int getMetricsCategory() {
return SettingsEnums.APN_EDITOR; return SettingsEnums.APN_EDITOR;

View File

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

View File

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

View File

@@ -17,6 +17,8 @@
package com.android.settings.network.apn package com.android.settings.network.apn
import android.content.Context import android.content.Context
import android.os.PersistableBundle
import android.telephony.CarrierConfigManager
import android.telephony.data.ApnSetting import android.telephony.data.ApnSetting
import android.util.Log import android.util.Log
import android.widget.Toast import android.widget.Toast
@@ -51,9 +53,7 @@ object ApnTypes {
private fun splitToList(apnType: String): List<String> { private fun splitToList(apnType: String): List<String> {
val types = apnType.split(',').map { it.trim().toLowerCase(Locale.current) } val types = apnType.split(',').map { it.trim().toLowerCase(Locale.current) }
if (ApnSetting.TYPE_ALL_STRING in types || APN_TYPES.all { it in types }) { if (hasAllApnTypes(types)) return listOf(ApnSetting.TYPE_ALL_STRING)
return listOf(ApnSetting.TYPE_ALL_STRING)
}
return APN_TYPES.filter { it in types } return APN_TYPES.filter { it in types }
} }
@@ -132,4 +132,32 @@ object ApnTypes {
private fun defaultPreSelectedApnTypes(readOnlyApnTypes: List<String>) = private fun defaultPreSelectedApnTypes(readOnlyApnTypes: List<String>) =
if (ApnSetting.TYPE_ALL_STRING in readOnlyApnTypes) emptyList() if (ApnSetting.TYPE_ALL_STRING in readOnlyApnTypes) emptyList()
else PreSelectedTypes.filterNot { it in readOnlyApnTypes } 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) { public boolean handlePreferenceTreeClick(Preference preference) {
if (KEY_SOUND.equals(preference.getKey()) && mFragment != null) { if (KEY_SOUND.equals(preference.getKey()) && mFragment != null) {
NotificationSoundPreference pref = (NotificationSoundPreference) preference; NotificationSoundPreference pref = (NotificationSoundPreference) preference;
// default to notification
pref.setRingtoneType(RingtoneManager.TYPE_NOTIFICATION);
if (mChannel != null && mChannel.getAudioAttributes() != null) { if (mChannel != null && mChannel.getAudioAttributes() != null) {
if (USAGE_ALARM == mChannel.getAudioAttributes().getUsage()) { if (USAGE_ALARM == mChannel.getAudioAttributes().getUsage()) {
pref.setRingtoneType(RingtoneManager.TYPE_ALARM); pref.setRingtoneType(RingtoneManager.TYPE_ALARM);

View File

@@ -18,6 +18,7 @@ package com.android.settings.notification.modes;
import android.annotation.Nullable; import android.annotation.Nullable;
import android.app.INotificationManager; import android.app.INotificationManager;
import android.app.ZenBypassingApp;
import android.content.ContentProvider; import android.content.ContentProvider;
import android.content.Context; import android.content.Context;
import android.content.pm.ParceledListSlice; import android.content.pm.ParceledListSlice;
@@ -30,6 +31,7 @@ import android.os.UserManager;
import android.provider.ContactsContract; import android.provider.ContactsContract;
import android.provider.ContactsContract.Contacts; import android.provider.ContactsContract.Contacts;
import android.service.notification.ConversationChannelWrapper; import android.service.notification.ConversationChannelWrapper;
import android.util.ArrayMap;
import android.util.Log; import android.util.Log;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
@@ -41,8 +43,9 @@ import com.google.common.collect.ImmutableList;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.ArrayList; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.function.Function; 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, Map<String, Boolean> getPackagesBypassingDnd(int userId) {
boolean includeConversationChannels) { Map<String, Boolean> bypassingAppsMap = new HashMap<>();
try { 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) { } catch (Exception e) {
Log.w(TAG, "Error calling NoMan", e); Log.w(TAG, "Error calling NoMan", e);
return new ArrayList<>();
} }
return bypassingAppsMap;
} }
/** Returns all conversation channels for profiles of the current user. */ /** 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.graphics.drawable.Drawable;
import android.os.Bundle; import android.os.Bundle;
import android.os.UserHandle; import android.os.UserHandle;
import android.os.UserManager;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting; import androidx.annotation.VisibleForTesting;
import androidx.core.text.BidiFormatter; import androidx.core.text.BidiFormatter;
@@ -35,7 +37,6 @@ import com.android.settings.R;
import com.android.settings.applications.AppInfoBase; import com.android.settings.applications.AppInfoBase;
import com.android.settings.core.PreferenceControllerMixin; import com.android.settings.core.PreferenceControllerMixin;
import com.android.settings.core.SubSettingLauncher; import com.android.settings.core.SubSettingLauncher;
import com.android.settings.notification.NotificationBackend;
import com.android.settings.notification.app.AppChannelsBypassingDndSettings; import com.android.settings.notification.app.AppChannelsBypassingDndSettings;
import com.android.settingslib.applications.AppUtils; import com.android.settingslib.applications.AppUtils;
import com.android.settingslib.applications.ApplicationsState; import com.android.settingslib.applications.ApplicationsState;
@@ -44,7 +45,9 @@ import com.android.settingslib.utils.ThreadUtils;
import com.android.settingslib.widget.AppPreference; import com.android.settingslib.widget.AppPreference;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
/** /**
* Adds a preference to the PreferenceScreen for each notification channel that can bypass DND. * 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"; public static final String KEY_NO_APPS = "all_none";
private static final String KEY = "zen_mode_bypassing_apps_list"; 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; @Nullable @VisibleForTesting ApplicationsState mApplicationsState;
@VisibleForTesting PreferenceCategory mPreferenceCategory; @VisibleForTesting PreferenceCategory mPreferenceCategory;
@@ -64,18 +68,18 @@ public class ZenModeAllBypassingAppsPreferenceController extends AbstractPrefere
@Nullable private Fragment mHostFragment; @Nullable private Fragment mHostFragment;
public ZenModeAllBypassingAppsPreferenceController(Context context, @Nullable Application app, public ZenModeAllBypassingAppsPreferenceController(Context context, @Nullable Application app,
@Nullable Fragment host, @Nullable NotificationBackend notificationBackend) { @Nullable Fragment host, @Nullable ZenHelperBackend helperBackend) {
this(context, app == null ? null : ApplicationsState.getInstance(app), host, this(context, app == null ? null : ApplicationsState.getInstance(app), host, helperBackend);
notificationBackend);
} }
private ZenModeAllBypassingAppsPreferenceController(Context context, private ZenModeAllBypassingAppsPreferenceController(Context context,
@Nullable ApplicationsState appState, @Nullable Fragment host, @Nullable ApplicationsState appState, @Nullable Fragment host,
@Nullable NotificationBackend notificationBackend) { @Nullable ZenHelperBackend helperBackend) {
super(context); super(context);
mNotificationBackend = notificationBackend;
mApplicationsState = appState; mApplicationsState = appState;
mHostFragment = host; mHostFragment = host;
mHelperBackend = helperBackend;
mUserManager = context.getSystemService(UserManager.class);
if (mApplicationsState != null && host != null) { if (mApplicationsState != null && host != null) {
mAppSession = mApplicationsState.newSession(mAppSessionCallbacks, host.getLifecycle()); mAppSession = mApplicationsState.newSession(mAppSessionCallbacks, host.getLifecycle());
@@ -140,19 +144,25 @@ public class ZenModeAllBypassingAppsPreferenceController extends AbstractPrefere
} }
boolean doAnyAppsPassCriteria = false; 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) { for (ApplicationsState.AppEntry app : apps) {
String pkg = app.info.packageName; String pkg = app.info.packageName;
final String key = getKey(pkg, app.info.uid); final String key = getKey(pkg, app.info.uid);
final int appChannels = mNotificationBackend.getChannelCount(pkg, app.info.uid); boolean doesAppBypassDnd = false;
final int appChannelsBypassingDnd = mNotificationBackend int userId = UserHandle.getUserId(app.info.uid);
.getNotificationChannelsBypassingDnd(pkg, app.info.uid).getList().size(); Map<String, Boolean> packagesBypassingDnd =
if (appChannelsBypassingDnd > 0) { packagesBypassingDndByUser.getOrDefault(userId, new HashMap<>());
if (packagesBypassingDnd.containsKey(pkg)) {
doAnyAppsPassCriteria = true; doAnyAppsPassCriteria = true;
doesAppBypassDnd = true;
} }
Preference pref = mPreferenceCategory.findPreference(key); Preference pref = mPreferenceCategory.findPreference(key);
if (pref == null) { if (pref == null) {
if (appChannelsBypassingDnd > 0) { if (doesAppBypassDnd) {
// does not exist but should // does not exist but should
pref = new AppPreference(mPrefContext); pref = new AppPreference(mPrefContext);
pref.setKey(key); pref.setKey(key);
@@ -172,14 +182,14 @@ public class ZenModeAllBypassingAppsPreferenceController extends AbstractPrefere
}); });
pref.setTitle(BidiFormatter.getInstance().unicodeWrap(app.label)); pref.setTitle(BidiFormatter.getInstance().unicodeWrap(app.label));
updateIcon(pref, app); updateIcon(pref, app);
if (appChannels > appChannelsBypassingDnd) { if (packagesBypassingDnd.get(pkg)) {
pref.setSummary(R.string.zen_mode_bypassing_apps_summary_some);
} else {
pref.setSummary(R.string.zen_mode_bypassing_apps_summary_all); pref.setSummary(R.string.zen_mode_bypassing_apps_summary_all);
} else {
pref.setSummary(R.string.zen_mode_bypassing_apps_summary_some);
} }
mPreferenceCategory.addPreference(pref); mPreferenceCategory.addPreference(pref);
} }
} else if (appChannelsBypassingDnd == 0) { } else if (!doesAppBypassDnd) {
// exists but shouldn't anymore // exists but shouldn't anymore
mPreferenceCategory.removePreference(pref); mPreferenceCategory.removePreference(pref);
} }

View File

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

View File

@@ -48,15 +48,17 @@ public class ZenModeSelectBypassingAppsFragment extends ZenModeFragmentBase impl
} else { } else {
app = null; 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, private static List<AbstractPreferenceController> buildPreferenceControllers(Context context,
@Nullable Application app, @Nullable Fragment host, @Nullable Application app, @Nullable Fragment host,
@Nullable NotificationBackend notificationBackend) { @Nullable NotificationBackend notificationBackend,
@Nullable ZenHelperBackend zenHelperBackend) {
final List<AbstractPreferenceController> controllers = new ArrayList<>(); final List<AbstractPreferenceController> controllers = new ArrayList<>();
controllers.add(new ZenModeAllBypassingAppsPreferenceController(context, app, host, controllers.add(new ZenModeAllBypassingAppsPreferenceController(context, app, host,
notificationBackend)); zenHelperBackend));
controllers.add(new ZenModeAddBypassingAppsPreferenceController(context, app, host, controllers.add(new ZenModeAddBypassingAppsPreferenceController(context, app, host,
notificationBackend)); notificationBackend));
return controllers; return controllers;
@@ -86,7 +88,7 @@ public class ZenModeSelectBypassingAppsFragment extends ZenModeFragmentBase impl
@Override @Override
public List<AbstractPreferenceController> createPreferenceControllers( public List<AbstractPreferenceController> createPreferenceControllers(
Context context) { 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; package com.android.settings.notification.modes;
import static com.android.settings.Utils.createAccessibleSequence;
import android.app.settings.SettingsEnums; import android.app.settings.SettingsEnums;
import android.content.Context; import android.content.Context;
import android.widget.TextView; import android.widget.TextView;
@@ -28,6 +30,7 @@ import com.android.settingslib.RestrictedPreference;
import com.android.settingslib.Utils; import com.android.settingslib.Utils;
import com.android.settingslib.notification.modes.ZenIconLoader; import com.android.settingslib.notification.modes.ZenIconLoader;
import com.android.settingslib.notification.modes.ZenMode; import com.android.settingslib.notification.modes.ZenMode;
import com.android.settingslib.notification.modes.ZenModeDescriptions;
import com.google.common.base.Strings; import com.google.common.base.Strings;
@@ -42,6 +45,7 @@ class ZenModesListItemPreference extends RestrictedPreference {
private final Context mContext; private final Context mContext;
private final ZenIconLoader mIconLoader; private final ZenIconLoader mIconLoader;
private final Executor mUiExecutor; private final Executor mUiExecutor;
private final ZenModeDescriptions mDescriptions;
private ZenMode mZenMode; private ZenMode mZenMode;
private TextView mTitleView; private TextView mTitleView;
@@ -58,6 +62,7 @@ class ZenModesListItemPreference extends RestrictedPreference {
mContext = context; mContext = context;
mIconLoader = iconLoader; mIconLoader = iconLoader;
mUiExecutor = uiExecutor; mUiExecutor = uiExecutor;
mDescriptions = new ZenModeDescriptions(context);
setZenMode(zenMode); setZenMode(zenMode);
setKey(zenMode.getId()); setKey(zenMode.getId());
} }
@@ -89,20 +94,17 @@ class ZenModesListItemPreference extends RestrictedPreference {
} }
setTitle(mZenMode.getName()); setTitle(mZenMode.getName());
String dynamicDescription = zenMode.getDynamicDescription(mContext); ZenMode.Status status = zenMode.getStatus();
CharSequence statusText = switch (mZenMode.getStatus()) { String statusText = getStatusText(status, mDescriptions.getTriggerDescription(zenMode));
case ENABLED_AND_ACTIVE -> String triggerDescriptionForA11y = mDescriptions.getTriggerDescriptionForAccessibility(
Strings.isNullOrEmpty(dynamicDescription) zenMode);
? mContext.getString(R.string.zen_mode_active_text)
: mContext.getString( if (triggerDescriptionForA11y != null) {
R.string.zen_mode_format_status_and_trigger, setSummary(createAccessibleSequence(statusText,
mContext.getString(R.string.zen_mode_active_text), getStatusText(status, triggerDescriptionForA11y)));
dynamicDescription); } else {
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);
};
setSummary(statusText); setSummary(statusText);
}
setIconSize(ICON_SIZE_SMALL); setIconSize(ICON_SIZE_SMALL);
FutureUtil.whenDone( FutureUtil.whenDone(
@@ -116,6 +118,21 @@ class ZenModesListItemPreference extends RestrictedPreference {
updateTextColor(zenMode); 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) { private void updateTextColor(@Nullable ZenMode zenMode) {
boolean isActive = zenMode != null && zenMode.isActive(); boolean isActive = zenMode != null && zenMode.isActive();
if (mTitleView != null) { 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(); shadowOf(Looper.getMainLooper()).idle();
assertThat(mPreference.getSummary().toString()).isEmpty(); assertThat(mPreference.getSummary().toString()).isEmpty();
// onReceiveStateChanged will update summary // onSourceAdded will update summary
Settings.Secure.putInt(mContentResolver, TEST_SETTINGS_KEY, TEST_DEVICE_GROUP_ID1); Settings.Secure.putInt(mContentResolver, TEST_SETTINGS_KEY, TEST_DEVICE_GROUP_ID1);
when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of(mDevice1)); when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of(mDevice1));
when(mAssistant.getAllSources(any())).thenReturn(ImmutableList.of(mState)); when(mAssistant.getAllSources(any())).thenReturn(ImmutableList.of(mState));
mController.mBroadcastAssistantCallback.onReceiveStateChanged( mController.mBroadcastAssistantCallback.onSourceAdded(mDevice1, /* sourceId= */
mDevice1, /* sourceId= */ 1, mState); 1, /* reason= */ 1);
shadowOf(Looper.getMainLooper()).idle(); shadowOf(Looper.getMainLooper()).idle();
assertThat(mPreference.getSummary().toString()) assertThat(mPreference.getSummary().toString())
.isEqualTo( .isEqualTo(
@@ -557,8 +557,6 @@ public class AudioSharingCallAudioPreferenceControllerTest {
mController.mBroadcastAssistantCallback.onSearchStartFailed(/* reason= */ 1); mController.mBroadcastAssistantCallback.onSearchStartFailed(/* reason= */ 1);
mController.mBroadcastAssistantCallback.onSearchStopped(/* reason= */ 1); mController.mBroadcastAssistantCallback.onSearchStopped(/* reason= */ 1);
mController.mBroadcastAssistantCallback.onSearchStopFailed(/* reason= */ 1); mController.mBroadcastAssistantCallback.onSearchStopFailed(/* reason= */ 1);
mController.mBroadcastAssistantCallback.onSourceAdded(
mDevice1, /* sourceId= */ 1, /* reason= */ 1);
mController.mBroadcastAssistantCallback.onSourceAddFailed( mController.mBroadcastAssistantCallback.onSourceAddFailed(
mDevice1, mSource, /* reason= */ 1); mDevice1, mSource, /* reason= */ 1);
mController.mBroadcastAssistantCallback.onSourceRemoved( mController.mBroadcastAssistantCallback.onSourceRemoved(
@@ -572,6 +570,8 @@ public class AudioSharingCallAudioPreferenceControllerTest {
mController.mBroadcastAssistantCallback.onSourceFound(mSource); mController.mBroadcastAssistantCallback.onSourceFound(mSource);
mController.mBroadcastAssistantCallback.onSourceLost(/* broadcastId= */ 1); mController.mBroadcastAssistantCallback.onSourceLost(/* broadcastId= */ 1);
shadowOf(Looper.getMainLooper()).idle(); shadowOf(Looper.getMainLooper()).idle();
mController.mBroadcastAssistantCallback.onReceiveStateChanged(mDevice1, /* sourceId= */ 1,
mState);
// Above callbacks won't update summary. // Above callbacks won't update summary.
assertThat(mPreference.getSummary().toString()).isEmpty(); assertThat(mPreference.getSummary().toString()).isEmpty();

View File

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

View File

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

View File

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

View File

@@ -17,6 +17,7 @@
package com.android.settings.connecteddevice.audiosharing.audiostreams; 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_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; 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 static org.mockito.Mockito.when;
import android.app.settings.SettingsEnums; import android.app.settings.SettingsEnums;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothLeBroadcastAssistant; import android.bluetooth.BluetoothLeBroadcastAssistant;
import android.bluetooth.BluetoothLeBroadcastMetadata; import android.bluetooth.BluetoothLeBroadcastMetadata;
import android.bluetooth.BluetoothLeBroadcastReceiveState; import android.bluetooth.BluetoothLeBroadcastReceiveState;
import android.bluetooth.BluetoothStatusCodes;
import android.content.Context; import android.content.Context;
import android.platform.test.flag.junit.SetFlagsRule; import android.platform.test.flag.junit.SetFlagsRule;
import android.view.View; import android.view.View;
@@ -46,6 +49,7 @@ import androidx.test.core.app.ApplicationProvider;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.connecteddevice.audiosharing.audiostreams.testshadows.ShadowAudioStreamsHelper; import com.android.settings.connecteddevice.audiosharing.audiostreams.testshadows.ShadowAudioStreamsHelper;
import com.android.settings.testutils.FakeFeatureFactory; import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
import com.android.settings.testutils.shadow.ShadowThreadUtils; import com.android.settings.testutils.shadow.ShadowThreadUtils;
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant; import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant;
import com.android.settingslib.core.lifecycle.Lifecycle; import com.android.settingslib.core.lifecycle.Lifecycle;
@@ -62,6 +66,7 @@ import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule; import org.mockito.junit.MockitoRule;
import org.robolectric.RobolectricTestRunner; import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config; import org.robolectric.annotation.Config;
import org.robolectric.shadow.api.Shadow;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
@@ -73,6 +78,7 @@ import java.util.concurrent.Executor;
shadows = { shadows = {
ShadowThreadUtils.class, ShadowThreadUtils.class,
ShadowAudioStreamsHelper.class, ShadowAudioStreamsHelper.class,
ShadowBluetoothAdapter.class,
}) })
public class AudioStreamButtonControllerTest { public class AudioStreamButtonControllerTest {
@Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule(); @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
@@ -95,6 +101,13 @@ public class AudioStreamButtonControllerTest {
@Before @Before
public void setUp() { public void setUp() {
mSetFlagsRule.disableFlags(FLAG_AUDIO_SHARING_HYSTERESIS_MODE_FIX); 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); ShadowAudioStreamsHelper.setUseMock(mAudioStreamsHelper);
when(mAudioStreamsHelper.getLeBroadcastAssistant()).thenReturn(mAssistant); when(mAudioStreamsHelper.getLeBroadcastAssistant()).thenReturn(mAssistant);
mFeatureFactory = FakeFeatureFactory.setupForTest(); mFeatureFactory = FakeFeatureFactory.setupForTest();
@@ -261,6 +274,7 @@ public class AudioStreamButtonControllerTest {
@Test @Test
public void testCallback_onReceiveStateChangedWithSourcePresent_updateButton() { public void testCallback_onReceiveStateChangedWithSourcePresent_updateButton() {
mSetFlagsRule.enableFlags(FLAG_ENABLE_LE_AUDIO_SHARING);
mSetFlagsRule.enableFlags(FLAG_AUDIO_SHARING_HYSTERESIS_MODE_FIX); mSetFlagsRule.enableFlags(FLAG_AUDIO_SHARING_HYSTERESIS_MODE_FIX);
String address = "11:22:33:44:55:66"; 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_NOT_LISTENING_SUMMARY;
import static com.android.settings.connecteddevice.audiosharing.audiostreams.AudioStreamHeaderController.AUDIO_STREAM_HEADER_PRESENT_NOW_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_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.any;
import static org.mockito.Mockito.mock; 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.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothLeBroadcastAssistant; import android.bluetooth.BluetoothLeBroadcastAssistant;
import android.bluetooth.BluetoothLeBroadcastReceiveState; import android.bluetooth.BluetoothLeBroadcastReceiveState;
import android.bluetooth.BluetoothStatusCodes;
import android.content.Context; import android.content.Context;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.platform.test.flag.junit.SetFlagsRule; 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.ShadowAudioStreamsHelper;
import com.android.settings.connecteddevice.audiosharing.audiostreams.testshadows.ShadowEntityHeaderController; 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.testutils.shadow.ShadowThreadUtils;
import com.android.settings.widget.EntityHeaderController; import com.android.settings.widget.EntityHeaderController;
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant; import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant;
@@ -57,6 +61,7 @@ import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule; import org.mockito.junit.MockitoRule;
import org.robolectric.RobolectricTestRunner; import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config; import org.robolectric.annotation.Config;
import org.robolectric.shadow.api.Shadow;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
@@ -69,6 +74,7 @@ import java.util.concurrent.Executor;
ShadowEntityHeaderController.class, ShadowEntityHeaderController.class,
ShadowThreadUtils.class, ShadowThreadUtils.class,
ShadowAudioStreamsHelper.class, ShadowAudioStreamsHelper.class,
ShadowBluetoothAdapter.class,
}) })
public class AudioStreamHeaderControllerTest { public class AudioStreamHeaderControllerTest {
@Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule(); @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
@@ -93,6 +99,13 @@ public class AudioStreamHeaderControllerTest {
@Before @Before
public void setUp() { public void setUp() {
mSetFlagsRule.disableFlags(FLAG_AUDIO_SHARING_HYSTERESIS_MODE_FIX); 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); ShadowEntityHeaderController.setUseMock(mHeaderController);
ShadowAudioStreamsHelper.setUseMock(mAudioStreamsHelper); ShadowAudioStreamsHelper.setUseMock(mAudioStreamsHelper);
@@ -260,6 +273,7 @@ public class AudioStreamHeaderControllerTest {
@Test @Test
public void testCallback_onReceiveStateChangedWithSourcePresent_updateButton() { public void testCallback_onReceiveStateChangedWithSourcePresent_updateButton() {
mSetFlagsRule.enableFlags(FLAG_ENABLE_LE_AUDIO_SHARING);
mSetFlagsRule.enableFlags(FLAG_AUDIO_SHARING_HYSTERESIS_MODE_FIX); mSetFlagsRule.enableFlags(FLAG_AUDIO_SHARING_HYSTERESIS_MODE_FIX);
String address = "11:22:33:44:55:66"; String address = "11:22:33:44:55:66";

View File

@@ -17,6 +17,7 @@
package com.android.settings.connecteddevice.audiosharing.audiostreams; 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_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; 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.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothStatusCodes;
import android.content.Context; import android.content.Context;
import android.platform.test.flag.junit.SetFlagsRule; import android.platform.test.flag.junit.SetFlagsRule;
import android.text.SpannableString; import android.text.SpannableString;
@@ -38,6 +41,8 @@ import android.text.SpannableString;
import androidx.preference.Preference; import androidx.preference.Preference;
import androidx.test.core.app.ApplicationProvider; import androidx.test.core.app.ApplicationProvider;
import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
import org.junit.Before; import org.junit.Before;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
@@ -47,8 +52,14 @@ import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule; import org.mockito.junit.MockitoRule;
import org.robolectric.RobolectricTestRunner; import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
import org.robolectric.shadow.api.Shadow;
@RunWith(RobolectricTestRunner.class) @RunWith(RobolectricTestRunner.class)
@Config(
shadows = {
ShadowBluetoothAdapter.class,
})
public class AudioStreamStateHandlerTest { public class AudioStreamStateHandlerTest {
@Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule(); @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
@Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
@@ -64,6 +75,13 @@ public class AudioStreamStateHandlerTest {
@Before @Before
public void setUp() { public void setUp() {
mSetFlagsRule.disableFlags(FLAG_AUDIO_SHARING_HYSTERESIS_MODE_FIX); 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()); mHandler = spy(new AudioStreamStateHandler());
} }
@@ -109,6 +127,7 @@ public class AudioStreamStateHandlerTest {
@Test @Test
public void testHandleStateChange_setNewState_sourcePresent() { public void testHandleStateChange_setNewState_sourcePresent() {
mSetFlagsRule.enableFlags(FLAG_ENABLE_LE_AUDIO_SHARING);
mSetFlagsRule.enableFlags(FLAG_AUDIO_SHARING_HYSTERESIS_MODE_FIX); mSetFlagsRule.enableFlags(FLAG_AUDIO_SHARING_HYSTERESIS_MODE_FIX);
when(mHandler.getStateEnum()) when(mHandler.getStateEnum())

View File

@@ -135,47 +135,47 @@ public class AudioStreamsCategoryControllerTest {
@Test @Test
public void getAvailabilityStatus_flagOn() { 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); assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
} }
@Test @Test
public void getAvailabilityStatus_flagOff() { 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); assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
} }
@Test @Test
public void onStart_flagOff_doNothing() { 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); mController.onStart(mLifecycleOwner);
verify(mBluetoothEventManager, never()).registerCallback(any()); verify(mBluetoothEventManager, never()).registerCallback(any());
} }
@Test @Test
public void onStart_flagOn_registerCallback() { 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); mController.onStart(mLifecycleOwner);
verify(mBluetoothEventManager).registerCallback(any()); verify(mBluetoothEventManager).registerCallback(any());
} }
@Test @Test
public void onStop_flagOff_doNothing() { 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); mController.onStop(mLifecycleOwner);
verify(mBluetoothEventManager, never()).unregisterCallback(any()); verify(mBluetoothEventManager, never()).unregisterCallback(any());
} }
@Test @Test
public void onStop_flagOn_unregisterCallback() { 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); mController.onStop(mLifecycleOwner);
verify(mBluetoothEventManager).unregisterCallback(any()); verify(mBluetoothEventManager).unregisterCallback(any());
} }
@Test @Test
public void updateVisibility_flagOff_invisible() { 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(); mController.updateVisibility();
shadowOf(Looper.getMainLooper()).idle(); shadowOf(Looper.getMainLooper()).idle();
assertThat(mPreference.isVisible()).isFalse(); assertThat(mPreference.isVisible()).isFalse();
@@ -183,7 +183,7 @@ public class AudioStreamsCategoryControllerTest {
@Test @Test
public void updateVisibility_noConnectedLe_invisible() { 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(); mController.updateVisibility();
shadowOf(Looper.getMainLooper()).idle(); shadowOf(Looper.getMainLooper()).idle();
assertThat(mPreference.isVisible()).isFalse(); assertThat(mPreference.isVisible()).isFalse();
@@ -191,7 +191,7 @@ public class AudioStreamsCategoryControllerTest {
@Test @Test
public void updateVisibility_isNotProfileReady_invisible() { 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( ShadowAudioStreamsHelper.setCachedBluetoothDeviceInSharingOrLeConnected(
mCachedBluetoothDevice); mCachedBluetoothDevice);
when(mVolumeControl.isProfileReady()).thenReturn(false); when(mVolumeControl.isProfileReady()).thenReturn(false);
@@ -202,7 +202,7 @@ public class AudioStreamsCategoryControllerTest {
@Test @Test
public void updateVisibility_isBroadcasting_invisible() { 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( ShadowAudioStreamsHelper.setCachedBluetoothDeviceInSharingOrLeConnected(
mCachedBluetoothDevice); mCachedBluetoothDevice);
when(mBroadcast.isEnabled(any())).thenReturn(true); when(mBroadcast.isEnabled(any())).thenReturn(true);
@@ -213,7 +213,7 @@ public class AudioStreamsCategoryControllerTest {
@Test @Test
public void updateVisibility_isBluetoothOff_invisible() { 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( ShadowAudioStreamsHelper.setCachedBluetoothDeviceInSharingOrLeConnected(
mCachedBluetoothDevice); mCachedBluetoothDevice);
mShadowBluetoothAdapter.setEnabled(false); mShadowBluetoothAdapter.setEnabled(false);
@@ -224,7 +224,7 @@ public class AudioStreamsCategoryControllerTest {
@Test @Test
public void updateVisibility_visible() { 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( ShadowAudioStreamsHelper.setCachedBluetoothDeviceInSharingOrLeConnected(
mCachedBluetoothDevice); mCachedBluetoothDevice);
mController.displayPreference(mScreen); mController.displayPreference(mScreen);
@@ -235,7 +235,7 @@ public class AudioStreamsCategoryControllerTest {
@Test @Test
public void onProfileConnectionStateChanged_updateVisibility() { 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<BluetoothCallback> argumentCaptor =
ArgumentCaptor.forClass(BluetoothCallback.class); ArgumentCaptor.forClass(BluetoothCallback.class);
mController.onStart(mLifecycleOwner); 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 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_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; 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.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothLeBroadcastMetadata; import android.bluetooth.BluetoothLeBroadcastMetadata;
import android.bluetooth.BluetoothLeBroadcastReceiveState; import android.bluetooth.BluetoothLeBroadcastReceiveState;
import android.bluetooth.BluetoothStatusCodes;
import android.content.Context; import android.content.Context;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.content.res.Resources; import android.content.res.Resources;
@@ -45,6 +48,7 @@ import androidx.fragment.app.FragmentActivity;
import androidx.test.core.app.ApplicationProvider; import androidx.test.core.app.ApplicationProvider;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
import com.android.settings.testutils.shadow.ShadowThreadUtils; import com.android.settings.testutils.shadow.ShadowThreadUtils;
import com.android.settingslib.bluetooth.CachedBluetoothDevice; import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager; import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
@@ -65,6 +69,7 @@ import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule; import org.mockito.junit.MockitoRule;
import org.robolectric.RobolectricTestRunner; import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config; import org.robolectric.annotation.Config;
import org.robolectric.shadow.api.Shadow;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
@@ -74,6 +79,7 @@ import java.util.List;
@Config( @Config(
shadows = { shadows = {
ShadowThreadUtils.class, ShadowThreadUtils.class,
ShadowBluetoothAdapter.class,
}) })
public class AudioStreamsHelperTest { public class AudioStreamsHelperTest {
@Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule(); @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
@@ -97,6 +103,13 @@ public class AudioStreamsHelperTest {
@Before @Before
public void setUp() { public void setUp() {
mSetFlagsRule.disableFlags(FLAG_AUDIO_SHARING_HYSTERESIS_MODE_FIX); 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.getProfileManager()).thenReturn(mLocalBluetoothProfileManager);
when(mLocalBluetoothManager.getCachedDeviceManager()).thenReturn(mDeviceManager); when(mLocalBluetoothManager.getCachedDeviceManager()).thenReturn(mDeviceManager);
when(mLocalBluetoothProfileManager.getLeAudioBroadcastAssistantProfile()) when(mLocalBluetoothProfileManager.getLeAudioBroadcastAssistantProfile())
@@ -229,6 +242,7 @@ public class AudioStreamsHelperTest {
@Test @Test
public void getAllPresentSources_noSource() { public void getAllPresentSources_noSource() {
mSetFlagsRule.enableFlags(FLAG_ENABLE_LE_AUDIO_SHARING);
mSetFlagsRule.enableFlags(FLAG_AUDIO_SHARING_HYSTERESIS_MODE_FIX); mSetFlagsRule.enableFlags(FLAG_AUDIO_SHARING_HYSTERESIS_MODE_FIX);
List<BluetoothDevice> devices = new ArrayList<>(); List<BluetoothDevice> devices = new ArrayList<>();
@@ -251,6 +265,7 @@ public class AudioStreamsHelperTest {
@Test @Test
public void getAllPresentSources_returnSource() { public void getAllPresentSources_returnSource() {
mSetFlagsRule.enableFlags(FLAG_ENABLE_LE_AUDIO_SHARING);
mSetFlagsRule.enableFlags(FLAG_AUDIO_SHARING_HYSTERESIS_MODE_FIX); mSetFlagsRule.enableFlags(FLAG_AUDIO_SHARING_HYSTERESIS_MODE_FIX);
String address = "11:22:33:44:55:66"; String address = "11:22:33:44:55:66";

View File

@@ -17,6 +17,7 @@
package com.android.settings.connecteddevice.audiosharing.audiostreams; 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_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.any;
import static org.mockito.ArgumentMatchers.anyBoolean; 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.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothLeBroadcastMetadata; import android.bluetooth.BluetoothLeBroadcastMetadata;
import android.bluetooth.BluetoothLeBroadcastReceiveState; import android.bluetooth.BluetoothLeBroadcastReceiveState;
import android.bluetooth.BluetoothStatusCodes;
import android.content.Context;
import android.platform.test.flag.junit.SetFlagsRule; 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.Before;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
@@ -37,15 +45,21 @@ import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule; import org.mockito.junit.MockitoRule;
import org.robolectric.RobolectricTestRunner; import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
import org.robolectric.shadow.api.Shadow;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@RunWith(RobolectricTestRunner.class) @RunWith(RobolectricTestRunner.class)
@Config(
shadows = {
ShadowBluetoothAdapter.class,
})
public class AudioStreamsProgressCategoryCallbackTest { public class AudioStreamsProgressCategoryCallbackTest {
@Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule(); @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
@Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
private final Context mContext = ApplicationProvider.getApplicationContext();
@Mock private AudioStreamsProgressCategoryController mController; @Mock private AudioStreamsProgressCategoryController mController;
@Mock private BluetoothDevice mDevice; @Mock private BluetoothDevice mDevice;
@Mock private BluetoothLeBroadcastReceiveState mState; @Mock private BluetoothLeBroadcastReceiveState mState;
@@ -56,7 +70,14 @@ public class AudioStreamsProgressCategoryCallbackTest {
@Before @Before
public void setUp() { public void setUp() {
mSetFlagsRule.disableFlags(FLAG_AUDIO_SHARING_HYSTERESIS_MODE_FIX); 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 @Test
@@ -71,6 +92,7 @@ public class AudioStreamsProgressCategoryCallbackTest {
@Test @Test
public void testOnReceiveStateChanged_sourcePresent() { public void testOnReceiveStateChanged_sourcePresent() {
mSetFlagsRule.enableFlags(FLAG_ENABLE_LE_AUDIO_SHARING);
mSetFlagsRule.enableFlags(FLAG_AUDIO_SHARING_HYSTERESIS_MODE_FIX); mSetFlagsRule.enableFlags(FLAG_AUDIO_SHARING_HYSTERESIS_MODE_FIX);
String address = "11:22:33:44:55:66"; 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.connecteddevice.audiosharing.audiostreams.AudioStreamsProgressCategoryController.UNSET_BROADCAST_ID;
import static com.android.settings.core.BasePreferenceController.AVAILABLE; 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_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; import static com.google.common.truth.Truth.assertThat;
@@ -48,6 +49,7 @@ import android.bluetooth.BluetoothLeAudioContentMetadata;
import android.bluetooth.BluetoothLeBroadcastMetadata; import android.bluetooth.BluetoothLeBroadcastMetadata;
import android.bluetooth.BluetoothLeBroadcastReceiveState; import android.bluetooth.BluetoothLeBroadcastReceiveState;
import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothStatusCodes;
import android.content.Context; import android.content.Context;
import android.os.Looper; import android.os.Looper;
import android.platform.test.flag.junit.SetFlagsRule; 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.R;
import com.android.settings.connecteddevice.audiosharing.audiostreams.testshadows.ShadowAudioStreamsHelper; 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.ShadowBluetoothUtils;
import com.android.settings.testutils.shadow.ShadowThreadUtils; import com.android.settings.testutils.shadow.ShadowThreadUtils;
import com.android.settingslib.bluetooth.BluetoothEventManager; import com.android.settingslib.bluetooth.BluetoothEventManager;
@@ -84,6 +87,7 @@ import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule; import org.mockito.junit.MockitoRule;
import org.robolectric.RobolectricTestRunner; import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config; import org.robolectric.annotation.Config;
import org.robolectric.shadow.api.Shadow;
import org.robolectric.shadows.ShadowAlertDialog; import org.robolectric.shadows.ShadowAlertDialog;
import org.robolectric.shadows.androidx.fragment.FragmentController; import org.robolectric.shadows.androidx.fragment.FragmentController;
@@ -97,6 +101,7 @@ import java.util.List;
ShadowAudioStreamsHelper.class, ShadowAudioStreamsHelper.class,
ShadowThreadUtils.class, ShadowThreadUtils.class,
ShadowAlertDialog.class, ShadowAlertDialog.class,
ShadowBluetoothAdapter.class,
}) })
public class AudioStreamsProgressCategoryControllerTest { public class AudioStreamsProgressCategoryControllerTest {
@Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule(); @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
@@ -129,6 +134,13 @@ public class AudioStreamsProgressCategoryControllerTest {
@Before @Before
public void setUp() { 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); ShadowAudioStreamsHelper.setUseMock(mAudioStreamsHelper);
when(mAudioStreamsHelper.getLeBroadcastAssistant()).thenReturn(mLeBroadcastAssistant); when(mAudioStreamsHelper.getLeBroadcastAssistant()).thenReturn(mLeBroadcastAssistant);
when(mAudioStreamsHelper.getAllConnectedSources()).thenReturn(emptyList()); when(mAudioStreamsHelper.getAllConnectedSources()).thenReturn(emptyList());
@@ -292,6 +304,7 @@ public class AudioStreamsProgressCategoryControllerTest {
@Test @Test
public void testOnStart_initHasDevice_getPresentSources() { public void testOnStart_initHasDevice_getPresentSources() {
mSetFlagsRule.enableFlags(FLAG_ENABLE_LE_AUDIO_SHARING);
mSetFlagsRule.enableFlags(FLAG_AUDIO_SHARING_HYSTERESIS_MODE_FIX); mSetFlagsRule.enableFlags(FLAG_AUDIO_SHARING_HYSTERESIS_MODE_FIX);
// Setup a device // Setup a device

View File

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

View File

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

View File

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

View File

@@ -16,12 +16,19 @@
package com.android.settings.notification.modes; 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 static com.google.common.truth.Truth.assertThat;
import android.app.Flags; import android.app.Flags;
import android.content.Context; import android.content.Context;
import android.platform.test.annotations.EnableFlags; import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule; 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.TestModeBuilder;
import com.android.settingslib.notification.modes.ZenIconLoader; import com.android.settingslib.notification.modes.ZenIconLoader;
@@ -37,6 +44,8 @@ import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner; import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment; import org.robolectric.RuntimeEnvironment;
import java.util.Calendar;
@RunWith(RobolectricTestRunner.class) @RunWith(RobolectricTestRunner.class)
@EnableFlags(Flags.FLAG_MODES_UI) @EnableFlags(Flags.FLAG_MODES_UI)
public class ZenModesListItemPreferenceTest { public class ZenModesListItemPreferenceTest {
@@ -122,6 +131,31 @@ public class ZenModesListItemPreferenceTest {
assertThat(preference.getIcon()).isNotNull(); 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) { private ZenModesListItemPreference newPreference(ZenMode zenMode) {
return new ZenModesListItemPreference(mContext, mIconLoader, MoreExecutors.directExecutor(), return new ZenModesListItemPreference(mContext, mIconLoader, MoreExecutors.directExecutor(),
zenMode); zenMode);

View File

@@ -91,6 +91,68 @@ class ApnTypesTest {
assertThat(apnType).isEqualTo("default,mms,supl,hipri,fota,cbs,xcap") 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 { private companion object {
const val APN_TYPE = "type" const val APN_TYPE = "type"
} }