Snap for 12651823 from b29b9b1b11 to 25Q1-release
Change-Id: Ifa207c095f83bbf430e5d91457b2e4ca6ce97d7e
This commit is contained in:
@@ -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>
|
||||
@@ -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>
|
||||
@@ -21,6 +21,15 @@
|
||||
android:height="@dimen/accessibility_icon_size"
|
||||
android:color="@color/accessibility_feature_background"/>
|
||||
</item>
|
||||
<item android:gravity="center"
|
||||
android:drawable="@drawable/ic_brightness_auto"/>
|
||||
<item android:gravity="center">
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="@dimen/accessibility_icon_foreground_size"
|
||||
android:height="@dimen/accessibility_icon_foreground_size"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M2 15V13H5V15H2ZM6.35 9.75L4.225 7.625L5.625 6.225L7.75 8.35L6.35 9.75ZM7 18V15H17V18H7ZM11 7V4H13V7H11ZM17.65 9.775L16.25 8.35L18.375 6.225L19.775 7.65L17.65 9.775ZM19 15V13H22V15H19Z"/>
|
||||
</vector>
|
||||
</item>
|
||||
</layer-list>
|
||||
@@ -21,6 +21,15 @@
|
||||
android:height="@dimen/accessibility_icon_size"
|
||||
android:color="@color/accessibility_feature_background"/>
|
||||
</item>
|
||||
<item android:gravity="center"
|
||||
android:drawable="@drawable/ic_brightness_medium"/>
|
||||
<item android:gravity="center">
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="@dimen/accessibility_icon_foreground_size"
|
||||
android:height="@dimen/accessibility_icon_foreground_size"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M9 14.5V13H15V14.5H9ZM8 11.5V10H16V11.5H8ZM7 23C6.45 23 5.975 22.8083 5.575 22.425C5.19167 22.025 5 21.55 5 21V3C5 2.45 5.19167 1.98333 5.575 1.6C5.975 1.2 6.45 0.999999 7 0.999999H17C17.55 0.999999 18.0167 1.2 18.4 1.6C18.8 1.98333 19 2.45 19 3V21C19 21.55 18.8 22.025 18.4 22.425C18.0167 22.8083 17.55 23 17 23H7ZM7 20V21H17V20H7ZM7 18H17V6H7V18ZM7 4H17V3H7V4ZM7 4V3V4ZM7 20V21V20Z"/>
|
||||
</vector>
|
||||
</item>
|
||||
</layer-list>
|
||||
@@ -2869,16 +2869,12 @@
|
||||
<string name="brightness">Brightness level</string>
|
||||
<!-- Sound & display settings screen, setting option name to enable adaptive brightness [CHAR LIMIT=30] -->
|
||||
<string name="auto_brightness_title">Adaptive brightness</string>
|
||||
<!-- Note: The content description title is only applied in adaptive brightness detailed page in setup wizard flow, to make the consistency with other accessibility suw pages. -->
|
||||
<!-- ContentDescription title for adaptive brightness detailed page footer. [CHAR LIMIT=60] -->
|
||||
<string name="auto_brightness_content_description_title">About adaptive brightness</string>
|
||||
<!-- Description about the feature adaptive brightness -->
|
||||
<string name="auto_brightness_description">Your screen brightness will automatically adjust to your environment and activities. You can move the slider manually to help adaptive brightness learn your preferences.</string>
|
||||
<!-- Setting option summary when adaptive brightness is on [CHAR LIMIT=NONE] -->
|
||||
<string name="auto_brightness_summary_on">On</string>
|
||||
<!-- Setting option summary when adaptive brightness is off [CHAR LIMIT=NONE] -->
|
||||
<string name="auto_brightness_summary_off">Off</string>
|
||||
|
||||
<!-- Display settings screen, display white balance settings title [CHAR LIMIT=30] -->
|
||||
<string name="display_white_balance_title">Display white balance</string>
|
||||
<!-- Display settings screen, display white balance settings summary [CHAR LIMIT=NONE] -->
|
||||
|
||||
@@ -37,11 +37,10 @@
|
||||
settings:useAdminDisabledSummary="true"
|
||||
settings:userRestriction="no_config_brightness"/>
|
||||
|
||||
<com.android.settingslib.PrimarySwitchPreference
|
||||
<com.android.settingslib.RestrictedSwitchPreference
|
||||
android:key="@string/preference_key_auto_brightness"
|
||||
android:icon="@drawable/ic_suw_brightness_auto"
|
||||
android:title="@string/auto_brightness_title"
|
||||
android:fragment="com.android.settings.accessibility.AutoBrightnessPreferenceFragmentForSetupWizard"
|
||||
settings:useAdminDisabledSummary="true"
|
||||
settings:userRestriction="no_config_brightness"
|
||||
settings:controller="com.android.settings.display.AutoBrightnessPreferenceControllerForSetupWizard"/>
|
||||
|
||||
@@ -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>
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -87,6 +87,12 @@ public class BluetoothDetailsCompanionAppsController extends BluetoothDetailsCon
|
||||
mProfilesContainer.setLayoutResource(R.layout.preference_companion_app);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
// Do not show this preference for now. More details in b/191992001#comment7
|
||||
return false;
|
||||
}
|
||||
|
||||
private List<AssociationInfo> getAssociations(String address) {
|
||||
return filter(
|
||||
mCompanionDeviceManager.getAllAssociations(),
|
||||
|
||||
@@ -110,7 +110,10 @@ public class AudioSharingCallAudioPreferenceController extends AudioSharingBaseP
|
||||
|
||||
@Override
|
||||
public void onSourceAdded(
|
||||
@NonNull BluetoothDevice sink, int sourceId, int reason) {}
|
||||
@NonNull BluetoothDevice sink, int sourceId, int reason) {
|
||||
Log.d(TAG, "onSourceAdded: updateSummary");
|
||||
updateSummary();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSourceAddFailed(
|
||||
@@ -138,12 +141,7 @@ public class AudioSharingCallAudioPreferenceController extends AudioSharingBaseP
|
||||
public void onReceiveStateChanged(
|
||||
@NonNull BluetoothDevice sink,
|
||||
int sourceId,
|
||||
@NonNull BluetoothLeBroadcastReceiveState state) {
|
||||
if (BluetoothUtils.isConnected(state)) {
|
||||
Log.d(TAG, "onReceiveStateChanged: synced, updateSummary");
|
||||
updateSummary();
|
||||
}
|
||||
}
|
||||
@NonNull BluetoothLeBroadcastReceiveState state) {}
|
||||
};
|
||||
|
||||
public AudioSharingCallAudioPreferenceController(Context context) {
|
||||
|
||||
@@ -116,7 +116,18 @@ public class AudioSharingDevicePreferenceController extends BasePreferenceContro
|
||||
|
||||
@Override
|
||||
public void onSourceAdded(
|
||||
@NonNull BluetoothDevice sink, int sourceId, int reason) {}
|
||||
@NonNull BluetoothDevice sink, int sourceId, int reason) {
|
||||
Log.d(TAG, "onSourceAdded: update sharing device list.");
|
||||
if (mBluetoothDeviceUpdater != null) {
|
||||
mBluetoothDeviceUpdater.forceUpdate();
|
||||
}
|
||||
if (mDeviceManager != null && mDialogHandler != null) {
|
||||
CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(sink);
|
||||
if (cachedDevice != null) {
|
||||
mDialogHandler.closeOpeningDialogsForLeaDevice(cachedDevice);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSourceAddFailed(
|
||||
@@ -173,20 +184,7 @@ public class AudioSharingDevicePreferenceController extends BasePreferenceContro
|
||||
public void onReceiveStateChanged(
|
||||
@NonNull BluetoothDevice sink,
|
||||
int sourceId,
|
||||
@NonNull BluetoothLeBroadcastReceiveState state) {
|
||||
if (BluetoothUtils.isConnected(state)) {
|
||||
Log.d(TAG, "onSourceAdded: update sharing device list.");
|
||||
if (mBluetoothDeviceUpdater != null) {
|
||||
mBluetoothDeviceUpdater.forceUpdate();
|
||||
}
|
||||
if (mDeviceManager != null && mDialogHandler != null) {
|
||||
CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(sink);
|
||||
if (cachedDevice != null) {
|
||||
mDialogHandler.closeOpeningDialogsForLeaDevice(cachedDevice);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@NonNull BluetoothLeBroadcastReceiveState state) {}
|
||||
};
|
||||
|
||||
public AudioSharingDevicePreferenceController(Context context) {
|
||||
|
||||
@@ -132,7 +132,12 @@ public class AudioSharingDeviceVolumeGroupController extends AudioSharingBasePre
|
||||
|
||||
@Override
|
||||
public void onSourceAdded(
|
||||
@NonNull BluetoothDevice sink, int sourceId, int reason) {}
|
||||
@NonNull BluetoothDevice sink, int sourceId, int reason) {
|
||||
Log.d(TAG, "onSourceAdded: update volume list.");
|
||||
if (mBluetoothDeviceUpdater != null) {
|
||||
mBluetoothDeviceUpdater.forceUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSourceAddFailed(
|
||||
@@ -165,14 +170,7 @@ public class AudioSharingDeviceVolumeGroupController extends AudioSharingBasePre
|
||||
public void onReceiveStateChanged(
|
||||
@NonNull BluetoothDevice sink,
|
||||
int sourceId,
|
||||
@NonNull BluetoothLeBroadcastReceiveState state) {
|
||||
if (BluetoothUtils.isConnected(state)) {
|
||||
Log.d(TAG, "onReceiveStateChanged: synced, update volume list.");
|
||||
if (mBluetoothDeviceUpdater != null) {
|
||||
mBluetoothDeviceUpdater.forceUpdate();
|
||||
}
|
||||
}
|
||||
}
|
||||
@NonNull BluetoothLeBroadcastReceiveState state) {}
|
||||
};
|
||||
|
||||
public AudioSharingDeviceVolumeGroupController(Context context) {
|
||||
|
||||
@@ -177,6 +177,20 @@ public class AudioSharingSwitchBarController extends BasePreferenceController
|
||||
+ broadcastId
|
||||
+ ", metadata = "
|
||||
+ metadata.getBroadcastName());
|
||||
if (mAssistant == null
|
||||
|| mAssistant.getAllConnectedDevices().stream()
|
||||
.anyMatch(
|
||||
device -> BluetoothUtils
|
||||
.hasActiveLocalBroadcastSourceForBtDevice(
|
||||
device, mBtManager))) {
|
||||
Log.d(
|
||||
TAG,
|
||||
"Skip handleOnBroadcastReady: null assistant or "
|
||||
+ "sink has active local source.");
|
||||
cleanUpStatesForStartSharing();
|
||||
return;
|
||||
}
|
||||
handleOnBroadcastReady();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -221,20 +235,6 @@ public class AudioSharingSwitchBarController extends BasePreferenceController
|
||||
+ reason
|
||||
+ ", broadcastId = "
|
||||
+ broadcastId);
|
||||
if (mAssistant == null
|
||||
|| mAssistant.getAllConnectedDevices().stream()
|
||||
.anyMatch(
|
||||
device -> BluetoothUtils
|
||||
.hasActiveLocalBroadcastSourceForBtDevice(
|
||||
device, mBtManager))) {
|
||||
Log.d(
|
||||
TAG,
|
||||
"Skip handleOnBroadcastReady: null assistant or "
|
||||
+ "sink has active local source.");
|
||||
cleanUpStatesForStartSharing();
|
||||
return;
|
||||
}
|
||||
handleOnBroadcastReady();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -261,7 +261,30 @@ public class AudioSharingSwitchBarController extends BasePreferenceController
|
||||
|
||||
@Override
|
||||
public void onSourceAdded(
|
||||
@NonNull BluetoothDevice sink, int sourceId, int reason) {}
|
||||
@NonNull BluetoothDevice sink, int sourceId, int reason) {
|
||||
if (mSinksInAdding.contains(sink)) {
|
||||
mSinksInAdding.remove(sink);
|
||||
}
|
||||
dismissProgressDialogIfNeeded();
|
||||
Log.d(TAG, "onSourceAdded(), sink = " + sink + ", remaining sinks = "
|
||||
+ mSinksInAdding);
|
||||
if (mSinksToWaitFor.contains(sink)) {
|
||||
mSinksToWaitFor.remove(sink);
|
||||
if (mSinksToWaitFor.isEmpty()) {
|
||||
// To avoid users advance to share then pair flow before the
|
||||
// primary/active sinks successfully join the audio sharing,
|
||||
// popup dialog till adding source complete for mSinksToWaitFor.
|
||||
Pair<Integer, Object>[] eventData =
|
||||
AudioSharingUtils.buildAudioSharingDialogEventData(
|
||||
SettingsEnums.AUDIO_SHARING_SETTINGS,
|
||||
SettingsEnums.DIALOG_AUDIO_SHARING_ADD_DEVICE,
|
||||
/* userTriggered= */ false,
|
||||
/* deviceCountInSharing= */ 1,
|
||||
/* candidateDeviceCount= */ 0);
|
||||
showAudioSharingDialog(eventData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSourceAddFailed(
|
||||
@@ -307,34 +330,9 @@ public class AudioSharingSwitchBarController extends BasePreferenceController
|
||||
@NonNull BluetoothDevice sink,
|
||||
int sourceId,
|
||||
@NonNull BluetoothLeBroadcastReceiveState state) {
|
||||
if (mStoppingSharing.get()) {
|
||||
Log.d(TAG, "Skip onReceiveStateChanged, stopping broadcast");
|
||||
return;
|
||||
}
|
||||
if (BluetoothUtils.isConnected(state)) {
|
||||
if (mSinksInAdding.contains(sink)) {
|
||||
mSinksInAdding.remove(sink);
|
||||
}
|
||||
dismissProgressDialogIfNeeded();
|
||||
Log.d(TAG, "onReceiveStateChanged() connected, sink = " + sink
|
||||
+ ", remaining sinks = " + mSinksInAdding);
|
||||
if (mSinksToWaitFor.contains(sink)) {
|
||||
mSinksToWaitFor.remove(sink);
|
||||
if (mSinksToWaitFor.isEmpty()) {
|
||||
// To avoid users advance to share then pair flow before the
|
||||
// primary/active sinks successfully join the audio sharing,
|
||||
// popup dialog till adding source complete for mSinksToWaitFor.
|
||||
Pair<Integer, Object>[] eventData =
|
||||
AudioSharingUtils.buildAudioSharingDialogEventData(
|
||||
SettingsEnums.AUDIO_SHARING_SETTINGS,
|
||||
SettingsEnums.DIALOG_AUDIO_SHARING_ADD_DEVICE,
|
||||
/* userTriggered= */ false,
|
||||
/* deviceCountInSharing= */ 1,
|
||||
/* candidateDeviceCount= */ 0);
|
||||
showAudioSharingDialog(eventData);
|
||||
}
|
||||
}
|
||||
}
|
||||
Log.d(TAG,
|
||||
"onReceiveStateChanged(), sink = " + sink + ", sourceId = " + sourceId
|
||||
+ ", state = " + state);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -46,7 +46,6 @@ import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
|
||||
import com.android.settingslib.bluetooth.VolumeControlProfile;
|
||||
import com.android.settingslib.flags.Flags;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
@@ -222,8 +221,8 @@ public class AudioSharingUtils {
|
||||
Log.d(TAG, "hasActiveConnectedLeadDevice return false due to null device manager.");
|
||||
return false;
|
||||
}
|
||||
return deviceManager.getCachedDevicesCopy().stream().anyMatch(
|
||||
BluetoothUtils::isActiveMediaDevice);
|
||||
return deviceManager.getCachedDevicesCopy().stream()
|
||||
.anyMatch(BluetoothUtils::isActiveMediaDevice);
|
||||
}
|
||||
|
||||
/** Build {@link AudioSharingDeviceItem} from {@link CachedBluetoothDevice}. */
|
||||
@@ -348,17 +347,18 @@ public class AudioSharingUtils {
|
||||
}
|
||||
|
||||
/** Set {@link CachedBluetoothDevice} as primary device for call audio */
|
||||
public static void setPrimary(@NonNull Context context,
|
||||
@Nullable CachedBluetoothDevice cachedDevice) {
|
||||
public static void setPrimary(
|
||||
@NonNull Context context, @Nullable CachedBluetoothDevice cachedDevice) {
|
||||
if (cachedDevice == null) return;
|
||||
cachedDevice.setActive();
|
||||
if (Flags.audioSharingHysteresisModeFix()) {
|
||||
if (BluetoothUtils.isAudioSharingHysteresisModeFixAvailable(context)) {
|
||||
int groupId = BluetoothUtils.getGroupId(cachedDevice);
|
||||
// TODO: use real key name in SettingsProvider
|
||||
int userPreferredId = Settings.Secure.getInt(
|
||||
context.getContentResolver(),
|
||||
BLUETOOTH_LE_BROADCAST_PRIMARY_DEVICE_GROUP_ID,
|
||||
BluetoothCsipSetCoordinator.GROUP_ID_INVALID);
|
||||
int userPreferredId =
|
||||
Settings.Secure.getInt(
|
||||
context.getContentResolver(),
|
||||
BLUETOOTH_LE_BROADCAST_PRIMARY_DEVICE_GROUP_ID,
|
||||
BluetoothCsipSetCoordinator.GROUP_ID_INVALID);
|
||||
if (groupId != userPreferredId) {
|
||||
Settings.Secure.putInt(
|
||||
context.getContentResolver(),
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
package com.android.settings.connecteddevice.audiosharing.audiostreams;
|
||||
|
||||
import static com.android.settingslib.flags.Flags.audioSharingHysteresisModeFix;
|
||||
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.BluetoothLeBroadcastAssistant;
|
||||
@@ -38,6 +36,7 @@ import com.android.settings.R;
|
||||
import com.android.settings.bluetooth.Utils;
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settingslib.bluetooth.BluetoothUtils;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant;
|
||||
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settingslib.utils.ThreadUtils;
|
||||
@@ -77,7 +76,7 @@ public class AudioStreamButtonController extends BasePreferenceController
|
||||
BluetoothLeBroadcastReceiveState state) {
|
||||
super.onReceiveStateChanged(sink, sourceId, state);
|
||||
boolean shouldUpdateButton =
|
||||
audioSharingHysteresisModeFix()
|
||||
BluetoothUtils.isAudioSharingHysteresisModeFixAvailable(mContext)
|
||||
? AudioStreamsHelper.hasSourcePresent(state)
|
||||
: AudioStreamsHelper.isConnected(state);
|
||||
if (shouldUpdateButton) {
|
||||
@@ -157,7 +156,7 @@ public class AudioStreamButtonController extends BasePreferenceController
|
||||
}
|
||||
|
||||
List<BluetoothLeBroadcastReceiveState> sources =
|
||||
audioSharingHysteresisModeFix()
|
||||
BluetoothUtils.isAudioSharingHysteresisModeFixAvailable(mContext)
|
||||
? mAudioStreamsHelper.getAllPresentSources()
|
||||
: mAudioStreamsHelper.getAllConnectedSources();
|
||||
boolean isConnected =
|
||||
|
||||
@@ -37,6 +37,7 @@ import com.android.settings.bluetooth.Utils;
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
import com.android.settings.dashboard.DashboardFragment;
|
||||
import com.android.settings.widget.EntityHeaderController;
|
||||
import com.android.settingslib.bluetooth.BluetoothUtils;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant;
|
||||
import com.android.settingslib.utils.ThreadUtils;
|
||||
import com.android.settingslib.widget.LayoutPreference;
|
||||
@@ -86,7 +87,7 @@ public class AudioStreamHeaderController extends BasePreferenceController
|
||||
updateSummary();
|
||||
mAudioStreamsHelper.startMediaService(
|
||||
mContext, mBroadcastId, mBroadcastName);
|
||||
} else if (audioSharingHysteresisModeFix()
|
||||
} else if (BluetoothUtils.isAudioSharingHysteresisModeFixAvailable(mContext)
|
||||
&& AudioStreamsHelper.hasSourcePresent(state)) {
|
||||
// if source present but not connected, only update the summary
|
||||
updateSummary();
|
||||
@@ -171,13 +172,13 @@ public class AudioStreamHeaderController extends BasePreferenceController
|
||||
: mContext.getString(
|
||||
AUDIO_STREAM_HEADER_PRESENT_NOW_SUMMARY))
|
||||
: mAudioStreamsHelper.getAllConnectedSources().stream()
|
||||
.map(
|
||||
BluetoothLeBroadcastReceiveState
|
||||
::getBroadcastId)
|
||||
.anyMatch(
|
||||
connectedBroadcastId ->
|
||||
connectedBroadcastId
|
||||
== mBroadcastId)
|
||||
.map(
|
||||
BluetoothLeBroadcastReceiveState
|
||||
::getBroadcastId)
|
||||
.anyMatch(
|
||||
connectedBroadcastId ->
|
||||
connectedBroadcastId
|
||||
== mBroadcastId)
|
||||
? mContext.getString(
|
||||
AUDIO_STREAM_HEADER_LISTENING_NOW_SUMMARY)
|
||||
: AUDIO_STREAM_HEADER_NOT_LISTENING_SUMMARY;
|
||||
|
||||
@@ -18,8 +18,6 @@ package com.android.settings.connecteddevice.audiosharing.audiostreams;
|
||||
|
||||
import static android.text.Spanned.SPAN_EXCLUSIVE_INCLUSIVE;
|
||||
|
||||
import static com.android.settingslib.flags.Flags.audioSharingHysteresisModeFix;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.text.SpannableString;
|
||||
@@ -98,7 +96,8 @@ class AudioStreamStateHandler {
|
||||
newState
|
||||
== AudioStreamsProgressCategoryController
|
||||
.AudioStreamState.SOURCE_ADDED
|
||||
|| (audioSharingHysteresisModeFix()
|
||||
|| (BluetoothUtils.isAudioSharingHysteresisModeFixAvailable(
|
||||
preference.getContext())
|
||||
&& newState
|
||||
== AudioStreamsProgressCategoryController
|
||||
.AudioStreamState.SOURCE_PRESENT));
|
||||
|
||||
@@ -31,7 +31,6 @@ import com.android.settingslib.bluetooth.BluetoothCallback;
|
||||
import com.android.settingslib.bluetooth.BluetoothUtils;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
||||
import com.android.settingslib.flags.Flags;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Executors;
|
||||
@@ -80,13 +79,6 @@ public class AudioStreamsCategoryController extends AudioSharingBasePreferenceCo
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAvailabilityStatus() {
|
||||
return Flags.enableLeAudioQrCodePrivateBroadcastSharing()
|
||||
? AVAILABLE
|
||||
: UNSUPPORTED_ON_DEVICE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateVisibility() {
|
||||
if (mPreference == null) return;
|
||||
|
||||
@@ -19,7 +19,6 @@ package com.android.settings.connecteddevice.audiosharing.audiostreams;
|
||||
import static com.android.settings.connecteddevice.audiosharing.audiostreams.AudioStreamMediaService.BROADCAST_ID;
|
||||
import static com.android.settings.connecteddevice.audiosharing.audiostreams.AudioStreamMediaService.BROADCAST_TITLE;
|
||||
import static com.android.settings.connecteddevice.audiosharing.audiostreams.AudioStreamMediaService.DEVICES;
|
||||
import static com.android.settingslib.flags.Flags.audioSharingHysteresisModeFix;
|
||||
|
||||
import static java.util.Collections.emptyList;
|
||||
|
||||
@@ -271,7 +270,8 @@ public class AudioStreamsHelper {
|
||||
List<BluetoothLeBroadcastReceiveState> sourceList =
|
||||
assistant.getAllSources(cachedDevice.getDevice());
|
||||
if (!sourceList.isEmpty()
|
||||
&& (audioSharingHysteresisModeFix()
|
||||
&& (BluetoothUtils.isAudioSharingHysteresisModeFixAvailable(
|
||||
localBtManager.getContext())
|
||||
|| sourceList.stream().anyMatch(AudioStreamsHelper::isConnected))) {
|
||||
Log.d(
|
||||
TAG,
|
||||
@@ -284,7 +284,8 @@ public class AudioStreamsHelper {
|
||||
List<BluetoothLeBroadcastReceiveState> list =
|
||||
assistant.getAllSources(device.getDevice());
|
||||
if (!list.isEmpty()
|
||||
&& (audioSharingHysteresisModeFix()
|
||||
&& (BluetoothUtils.isAudioSharingHysteresisModeFixAvailable(
|
||||
localBtManager.getContext())
|
||||
|| list.stream().anyMatch(AudioStreamsHelper::isConnected))) {
|
||||
Log.d(
|
||||
TAG,
|
||||
|
||||
@@ -16,19 +16,24 @@
|
||||
|
||||
package com.android.settings.connecteddevice.audiosharing.audiostreams;
|
||||
|
||||
import static com.android.settingslib.flags.Flags.audioSharingHysteresisModeFix;
|
||||
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.BluetoothLeBroadcastMetadata;
|
||||
import android.bluetooth.BluetoothLeBroadcastReceiveState;
|
||||
import android.content.Context;
|
||||
|
||||
import com.android.settingslib.bluetooth.BluetoothUtils;
|
||||
|
||||
public class AudioStreamsProgressCategoryCallback extends AudioStreamsBroadcastAssistantCallback {
|
||||
private static final String TAG = "AudioStreamsProgressCategoryCallback";
|
||||
|
||||
private final Context mContext;
|
||||
private final AudioStreamsProgressCategoryController mCategoryController;
|
||||
|
||||
public AudioStreamsProgressCategoryCallback(
|
||||
Context context,
|
||||
AudioStreamsProgressCategoryController audioStreamsProgressCategoryController) {
|
||||
mContext = context;
|
||||
mCategoryController = audioStreamsProgressCategoryController;
|
||||
}
|
||||
|
||||
@@ -41,7 +46,8 @@ public class AudioStreamsProgressCategoryCallback extends AudioStreamsBroadcastA
|
||||
mCategoryController.handleSourceConnected(state);
|
||||
} else if (AudioStreamsHelper.isBadCode(state)) {
|
||||
mCategoryController.handleSourceConnectBadCode(state);
|
||||
} else if (audioSharingHysteresisModeFix() && AudioStreamsHelper.hasSourcePresent(state)) {
|
||||
} else if (BluetoothUtils.isAudioSharingHysteresisModeFixAvailable(mContext)
|
||||
&& AudioStreamsHelper.hasSourcePresent(state)) {
|
||||
// Keep this check as the last, source might also present in above states
|
||||
mCategoryController.handleSourcePresent(state);
|
||||
}
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
package com.android.settings.connecteddevice.audiosharing.audiostreams;
|
||||
|
||||
import static com.android.settingslib.flags.Flags.audioSharingHysteresisModeFix;
|
||||
|
||||
import static java.util.Collections.emptyList;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
@@ -101,7 +99,7 @@ public class AudioStreamsProgressCategoryController extends BasePreferenceContro
|
||||
(p.getAudioStreamState()
|
||||
== AudioStreamsProgressCategoryController
|
||||
.AudioStreamState.SOURCE_ADDED
|
||||
|| (audioSharingHysteresisModeFix()
|
||||
|| (isAudioSharingHysteresisModeFixAvailable(mContext)
|
||||
&& p.getAudioStreamState()
|
||||
== AudioStreamsProgressCategoryController
|
||||
.AudioStreamState
|
||||
@@ -147,7 +145,7 @@ public class AudioStreamsProgressCategoryController extends BasePreferenceContro
|
||||
mAudioStreamsHelper = new AudioStreamsHelper(mBluetoothManager);
|
||||
mMediaControlHelper = new MediaControlHelper(mContext, mBluetoothManager);
|
||||
mLeBroadcastAssistant = mAudioStreamsHelper.getLeBroadcastAssistant();
|
||||
mBroadcastAssistantCallback = new AudioStreamsProgressCategoryCallback(this);
|
||||
mBroadcastAssistantCallback = new AudioStreamsProgressCategoryCallback(context, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -258,7 +256,7 @@ public class AudioStreamsProgressCategoryController extends BasePreferenceContro
|
||||
// change it's state.
|
||||
existingPreference.setAudioStreamMetadata(source);
|
||||
if (fromState != AudioStreamState.SOURCE_ADDED
|
||||
&& (!audioSharingHysteresisModeFix()
|
||||
&& (!isAudioSharingHysteresisModeFixAvailable(mContext)
|
||||
|| fromState != AudioStreamState.SOURCE_PRESENT)) {
|
||||
Log.w(
|
||||
TAG,
|
||||
@@ -364,7 +362,7 @@ public class AudioStreamsProgressCategoryController extends BasePreferenceContro
|
||||
// not, means the source is removed from the sink, we move back the preference to SYNCED
|
||||
// state.
|
||||
if ((preference.getAudioStreamState() == AudioStreamState.SOURCE_ADDED
|
||||
|| (audioSharingHysteresisModeFix()
|
||||
|| (isAudioSharingHysteresisModeFixAvailable(mContext)
|
||||
&& preference.getAudioStreamState()
|
||||
== AudioStreamState.SOURCE_PRESENT))
|
||||
&& mAudioStreamsHelper.getAllConnectedSources().stream()
|
||||
@@ -600,7 +598,7 @@ public class AudioStreamsProgressCategoryController extends BasePreferenceContro
|
||||
// Handle QR code scan, display currently connected streams then start scanning
|
||||
// sequentially
|
||||
handleSourceFromQrCodeIfExists();
|
||||
if (audioSharingHysteresisModeFix()) {
|
||||
if (isAudioSharingHysteresisModeFixAvailable(mContext)) {
|
||||
// With hysteresis mode, we prioritize showing connected sources first.
|
||||
// If no connected sources are found, we then show present sources.
|
||||
List<BluetoothLeBroadcastReceiveState> sources =
|
||||
@@ -702,4 +700,8 @@ public class AudioStreamsProgressCategoryController extends BasePreferenceContro
|
||||
dialog.dismiss();
|
||||
});
|
||||
}
|
||||
|
||||
private static boolean isAudioSharingHysteresisModeFixAvailable(Context context) {
|
||||
return BluetoothUtils.isAudioSharingHysteresisModeFixAvailable(context);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,6 @@ import com.android.settings.accessibility.AccessibilityDetailsSettingsFragment;
|
||||
import com.android.settings.accessibility.AccessibilityHearingAidsFragment;
|
||||
import com.android.settings.accessibility.AccessibilitySettings;
|
||||
import com.android.settings.accessibility.AccessibilitySettingsForSetupWizard;
|
||||
import com.android.settings.accessibility.AutoBrightnessPreferenceFragmentForSetupWizard;
|
||||
import com.android.settings.accessibility.CaptioningPropertiesFragment;
|
||||
import com.android.settings.accessibility.ColorAndMotionFragment;
|
||||
import com.android.settings.accessibility.HearingDevicePairingFragment;
|
||||
@@ -268,7 +267,6 @@ public class SettingsGateway {
|
||||
EditShortcutsPreferenceFragment.class.getName(),
|
||||
TextReadingPreferenceFragment.class.getName(),
|
||||
TextReadingPreferenceFragmentForSetupWizard.class.getName(),
|
||||
AutoBrightnessPreferenceFragmentForSetupWizard.class.getName(),
|
||||
CaptioningPropertiesFragment.class.getName(),
|
||||
ToggleDaltonizerPreferenceFragment.class.getName(),
|
||||
ToggleColorInversionPreferenceFragment.class.getName(),
|
||||
|
||||
@@ -41,4 +41,9 @@ public class AutoBrightnessPreferenceControllerForSetupWizard
|
||||
}
|
||||
return super.getAvailabilityStatus();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getSummary() {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,35 +19,43 @@ package com.android.settings.network
|
||||
import android.content.Context
|
||||
import android.net.wifi.WifiManager
|
||||
import android.provider.Settings.Secure.ADAPTIVE_CONNECTIVITY_ENABLED
|
||||
import androidx.preference.Preference
|
||||
import com.android.settings.R
|
||||
import com.android.settingslib.datastore.KeyValueStore
|
||||
import com.android.settingslib.datastore.KeyedObservableDelegate
|
||||
import com.android.settingslib.datastore.SettingsSecureStore
|
||||
import com.android.settingslib.datastore.SettingsStore
|
||||
import com.android.settingslib.metadata.MainSwitchPreference
|
||||
import com.android.settingslib.metadata.PreferenceMetadata
|
||||
import com.android.settingslib.preference.MainSwitchPreferenceBinding
|
||||
|
||||
// LINT.IfChange
|
||||
class AdaptiveConnectivityTogglePreference :
|
||||
MainSwitchPreference(
|
||||
ADAPTIVE_CONNECTIVITY_ENABLED,
|
||||
R.string.adaptive_connectivity_main_switch_title,
|
||||
),
|
||||
MainSwitchPreferenceBinding,
|
||||
Preference.OnPreferenceChangeListener {
|
||||
MainSwitchPreference(KEY, R.string.adaptive_connectivity_main_switch_title) {
|
||||
|
||||
override fun storage(context: Context) = SettingsSecureStore.get(context)
|
||||
override fun storage(context: Context): KeyValueStore =
|
||||
AdaptiveConnectivityToggleStorage(context, SettingsSecureStore.get(context))
|
||||
|
||||
override fun bind(preference: Preference, metadata: PreferenceMetadata) {
|
||||
super.bind(preference, metadata)
|
||||
preference.onPreferenceChangeListener = this
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
private class AdaptiveConnectivityToggleStorage(
|
||||
private val context: Context,
|
||||
private val settingsStore: SettingsStore,
|
||||
) : KeyedObservableDelegate<String>(settingsStore), KeyValueStore {
|
||||
|
||||
override fun contains(key: String) = settingsStore.contains(KEY)
|
||||
|
||||
override fun <T : Any> getDefaultValue(key: String, valueType: Class<T>) =
|
||||
DEFAULT_VALUE as T
|
||||
|
||||
override fun <T : Any> getValue(key: String, valueType: Class<T>) =
|
||||
(settingsStore.getBoolean(key) ?: DEFAULT_VALUE) as T
|
||||
|
||||
override fun <T : Any> setValue(key: String, valueType: Class<T>, value: T?) {
|
||||
settingsStore.setBoolean(key, value as Boolean)
|
||||
context.getSystemService(WifiManager::class.java)?.setWifiScoringEnabled(value)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPreferenceChange(preference: Preference, newValue: Any): Boolean {
|
||||
val isChecked = newValue as Boolean
|
||||
preference.context
|
||||
.getSystemService(WifiManager::class.java)
|
||||
?.setWifiScoringEnabled(isChecked)
|
||||
return true
|
||||
companion object {
|
||||
const val KEY = ADAPTIVE_CONNECTIVITY_ENABLED
|
||||
const val DEFAULT_VALUE = true
|
||||
}
|
||||
}
|
||||
// LINT.ThenChange(AdaptiveConnectivityTogglePreferenceController.java)
|
||||
|
||||
@@ -23,88 +23,21 @@ import android.app.settings.SettingsEnums;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.PersistableBundle;
|
||||
import android.os.UserManager;
|
||||
import android.provider.Telephony;
|
||||
import android.telephony.CarrierConfigManager;
|
||||
import android.telephony.SubscriptionManager;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import com.android.internal.util.ArrayUtils;
|
||||
import com.android.settings.SettingsPreferenceFragment;
|
||||
import com.android.settings.spa.SpaActivity;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/** Use to edit apn settings. */
|
||||
public class ApnEditor extends SettingsPreferenceFragment {
|
||||
|
||||
private static final String TAG = ApnEditor.class.getSimpleName();
|
||||
|
||||
/**
|
||||
* APN types for data connections. These are usage categories for an APN
|
||||
* entry. One APN entry may support multiple APN types, eg, a single APN
|
||||
* may service regular internet traffic ("default") as well as MMS-specific
|
||||
* connections.<br/>
|
||||
* APN_TYPE_ALL is a special type to indicate that this APN entry can
|
||||
* service all data connections.
|
||||
*/
|
||||
public static final String APN_TYPE_ALL = "*";
|
||||
/** APN type for default data traffic */
|
||||
public static final String APN_TYPE_DEFAULT = "default";
|
||||
/** APN type for MMS traffic */
|
||||
public static final String APN_TYPE_MMS = "mms";
|
||||
/** APN type for SUPL assisted GPS */
|
||||
public static final String APN_TYPE_SUPL = "supl";
|
||||
/** APN type for DUN traffic */
|
||||
public static final String APN_TYPE_DUN = "dun";
|
||||
/** APN type for HiPri traffic */
|
||||
public static final String APN_TYPE_HIPRI = "hipri";
|
||||
/** APN type for FOTA */
|
||||
public static final String APN_TYPE_FOTA = "fota";
|
||||
/** APN type for IMS */
|
||||
public static final String APN_TYPE_IMS = "ims";
|
||||
/** APN type for CBS */
|
||||
public static final String APN_TYPE_CBS = "cbs";
|
||||
/** APN type for IA Initial Attach APN */
|
||||
public static final String APN_TYPE_IA = "ia";
|
||||
/** APN type for Emergency PDN. This is not an IA apn, but is used
|
||||
* for access to carrier services in an emergency call situation. */
|
||||
public static final String APN_TYPE_EMERGENCY = "emergency";
|
||||
/** APN type for Mission Critical Services */
|
||||
public static final String APN_TYPE_MCX = "mcx";
|
||||
/** APN type for XCAP */
|
||||
public static final String APN_TYPE_XCAP = "xcap";
|
||||
/** APN type for OEM_PAID networks (Automotive PANS) */
|
||||
public static final String APN_TYPE_OEM_PAID = "oem_paid";
|
||||
/** APN type for OEM_PRIVATE networks (Automotive PANS) */
|
||||
public static final String APN_TYPE_OEM_PRIVATE = "oem_private";
|
||||
/** Array of all APN types */
|
||||
public static final String[] APN_TYPES = {APN_TYPE_DEFAULT,
|
||||
APN_TYPE_MMS,
|
||||
APN_TYPE_SUPL,
|
||||
APN_TYPE_DUN,
|
||||
APN_TYPE_HIPRI,
|
||||
APN_TYPE_FOTA,
|
||||
APN_TYPE_IMS,
|
||||
APN_TYPE_CBS,
|
||||
APN_TYPE_IA,
|
||||
APN_TYPE_EMERGENCY,
|
||||
APN_TYPE_MCX,
|
||||
APN_TYPE_XCAP,
|
||||
APN_TYPE_OEM_PAID,
|
||||
APN_TYPE_OEM_PRIVATE,
|
||||
};
|
||||
|
||||
/** Array of APN types that are never user-editable */
|
||||
private static final String[] ALWAYS_READ_ONLY_APN_TYPES = new String[] {
|
||||
APN_TYPE_OEM_PAID,
|
||||
APN_TYPE_OEM_PRIVATE,
|
||||
};
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle icicle) {
|
||||
super.onCreate(icicle);
|
||||
@@ -143,43 +76,6 @@ public class ApnEditor extends SettingsPreferenceFragment {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch complete list of read only APN types.
|
||||
*
|
||||
* The list primarily comes from carrier config, but is also supplied by APN types which are
|
||||
* always read only.
|
||||
*/
|
||||
static String[] getReadOnlyApnTypes(PersistableBundle b) {
|
||||
String[] carrierReadOnlyApnTypes = b.getStringArray(
|
||||
CarrierConfigManager.KEY_READ_ONLY_APN_TYPES_STRING_ARRAY);
|
||||
return ArrayUtils.concat(String.class, carrierReadOnlyApnTypes, ALWAYS_READ_ONLY_APN_TYPES);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if passed in array of APN types indicates all APN types
|
||||
* @param apnTypes array of APN types. "*" indicates all types.
|
||||
* @return true if all apn types are included in the array, false otherwise
|
||||
*/
|
||||
static boolean hasAllApns(String[] apnTypes) {
|
||||
if (ArrayUtils.isEmpty(apnTypes)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final List apnList = Arrays.asList(apnTypes);
|
||||
if (apnList.contains(APN_TYPE_ALL)) {
|
||||
Log.d(TAG, "hasAllApns: true because apnList.contains(APN_TYPE_ALL)");
|
||||
return true;
|
||||
}
|
||||
for (String apn : APN_TYPES) {
|
||||
if (!apnList.contains(apn)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Log.d(TAG, "hasAllApns: true");
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
return SettingsEnums.APN_EDITOR;
|
||||
|
||||
@@ -23,7 +23,6 @@ import android.app.Dialog;
|
||||
import android.app.ProgressDialog;
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
@@ -34,7 +33,6 @@ import android.provider.Telephony;
|
||||
import android.telephony.CarrierConfigManager;
|
||||
import android.telephony.SubscriptionManager;
|
||||
import android.telephony.data.ApnSetting;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
@@ -51,7 +49,6 @@ import androidx.preference.PreferenceGroup;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.RestrictedSettingsFragment;
|
||||
import com.android.settings.flags.Flags;
|
||||
import com.android.settings.network.telephony.SubscriptionRepository;
|
||||
import com.android.settings.spa.SpaActivity;
|
||||
import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
|
||||
@@ -59,6 +56,7 @@ import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
|
||||
import kotlin.Unit;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/** Handle each different apn setting. */
|
||||
public class ApnSettings extends RestrictedSettingsFragment
|
||||
@@ -68,16 +66,12 @@ public class ApnSettings extends RestrictedSettingsFragment
|
||||
public static final String APN_ID = "apn_id";
|
||||
public static final String APN_LIST = "apn_list";
|
||||
public static final String SUB_ID = "sub_id";
|
||||
public static final String MVNO_TYPE = "mvno_type";
|
||||
public static final String MVNO_MATCH_DATA = "mvno_match_data";
|
||||
|
||||
private static final String[] CARRIERS_PROJECTION = new String[] {
|
||||
Telephony.Carriers._ID,
|
||||
Telephony.Carriers.NAME,
|
||||
Telephony.Carriers.APN,
|
||||
Telephony.Carriers.TYPE,
|
||||
Telephony.Carriers.MVNO_TYPE,
|
||||
Telephony.Carriers.MVNO_MATCH_DATA,
|
||||
Telephony.Carriers.EDITED_STATUS,
|
||||
};
|
||||
|
||||
@@ -85,9 +79,7 @@ public class ApnSettings extends RestrictedSettingsFragment
|
||||
private static final int NAME_INDEX = 1;
|
||||
private static final int APN_INDEX = 2;
|
||||
private static final int TYPES_INDEX = 3;
|
||||
private static final int MVNO_TYPE_INDEX = 4;
|
||||
private static final int MVNO_MATCH_DATA_INDEX = 5;
|
||||
private static final int EDITED_INDEX = 6;
|
||||
private static final int EDITED_INDEX = 4;
|
||||
|
||||
private static final int MENU_NEW = Menu.FIRST;
|
||||
private static final int MENU_RESTORE = Menu.FIRST + 1;
|
||||
@@ -101,8 +93,6 @@ public class ApnSettings extends RestrictedSettingsFragment
|
||||
private PreferredApnRepository mPreferredApnRepository;
|
||||
@Nullable
|
||||
private String mPreferredApnKey;
|
||||
private String mMvnoType;
|
||||
private String mMvnoMatchData;
|
||||
|
||||
private boolean mUnavailable;
|
||||
|
||||
@@ -135,9 +125,9 @@ public class ApnSettings extends RestrictedSettingsFragment
|
||||
mHideImsApn = b.getBoolean(CarrierConfigManager.KEY_HIDE_IMS_APN_BOOL);
|
||||
mAllowAddingApns = b.getBoolean(CarrierConfigManager.KEY_ALLOW_ADDING_APNS_BOOL);
|
||||
if (mAllowAddingApns) {
|
||||
final String[] readOnlyApnTypes = ApnEditor.getReadOnlyApnTypes(b);
|
||||
final List<String> readOnlyApnTypes = ApnTypes.getReadOnlyApnTypes(b);
|
||||
// if no apn type can be edited, do not allow adding APNs
|
||||
if (ApnEditor.hasAllApns(readOnlyApnTypes)) {
|
||||
if (ApnTypes.hasAllApnTypes(readOnlyApnTypes)) {
|
||||
Log.d(TAG, "not allowing adding APN because all APN types are read only");
|
||||
mAllowAddingApns = false;
|
||||
}
|
||||
@@ -241,8 +231,6 @@ public class ApnSettings extends RestrictedSettingsFragment
|
||||
final String key = cursor.getString(ID_INDEX);
|
||||
final String type = cursor.getString(TYPES_INDEX);
|
||||
final int edited = cursor.getInt(EDITED_INDEX);
|
||||
mMvnoType = cursor.getString(MVNO_TYPE_INDEX);
|
||||
mMvnoMatchData = cursor.getString(MVNO_MATCH_DATA_INDEX);
|
||||
|
||||
final ApnPreference pref = new ApnPreference(getPrefContext());
|
||||
|
||||
@@ -310,20 +298,9 @@ public class ApnSettings extends RestrictedSettingsFragment
|
||||
}
|
||||
|
||||
private void addNewApn() {
|
||||
if (Flags.newApnPageEnabled()) {
|
||||
String route = ApnEditPageProvider.INSTANCE.getRoute(
|
||||
INSERT_URL, Telephony.Carriers.CONTENT_URI, mSubId);
|
||||
SpaActivity.startSpaActivity(getContext(), route);
|
||||
} else {
|
||||
final Intent intent = new Intent(Intent.ACTION_INSERT, Telephony.Carriers.CONTENT_URI);
|
||||
intent.putExtra(SUB_ID, mSubId);
|
||||
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
if (!TextUtils.isEmpty(mMvnoType) && !TextUtils.isEmpty(mMvnoMatchData)) {
|
||||
intent.putExtra(MVNO_TYPE, mMvnoType);
|
||||
intent.putExtra(MVNO_MATCH_DATA, mMvnoMatchData);
|
||||
}
|
||||
startActivity(intent);
|
||||
}
|
||||
String route = ApnEditPageProvider.INSTANCE.getRoute(
|
||||
INSERT_URL, Telephony.Carriers.CONTENT_URI, mSubId);
|
||||
SpaActivity.startSpaActivity(getContext(), route);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -25,6 +25,7 @@ import android.telephony.CarrierConfigManager
|
||||
import android.util.Log
|
||||
import com.android.settings.R
|
||||
import com.android.settings.network.apn.ApnTypes.getPreSelectedApnType
|
||||
import com.android.settings.network.apn.ApnTypes.getReadOnlyApnTypes
|
||||
|
||||
private const val TAG = "ApnStatus"
|
||||
|
||||
@@ -204,7 +205,7 @@ fun getCarrierCustomizedConfig(
|
||||
CarrierConfigManager.KEY_ALLOW_ADDING_APNS_BOOL
|
||||
)
|
||||
val customizedConfig = CustomizedConfig(
|
||||
readOnlyApnTypes = ApnEditor.getReadOnlyApnTypes(b)?.toList() ?: emptyList(),
|
||||
readOnlyApnTypes = b.getReadOnlyApnTypes(),
|
||||
readOnlyApnFields = b.getStringArray(
|
||||
CarrierConfigManager.KEY_READ_ONLY_APN_FIELDS_STRING_ARRAY
|
||||
)?.toList() ?: emptyList(),
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
package com.android.settings.network.apn
|
||||
|
||||
import android.content.Context
|
||||
import android.os.PersistableBundle
|
||||
import android.telephony.CarrierConfigManager
|
||||
import android.telephony.data.ApnSetting
|
||||
import android.util.Log
|
||||
import android.widget.Toast
|
||||
@@ -51,9 +53,7 @@ object ApnTypes {
|
||||
|
||||
private fun splitToList(apnType: String): List<String> {
|
||||
val types = apnType.split(',').map { it.trim().toLowerCase(Locale.current) }
|
||||
if (ApnSetting.TYPE_ALL_STRING in types || APN_TYPES.all { it in types }) {
|
||||
return listOf(ApnSetting.TYPE_ALL_STRING)
|
||||
}
|
||||
if (hasAllApnTypes(types)) return listOf(ApnSetting.TYPE_ALL_STRING)
|
||||
return APN_TYPES.filter { it in types }
|
||||
}
|
||||
|
||||
@@ -132,4 +132,32 @@ object ApnTypes {
|
||||
private fun defaultPreSelectedApnTypes(readOnlyApnTypes: List<String>) =
|
||||
if (ApnSetting.TYPE_ALL_STRING in readOnlyApnTypes) emptyList()
|
||||
else PreSelectedTypes.filterNot { it in readOnlyApnTypes }
|
||||
|
||||
/** Array of APN types that are never user-editable */
|
||||
private val ALWAYS_READ_ONLY_APN_TYPES =
|
||||
arrayOf(ApnSetting.TYPE_OEM_PAID_STRING, ApnSetting.TYPE_OEM_PRIVATE_STRING)
|
||||
|
||||
/**
|
||||
* Fetch complete list of read only APN types.
|
||||
*
|
||||
* The list primarily comes from carrier config, but is also supplied by APN types which are
|
||||
* always read only.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun PersistableBundle.getReadOnlyApnTypes(): List<String> {
|
||||
val carrierReadOnlyApnTypes =
|
||||
getStringArray(CarrierConfigManager.KEY_READ_ONLY_APN_TYPES_STRING_ARRAY)?.toList()
|
||||
?: emptyList()
|
||||
return carrierReadOnlyApnTypes + ALWAYS_READ_ONLY_APN_TYPES
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if passed in array of APN types indicates all APN types
|
||||
*
|
||||
* @param apnTypes array of APN types. "*" indicates all types.
|
||||
* @return true if all apn types are included in the array, false otherwise
|
||||
*/
|
||||
@JvmStatic
|
||||
fun hasAllApnTypes(apnTypes: List<String>): Boolean =
|
||||
ApnSetting.TYPE_ALL_STRING in apnTypes || APN_TYPES.all { it in apnTypes }
|
||||
}
|
||||
|
||||
@@ -101,6 +101,8 @@ public class SoundPreferenceController extends NotificationPreferenceController
|
||||
public boolean handlePreferenceTreeClick(Preference preference) {
|
||||
if (KEY_SOUND.equals(preference.getKey()) && mFragment != null) {
|
||||
NotificationSoundPreference pref = (NotificationSoundPreference) preference;
|
||||
// default to notification
|
||||
pref.setRingtoneType(RingtoneManager.TYPE_NOTIFICATION);
|
||||
if (mChannel != null && mChannel.getAudioAttributes() != null) {
|
||||
if (USAGE_ALARM == mChannel.getAudioAttributes().getUsage()) {
|
||||
pref.setRingtoneType(RingtoneManager.TYPE_ALARM);
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.android.settings.notification.modes;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.app.INotificationManager;
|
||||
import android.app.ZenBypassingApp;
|
||||
import android.content.ContentProvider;
|
||||
import android.content.Context;
|
||||
import android.content.pm.ParceledListSlice;
|
||||
@@ -30,6 +31,7 @@ import android.os.UserManager;
|
||||
import android.provider.ContactsContract;
|
||||
import android.provider.ContactsContract.Contacts;
|
||||
import android.service.notification.ConversationChannelWrapper;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
@@ -41,8 +43,9 @@ import com.google.common.collect.ImmutableList;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
@@ -76,16 +79,20 @@ class ZenHelperBackend {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all of a user's packages that have at least one channel that will bypass DND
|
||||
* Returns a mapping between a user's packages that have at least one channel that will
|
||||
* bypass DND, and a Boolean indicating whether all of the package's channels bypass.
|
||||
*/
|
||||
List<String> getPackagesBypassingDnd(int userId,
|
||||
boolean includeConversationChannels) {
|
||||
Map<String, Boolean> getPackagesBypassingDnd(int userId) {
|
||||
Map<String, Boolean> bypassingAppsMap = new HashMap<>();
|
||||
try {
|
||||
return mInm.getPackagesBypassingDnd(userId, includeConversationChannels);
|
||||
List<ZenBypassingApp> bypassingApps = mInm.getPackagesBypassingDnd(userId).getList();
|
||||
for (ZenBypassingApp zba : bypassingApps) {
|
||||
bypassingAppsMap.put(zba.getPkg(), zba.doAllChannelsBypass());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.w(TAG, "Error calling NoMan", e);
|
||||
return new ArrayList<>();
|
||||
}
|
||||
return bypassingAppsMap;
|
||||
}
|
||||
|
||||
/** Returns all conversation channels for profiles of the current user. */
|
||||
|
||||
@@ -22,7 +22,9 @@ import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Bundle;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.core.text.BidiFormatter;
|
||||
@@ -35,7 +37,6 @@ import com.android.settings.R;
|
||||
import com.android.settings.applications.AppInfoBase;
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settings.core.SubSettingLauncher;
|
||||
import com.android.settings.notification.NotificationBackend;
|
||||
import com.android.settings.notification.app.AppChannelsBypassingDndSettings;
|
||||
import com.android.settingslib.applications.AppUtils;
|
||||
import com.android.settingslib.applications.ApplicationsState;
|
||||
@@ -44,7 +45,9 @@ import com.android.settingslib.utils.ThreadUtils;
|
||||
import com.android.settingslib.widget.AppPreference;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Adds a preference to the PreferenceScreen for each notification channel that can bypass DND.
|
||||
@@ -54,7 +57,8 @@ public class ZenModeAllBypassingAppsPreferenceController extends AbstractPrefere
|
||||
public static final String KEY_NO_APPS = "all_none";
|
||||
private static final String KEY = "zen_mode_bypassing_apps_list";
|
||||
|
||||
@Nullable private final NotificationBackend mNotificationBackend;
|
||||
@Nullable private final ZenHelperBackend mHelperBackend;
|
||||
private final UserManager mUserManager;
|
||||
|
||||
@Nullable @VisibleForTesting ApplicationsState mApplicationsState;
|
||||
@VisibleForTesting PreferenceCategory mPreferenceCategory;
|
||||
@@ -64,18 +68,18 @@ public class ZenModeAllBypassingAppsPreferenceController extends AbstractPrefere
|
||||
@Nullable private Fragment mHostFragment;
|
||||
|
||||
public ZenModeAllBypassingAppsPreferenceController(Context context, @Nullable Application app,
|
||||
@Nullable Fragment host, @Nullable NotificationBackend notificationBackend) {
|
||||
this(context, app == null ? null : ApplicationsState.getInstance(app), host,
|
||||
notificationBackend);
|
||||
@Nullable Fragment host, @Nullable ZenHelperBackend helperBackend) {
|
||||
this(context, app == null ? null : ApplicationsState.getInstance(app), host, helperBackend);
|
||||
}
|
||||
|
||||
private ZenModeAllBypassingAppsPreferenceController(Context context,
|
||||
@Nullable ApplicationsState appState, @Nullable Fragment host,
|
||||
@Nullable NotificationBackend notificationBackend) {
|
||||
@Nullable ZenHelperBackend helperBackend) {
|
||||
super(context);
|
||||
mNotificationBackend = notificationBackend;
|
||||
mApplicationsState = appState;
|
||||
mHostFragment = host;
|
||||
mHelperBackend = helperBackend;
|
||||
mUserManager = context.getSystemService(UserManager.class);
|
||||
|
||||
if (mApplicationsState != null && host != null) {
|
||||
mAppSession = mApplicationsState.newSession(mAppSessionCallbacks, host.getLifecycle());
|
||||
@@ -140,19 +144,25 @@ public class ZenModeAllBypassingAppsPreferenceController extends AbstractPrefere
|
||||
}
|
||||
|
||||
boolean doAnyAppsPassCriteria = false;
|
||||
Map<Integer, Map<String, Boolean>> packagesBypassingDndByUser = new HashMap<>();
|
||||
for (UserHandle userHandle : mUserManager.getUserProfiles()) {
|
||||
packagesBypassingDndByUser.put(userHandle.getIdentifier(),
|
||||
mHelperBackend.getPackagesBypassingDnd(userHandle.getIdentifier()));
|
||||
}
|
||||
for (ApplicationsState.AppEntry app : apps) {
|
||||
String pkg = app.info.packageName;
|
||||
final String key = getKey(pkg, app.info.uid);
|
||||
final int appChannels = mNotificationBackend.getChannelCount(pkg, app.info.uid);
|
||||
final int appChannelsBypassingDnd = mNotificationBackend
|
||||
.getNotificationChannelsBypassingDnd(pkg, app.info.uid).getList().size();
|
||||
if (appChannelsBypassingDnd > 0) {
|
||||
boolean doesAppBypassDnd = false;
|
||||
int userId = UserHandle.getUserId(app.info.uid);
|
||||
Map<String, Boolean> packagesBypassingDnd =
|
||||
packagesBypassingDndByUser.getOrDefault(userId, new HashMap<>());
|
||||
if (packagesBypassingDnd.containsKey(pkg)) {
|
||||
doAnyAppsPassCriteria = true;
|
||||
doesAppBypassDnd = true;
|
||||
}
|
||||
|
||||
Preference pref = mPreferenceCategory.findPreference(key);
|
||||
if (pref == null) {
|
||||
if (appChannelsBypassingDnd > 0) {
|
||||
if (doesAppBypassDnd) {
|
||||
// does not exist but should
|
||||
pref = new AppPreference(mPrefContext);
|
||||
pref.setKey(key);
|
||||
@@ -172,14 +182,14 @@ public class ZenModeAllBypassingAppsPreferenceController extends AbstractPrefere
|
||||
});
|
||||
pref.setTitle(BidiFormatter.getInstance().unicodeWrap(app.label));
|
||||
updateIcon(pref, app);
|
||||
if (appChannels > appChannelsBypassingDnd) {
|
||||
pref.setSummary(R.string.zen_mode_bypassing_apps_summary_some);
|
||||
} else {
|
||||
if (packagesBypassingDnd.get(pkg)) {
|
||||
pref.setSummary(R.string.zen_mode_bypassing_apps_summary_all);
|
||||
} else {
|
||||
pref.setSummary(R.string.zen_mode_bypassing_apps_summary_some);
|
||||
}
|
||||
mPreferenceCategory.addPreference(pref);
|
||||
}
|
||||
} else if (appChannelsBypassingDnd == 0) {
|
||||
} else if (!doesAppBypassDnd) {
|
||||
// exists but shouldn't anymore
|
||||
mPreferenceCategory.removePreference(pref);
|
||||
}
|
||||
|
||||
@@ -161,8 +161,7 @@ class ZenModeAppsLinkPreferenceController extends AbstractZenModePreferenceContr
|
||||
Multimap<Integer, String> packagesBypassingDnd = HashMultimap.create();
|
||||
for (UserHandle userHandle : mUserManager.getUserProfiles()) {
|
||||
packagesBypassingDnd.putAll(userHandle.getIdentifier(),
|
||||
mHelperBackend.getPackagesBypassingDnd(userHandle.getIdentifier(),
|
||||
/* includeConversationChannels= */ false));
|
||||
mHelperBackend.getPackagesBypassingDnd(userHandle.getIdentifier()).keySet());
|
||||
}
|
||||
|
||||
return ImmutableList.copyOf(
|
||||
|
||||
@@ -48,15 +48,17 @@ public class ZenModeSelectBypassingAppsFragment extends ZenModeFragmentBase impl
|
||||
} else {
|
||||
app = null;
|
||||
}
|
||||
return buildPreferenceControllers(context, app, this, new NotificationBackend());
|
||||
return buildPreferenceControllers(context, app, this, new NotificationBackend(),
|
||||
new ZenHelperBackend(context));
|
||||
}
|
||||
|
||||
private static List<AbstractPreferenceController> buildPreferenceControllers(Context context,
|
||||
@Nullable Application app, @Nullable Fragment host,
|
||||
@Nullable NotificationBackend notificationBackend) {
|
||||
@Nullable NotificationBackend notificationBackend,
|
||||
@Nullable ZenHelperBackend zenHelperBackend) {
|
||||
final List<AbstractPreferenceController> controllers = new ArrayList<>();
|
||||
controllers.add(new ZenModeAllBypassingAppsPreferenceController(context, app, host,
|
||||
notificationBackend));
|
||||
zenHelperBackend));
|
||||
controllers.add(new ZenModeAddBypassingAppsPreferenceController(context, app, host,
|
||||
notificationBackend));
|
||||
return controllers;
|
||||
@@ -86,7 +88,7 @@ public class ZenModeSelectBypassingAppsFragment extends ZenModeFragmentBase impl
|
||||
@Override
|
||||
public List<AbstractPreferenceController> createPreferenceControllers(
|
||||
Context context) {
|
||||
return buildPreferenceControllers(context, null, null, null);
|
||||
return buildPreferenceControllers(context, null, null, null, null);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
package com.android.settings.notification.modes;
|
||||
|
||||
import static com.android.settings.Utils.createAccessibleSequence;
|
||||
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.content.Context;
|
||||
import android.widget.TextView;
|
||||
@@ -28,6 +30,7 @@ import com.android.settingslib.RestrictedPreference;
|
||||
import com.android.settingslib.Utils;
|
||||
import com.android.settingslib.notification.modes.ZenIconLoader;
|
||||
import com.android.settingslib.notification.modes.ZenMode;
|
||||
import com.android.settingslib.notification.modes.ZenModeDescriptions;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
|
||||
@@ -42,6 +45,7 @@ class ZenModesListItemPreference extends RestrictedPreference {
|
||||
private final Context mContext;
|
||||
private final ZenIconLoader mIconLoader;
|
||||
private final Executor mUiExecutor;
|
||||
private final ZenModeDescriptions mDescriptions;
|
||||
private ZenMode mZenMode;
|
||||
|
||||
private TextView mTitleView;
|
||||
@@ -58,6 +62,7 @@ class ZenModesListItemPreference extends RestrictedPreference {
|
||||
mContext = context;
|
||||
mIconLoader = iconLoader;
|
||||
mUiExecutor = uiExecutor;
|
||||
mDescriptions = new ZenModeDescriptions(context);
|
||||
setZenMode(zenMode);
|
||||
setKey(zenMode.getId());
|
||||
}
|
||||
@@ -89,20 +94,17 @@ class ZenModesListItemPreference extends RestrictedPreference {
|
||||
}
|
||||
|
||||
setTitle(mZenMode.getName());
|
||||
String dynamicDescription = zenMode.getDynamicDescription(mContext);
|
||||
CharSequence statusText = switch (mZenMode.getStatus()) {
|
||||
case ENABLED_AND_ACTIVE ->
|
||||
Strings.isNullOrEmpty(dynamicDescription)
|
||||
? mContext.getString(R.string.zen_mode_active_text)
|
||||
: mContext.getString(
|
||||
R.string.zen_mode_format_status_and_trigger,
|
||||
mContext.getString(R.string.zen_mode_active_text),
|
||||
dynamicDescription);
|
||||
case ENABLED -> dynamicDescription;
|
||||
case DISABLED_BY_USER -> mContext.getString(R.string.zen_mode_disabled_by_user);
|
||||
case DISABLED_BY_OTHER -> mContext.getString(R.string.zen_mode_disabled_needs_setup);
|
||||
};
|
||||
setSummary(statusText);
|
||||
ZenMode.Status status = zenMode.getStatus();
|
||||
String statusText = getStatusText(status, mDescriptions.getTriggerDescription(zenMode));
|
||||
String triggerDescriptionForA11y = mDescriptions.getTriggerDescriptionForAccessibility(
|
||||
zenMode);
|
||||
|
||||
if (triggerDescriptionForA11y != null) {
|
||||
setSummary(createAccessibleSequence(statusText,
|
||||
getStatusText(status, triggerDescriptionForA11y)));
|
||||
} else {
|
||||
setSummary(statusText);
|
||||
}
|
||||
|
||||
setIconSize(ICON_SIZE_SMALL);
|
||||
FutureUtil.whenDone(
|
||||
@@ -116,6 +118,21 @@ class ZenModesListItemPreference extends RestrictedPreference {
|
||||
updateTextColor(zenMode);
|
||||
}
|
||||
|
||||
private String getStatusText(ZenMode.Status status, String triggerDescription) {
|
||||
return switch (status) {
|
||||
case ENABLED_AND_ACTIVE ->
|
||||
Strings.isNullOrEmpty(triggerDescription)
|
||||
? mContext.getString(R.string.zen_mode_active_text)
|
||||
: mContext.getString(
|
||||
R.string.zen_mode_format_status_and_trigger,
|
||||
mContext.getString(R.string.zen_mode_active_text),
|
||||
triggerDescription);
|
||||
case ENABLED -> Strings.nullToEmpty(triggerDescription);
|
||||
case DISABLED_BY_USER -> mContext.getString(R.string.zen_mode_disabled_by_user);
|
||||
case DISABLED_BY_OTHER -> mContext.getString(R.string.zen_mode_disabled_needs_setup);
|
||||
};
|
||||
}
|
||||
|
||||
private void updateTextColor(@Nullable ZenMode zenMode) {
|
||||
boolean isActive = zenMode != null && zenMode.isActive();
|
||||
if (mTitleView != null) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -527,12 +527,12 @@ public class AudioSharingCallAudioPreferenceControllerTest {
|
||||
shadowOf(Looper.getMainLooper()).idle();
|
||||
assertThat(mPreference.getSummary().toString()).isEmpty();
|
||||
|
||||
// onReceiveStateChanged will update summary
|
||||
// onSourceAdded will update summary
|
||||
Settings.Secure.putInt(mContentResolver, TEST_SETTINGS_KEY, TEST_DEVICE_GROUP_ID1);
|
||||
when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of(mDevice1));
|
||||
when(mAssistant.getAllSources(any())).thenReturn(ImmutableList.of(mState));
|
||||
mController.mBroadcastAssistantCallback.onReceiveStateChanged(
|
||||
mDevice1, /* sourceId= */ 1, mState);
|
||||
mController.mBroadcastAssistantCallback.onSourceAdded(mDevice1, /* sourceId= */
|
||||
1, /* reason= */ 1);
|
||||
shadowOf(Looper.getMainLooper()).idle();
|
||||
assertThat(mPreference.getSummary().toString())
|
||||
.isEqualTo(
|
||||
@@ -557,8 +557,6 @@ public class AudioSharingCallAudioPreferenceControllerTest {
|
||||
mController.mBroadcastAssistantCallback.onSearchStartFailed(/* reason= */ 1);
|
||||
mController.mBroadcastAssistantCallback.onSearchStopped(/* reason= */ 1);
|
||||
mController.mBroadcastAssistantCallback.onSearchStopFailed(/* reason= */ 1);
|
||||
mController.mBroadcastAssistantCallback.onSourceAdded(
|
||||
mDevice1, /* sourceId= */ 1, /* reason= */ 1);
|
||||
mController.mBroadcastAssistantCallback.onSourceAddFailed(
|
||||
mDevice1, mSource, /* reason= */ 1);
|
||||
mController.mBroadcastAssistantCallback.onSourceRemoved(
|
||||
@@ -572,6 +570,8 @@ public class AudioSharingCallAudioPreferenceControllerTest {
|
||||
mController.mBroadcastAssistantCallback.onSourceFound(mSource);
|
||||
mController.mBroadcastAssistantCallback.onSourceLost(/* broadcastId= */ 1);
|
||||
shadowOf(Looper.getMainLooper()).idle();
|
||||
mController.mBroadcastAssistantCallback.onReceiveStateChanged(mDevice1, /* sourceId= */ 1,
|
||||
mState);
|
||||
|
||||
// Above callbacks won't update summary.
|
||||
assertThat(mPreference.getSummary().toString()).isEmpty();
|
||||
|
||||
@@ -521,21 +521,9 @@ public class AudioSharingDevicePreferenceControllerTest {
|
||||
|
||||
@Test
|
||||
public void testBluetoothLeBroadcastAssistantCallbacks_updateGroup() {
|
||||
// onReceiveStateChanged with unconnected state will do nothing
|
||||
when(mState.getBisSyncState()).thenReturn(new ArrayList<>());
|
||||
mController.mBroadcastAssistantCallback.onReceiveStateChanged(
|
||||
mDevice, /* sourceId= */ 1, mState);
|
||||
shadowOf(Looper.getMainLooper()).idle();
|
||||
verify(mBluetoothDeviceUpdater, never()).forceUpdate();
|
||||
verify(mDialogHandler, never()).closeOpeningDialogsForLeaDevice(mCachedDevice);
|
||||
|
||||
// onReceiveStateChanged with connected state will update group preference and handle
|
||||
// stale dialogs
|
||||
List<Long> bisSyncState = new ArrayList<>();
|
||||
bisSyncState.add(1L);
|
||||
when(mState.getBisSyncState()).thenReturn(bisSyncState);
|
||||
mController.mBroadcastAssistantCallback.onReceiveStateChanged(
|
||||
mDevice, /* sourceId= */ 1, mState);
|
||||
// onSourceAdded will update group preference and handle stale dialogs
|
||||
mController.mBroadcastAssistantCallback.onSourceAdded(mDevice, /* sourceId= */
|
||||
1, /* reason= */ 1);
|
||||
shadowOf(Looper.getMainLooper()).idle();
|
||||
verify(mBluetoothDeviceUpdater).forceUpdate();
|
||||
verify(mDialogHandler).closeOpeningDialogsForLeaDevice(mCachedDevice);
|
||||
@@ -572,8 +560,13 @@ public class AudioSharingDevicePreferenceControllerTest {
|
||||
mController.mBroadcastAssistantCallback.onSearchStartFailed(/* reason= */ 1);
|
||||
mController.mBroadcastAssistantCallback.onSearchStopped(/* reason= */ 1);
|
||||
mController.mBroadcastAssistantCallback.onSearchStopFailed(/* reason= */ 1);
|
||||
mController.mBroadcastAssistantCallback.onSourceAdded(
|
||||
mDevice, /* sourceId= */ 1, /* reason= */ 1);
|
||||
List<Long> bisSyncState = new ArrayList<>();
|
||||
bisSyncState.add(1L);
|
||||
when(mState.getBisSyncState()).thenReturn(bisSyncState);
|
||||
when(mBroadcast.getLatestBroadcastId()).thenReturn(1);
|
||||
when(mState.getBroadcastId()).thenReturn(1);
|
||||
mController.mBroadcastAssistantCallback.onReceiveStateChanged(mDevice, /* sourceId= */ 1,
|
||||
mState);
|
||||
mController.mBroadcastAssistantCallback.onSourceModified(
|
||||
mDevice, /* sourceId= */ 1, /* reason= */ 1);
|
||||
mController.mBroadcastAssistantCallback.onSourceModifyFailed(
|
||||
|
||||
@@ -461,18 +461,9 @@ public class AudioSharingDeviceVolumeGroupControllerTest {
|
||||
|
||||
@Test
|
||||
public void testBluetoothLeBroadcastAssistantCallbacks_updateGroup() {
|
||||
when(mState.getBisSyncState()).thenReturn(new ArrayList<>());
|
||||
// onReceiveStateChanged with unconnected state will do nothing
|
||||
mController.mBroadcastAssistantCallback.onReceiveStateChanged(
|
||||
mDevice1, /* sourceId= */ 1, mState);
|
||||
verify(mDeviceUpdater, never()).forceUpdate();
|
||||
|
||||
// onReceiveStateChanged with connected state will update group preference
|
||||
List<Long> bisSyncState = new ArrayList<>();
|
||||
bisSyncState.add(1L);
|
||||
when(mState.getBisSyncState()).thenReturn(bisSyncState);
|
||||
mController.mBroadcastAssistantCallback.onReceiveStateChanged(
|
||||
mDevice1, /* sourceId= */ 1, mState);
|
||||
// onSourceAdded will update group preference
|
||||
mController.mBroadcastAssistantCallback.onSourceAdded(mDevice1, /* sourceId= */
|
||||
1, /* reason= */ 1);
|
||||
verify(mDeviceUpdater).forceUpdate();
|
||||
|
||||
// onSourceRemoved will update group preference
|
||||
@@ -487,8 +478,13 @@ public class AudioSharingDeviceVolumeGroupControllerTest {
|
||||
mController.mBroadcastAssistantCallback.onSearchStartFailed(/* reason= */ 1);
|
||||
mController.mBroadcastAssistantCallback.onSearchStopped(/* reason= */ 1);
|
||||
mController.mBroadcastAssistantCallback.onSearchStopFailed(/* reason= */ 1);
|
||||
mController.mBroadcastAssistantCallback.onSourceAdded(
|
||||
mDevice1, /* sourceId= */ 1, /* reason= */ 1);
|
||||
List<Long> bisSyncState = new ArrayList<>();
|
||||
bisSyncState.add(1L);
|
||||
when(mState.getBisSyncState()).thenReturn(bisSyncState);
|
||||
when(mBroadcast.getLatestBroadcastId()).thenReturn(1);
|
||||
when(mState.getBroadcastId()).thenReturn(1);
|
||||
mController.mBroadcastAssistantCallback.onReceiveStateChanged(mDevice1, /* sourceId= */ 1,
|
||||
mState);
|
||||
mController.mBroadcastAssistantCallback.onSourceAddFailed(
|
||||
mDevice1, mSource, /* reason= */ 1);
|
||||
mController.mBroadcastAssistantCallback.onSourceRemoveFailed(
|
||||
|
||||
@@ -476,7 +476,7 @@ public class AudioSharingSwitchBarControllerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onPlaybackStarted_notInit_noDialog() {
|
||||
public void onBroadcastMetadataChanged_notInit_noDialog() {
|
||||
FeatureFlagUtils.setEnabled(
|
||||
mContext, FeatureFlagUtils.SETTINGS_NEED_CONNECTED_BLE_DEVICE_FOR_BROADCAST, true);
|
||||
when(mBtnView.isEnabled()).thenReturn(true);
|
||||
@@ -503,7 +503,7 @@ public class AudioSharingSwitchBarControllerTest {
|
||||
// No progress dialog.
|
||||
assertThat(childFragments).isEmpty();
|
||||
|
||||
mController.mBroadcastCallback.onPlaybackStarted(0, 0);
|
||||
mController.mBroadcastCallback.onBroadcastMetadataChanged(/* reason= */ 1, mMetadata);
|
||||
shadowOf(Looper.getMainLooper()).idle();
|
||||
|
||||
verify(mFeatureFactory.metricsFeatureProvider)
|
||||
@@ -515,7 +515,7 @@ public class AudioSharingSwitchBarControllerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onPlaybackStarted_hasLocalSource_noDialog() {
|
||||
public void onBroadcastMetadataChanged_hasLocalSource_noDialog() {
|
||||
FeatureFlagUtils.setEnabled(
|
||||
mContext, FeatureFlagUtils.SETTINGS_NEED_CONNECTED_BLE_DEVICE_FOR_BROADCAST, true);
|
||||
when(mBtnView.isEnabled()).thenReturn(true);
|
||||
@@ -533,7 +533,7 @@ public class AudioSharingSwitchBarControllerTest {
|
||||
assertThat(childFragments).comparingElementsUsing(CLAZZNAME_EQUALS).containsExactly(
|
||||
AudioSharingProgressDialogFragment.class.getName());
|
||||
|
||||
mController.mBroadcastCallback.onPlaybackStarted(0, 0);
|
||||
mController.mBroadcastCallback.onBroadcastMetadataChanged(/* reason= */ 1, mMetadata);
|
||||
shadowOf(Looper.getMainLooper()).idle();
|
||||
|
||||
verify(mAssistant, never()).addSource(any(), any(), anyBoolean());
|
||||
@@ -549,7 +549,7 @@ public class AudioSharingSwitchBarControllerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onPlaybackStarted_singleActiveDevice_showJoinAudioSharingDialog() {
|
||||
public void onBroadcastMetadataChanged_singleActiveDevice_showJoinAudioSharingDialog() {
|
||||
FeatureFlagUtils.setEnabled(
|
||||
mContext, FeatureFlagUtils.SETTINGS_NEED_CONNECTED_BLE_DEVICE_FOR_BROADCAST, true);
|
||||
when(mBtnView.isEnabled()).thenReturn(true);
|
||||
@@ -566,15 +566,15 @@ public class AudioSharingSwitchBarControllerTest {
|
||||
|
||||
when(mBroadcast.isEnabled(null)).thenReturn(true);
|
||||
when(mBroadcast.getLatestBluetoothLeBroadcastMetadata()).thenReturn(mMetadata);
|
||||
mController.mBroadcastCallback.onPlaybackStarted(0, 0);
|
||||
mController.mBroadcastCallback.onBroadcastMetadataChanged(/* reason= */ 1, mMetadata);
|
||||
shadowOf(Looper.getMainLooper()).idle();
|
||||
|
||||
verify(mFeatureFactory.metricsFeatureProvider)
|
||||
.action(any(Context.class), eq(SettingsEnums.ACTION_AUTO_JOIN_AUDIO_SHARING));
|
||||
|
||||
when(mState.getBisSyncState()).thenReturn(ImmutableList.of(1L));
|
||||
mController.mBroadcastAssistantCallback.onReceiveStateChanged(mDevice2, /* sourceId= */ 1,
|
||||
mState);
|
||||
mController.mBroadcastAssistantCallback.onSourceAdded(mDevice2, /* sourceId= */
|
||||
1, /* reason= */ 1);
|
||||
shadowOf(Looper.getMainLooper()).idle();
|
||||
|
||||
childFragments = mParentFragment.getChildFragmentManager().getFragments();
|
||||
@@ -613,7 +613,7 @@ public class AudioSharingSwitchBarControllerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onPlaybackStarted_oneActiveOnConnected_showJoinAudioSharingDialog() {
|
||||
public void onBroadcastMetadataChanged_oneActiveOnConnected_showJoinAudioSharingDialog() {
|
||||
FeatureFlagUtils.setEnabled(
|
||||
mContext, FeatureFlagUtils.SETTINGS_NEED_CONNECTED_BLE_DEVICE_FOR_BROADCAST, true);
|
||||
when(mBtnView.isEnabled()).thenReturn(true);
|
||||
@@ -635,7 +635,7 @@ public class AudioSharingSwitchBarControllerTest {
|
||||
|
||||
when(mBroadcast.isEnabled(null)).thenReturn(true);
|
||||
when(mBroadcast.getLatestBluetoothLeBroadcastMetadata()).thenReturn(mMetadata);
|
||||
mController.mBroadcastCallback.onPlaybackStarted(0, 0);
|
||||
mController.mBroadcastCallback.onBroadcastMetadataChanged(/* reason= */ 1, mMetadata);
|
||||
shadowOf(Looper.getMainLooper()).idle();
|
||||
|
||||
verify(mFeatureFactory.metricsFeatureProvider)
|
||||
@@ -681,7 +681,7 @@ public class AudioSharingSwitchBarControllerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onPlaybackStarted_oneActiveOnConnected_clickShareBtnOnDialog_addSource() {
|
||||
public void onBroadcastMetadataChanged_oneActiveOnConnected_clickShareBtnOnDialog_addSource() {
|
||||
FeatureFlagUtils.setEnabled(
|
||||
mContext, FeatureFlagUtils.SETTINGS_NEED_CONNECTED_BLE_DEVICE_FOR_BROADCAST, true);
|
||||
when(mBtnView.isEnabled()).thenReturn(true);
|
||||
@@ -694,7 +694,7 @@ public class AudioSharingSwitchBarControllerTest {
|
||||
verify(mBroadcast).startPrivateBroadcast();
|
||||
when(mBroadcast.isEnabled(null)).thenReturn(true);
|
||||
when(mBroadcast.getLatestBluetoothLeBroadcastMetadata()).thenReturn(mMetadata);
|
||||
mController.mBroadcastCallback.onPlaybackStarted(0, 0);
|
||||
mController.mBroadcastCallback.onBroadcastMetadataChanged(/* reason= */ 1, mMetadata);
|
||||
shadowOf(Looper.getMainLooper()).idle();
|
||||
|
||||
verify(mAssistant).addSource(mDevice2, mMetadata, /* isGroupOp= */ false);
|
||||
@@ -722,7 +722,7 @@ public class AudioSharingSwitchBarControllerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onPlaybackStarted_oneActiveOnConnected_clickCancelBtnOnDialog_doNothing() {
|
||||
public void onBroadcastMetadataChanged_oneActiveOnConnected_clickCancelBtnOnDialog_doNothing() {
|
||||
FeatureFlagUtils.setEnabled(
|
||||
mContext, FeatureFlagUtils.SETTINGS_NEED_CONNECTED_BLE_DEVICE_FOR_BROADCAST, true);
|
||||
when(mBtnView.isEnabled()).thenReturn(true);
|
||||
@@ -735,7 +735,7 @@ public class AudioSharingSwitchBarControllerTest {
|
||||
verify(mBroadcast).startPrivateBroadcast();
|
||||
when(mBroadcast.isEnabled(null)).thenReturn(true);
|
||||
when(mBroadcast.getLatestBluetoothLeBroadcastMetadata()).thenReturn(mMetadata);
|
||||
mController.mBroadcastCallback.onPlaybackStarted(0, 0);
|
||||
mController.mBroadcastCallback.onBroadcastMetadataChanged(/* reason= */ 1, mMetadata);
|
||||
shadowOf(Looper.getMainLooper()).idle();
|
||||
|
||||
verify(mAssistant).addSource(mDevice2, mMetadata, /* isGroupOp= */ false);
|
||||
@@ -835,7 +835,7 @@ public class AudioSharingSwitchBarControllerTest {
|
||||
|
||||
when(mBroadcast.isEnabled(null)).thenReturn(true);
|
||||
when(mBroadcast.getLatestBluetoothLeBroadcastMetadata()).thenReturn(mMetadata);
|
||||
mController.mBroadcastCallback.onPlaybackStarted(0, 0);
|
||||
mController.mBroadcastCallback.onBroadcastMetadataChanged(/* reason= */ 1, mMetadata);
|
||||
shadowOf(Looper.getMainLooper()).idle();
|
||||
|
||||
verify(mAssistant).addSource(mDevice2, mMetadata, /* isGroupOp= */ false);
|
||||
@@ -868,16 +868,15 @@ public class AudioSharingSwitchBarControllerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAssistantCallbacks_onReceiveStateChanged_dismissProgressDialog() {
|
||||
public void testAssistantCallbacks_onSourceAdded_dismissProgressDialog() {
|
||||
AudioSharingProgressDialogFragment.show(mParentFragment, TEST_DEVICE_NAME1);
|
||||
shadowOf(Looper.getMainLooper()).idle();
|
||||
List<Fragment> childFragments = mParentFragment.getChildFragmentManager().getFragments();
|
||||
assertThat(childFragments).comparingElementsUsing(CLAZZNAME_EQUALS).containsExactly(
|
||||
AudioSharingProgressDialogFragment.class.getName());
|
||||
|
||||
when(mState.getBisSyncState()).thenReturn(ImmutableList.of(1L));
|
||||
mController.mBroadcastAssistantCallback.onReceiveStateChanged(mDevice1, /* sourceId= */ 1,
|
||||
mState);
|
||||
mController.mBroadcastAssistantCallback.onSourceAdded(mDevice1, /* sourceId= */
|
||||
1, /* reason= */ 1);
|
||||
shadowOf(Looper.getMainLooper()).idle();
|
||||
childFragments = mParentFragment.getChildFragmentManager().getFragments();
|
||||
assertThat(childFragments).isEmpty();
|
||||
@@ -892,8 +891,6 @@ public class AudioSharingSwitchBarControllerTest {
|
||||
mController.mBroadcastAssistantCallback.onSearchStartFailed(/* reason= */ 1);
|
||||
mController.mBroadcastAssistantCallback.onSearchStopped(/* reason= */ 1);
|
||||
mController.mBroadcastAssistantCallback.onSearchStopFailed(/* reason= */ 1);
|
||||
mController.mBroadcastAssistantCallback.onSourceAdded(
|
||||
mDevice1, /* sourceId= */ 1, /* reason= */ 1);
|
||||
mController.mBroadcastAssistantCallback.onSourceRemoved(
|
||||
mDevice1, /* sourceId= */ 1, /* reason= */ 1);
|
||||
mController.mBroadcastAssistantCallback.onSourceRemoveFailed(
|
||||
@@ -1013,7 +1010,7 @@ public class AudioSharingSwitchBarControllerTest {
|
||||
shadowOf(Looper.getMainLooper()).idle();
|
||||
|
||||
verify(mBroadcast).startPrivateBroadcast();
|
||||
mController.mBroadcastCallback.onPlaybackStarted(0, 0);
|
||||
mController.mBroadcastCallback.onBroadcastMetadataChanged(/* reason= */ 1, mMetadata);
|
||||
shadowOf(Looper.getMainLooper()).idle();
|
||||
|
||||
verify(mFeatureFactory.metricsFeatureProvider)
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.android.settings.connecteddevice.audiosharing.audiostreams;
|
||||
|
||||
import static com.android.settingslib.flags.Flags.FLAG_AUDIO_SHARING_HYSTERESIS_MODE_FIX;
|
||||
import static com.android.settingslib.flags.Flags.FLAG_ENABLE_LE_AUDIO_SHARING;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
@@ -31,10 +32,12 @@ import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.BluetoothLeBroadcastAssistant;
|
||||
import android.bluetooth.BluetoothLeBroadcastMetadata;
|
||||
import android.bluetooth.BluetoothLeBroadcastReceiveState;
|
||||
import android.bluetooth.BluetoothStatusCodes;
|
||||
import android.content.Context;
|
||||
import android.platform.test.flag.junit.SetFlagsRule;
|
||||
import android.view.View;
|
||||
@@ -46,6 +49,7 @@ import androidx.test.core.app.ApplicationProvider;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.connecteddevice.audiosharing.audiostreams.testshadows.ShadowAudioStreamsHelper;
|
||||
import com.android.settings.testutils.FakeFeatureFactory;
|
||||
import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
|
||||
import com.android.settings.testutils.shadow.ShadowThreadUtils;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant;
|
||||
import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||
@@ -62,6 +66,7 @@ import org.mockito.junit.MockitoJUnit;
|
||||
import org.mockito.junit.MockitoRule;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.shadow.api.Shadow;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
@@ -73,6 +78,7 @@ import java.util.concurrent.Executor;
|
||||
shadows = {
|
||||
ShadowThreadUtils.class,
|
||||
ShadowAudioStreamsHelper.class,
|
||||
ShadowBluetoothAdapter.class,
|
||||
})
|
||||
public class AudioStreamButtonControllerTest {
|
||||
@Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
|
||||
@@ -95,6 +101,13 @@ public class AudioStreamButtonControllerTest {
|
||||
@Before
|
||||
public void setUp() {
|
||||
mSetFlagsRule.disableFlags(FLAG_AUDIO_SHARING_HYSTERESIS_MODE_FIX);
|
||||
ShadowBluetoothAdapter shadowBluetoothAdapter = Shadow.extract(
|
||||
BluetoothAdapter.getDefaultAdapter());
|
||||
shadowBluetoothAdapter.setEnabled(true);
|
||||
shadowBluetoothAdapter.setIsLeAudioBroadcastSourceSupported(
|
||||
BluetoothStatusCodes.FEATURE_SUPPORTED);
|
||||
shadowBluetoothAdapter.setIsLeAudioBroadcastAssistantSupported(
|
||||
BluetoothStatusCodes.FEATURE_SUPPORTED);
|
||||
ShadowAudioStreamsHelper.setUseMock(mAudioStreamsHelper);
|
||||
when(mAudioStreamsHelper.getLeBroadcastAssistant()).thenReturn(mAssistant);
|
||||
mFeatureFactory = FakeFeatureFactory.setupForTest();
|
||||
@@ -261,6 +274,7 @@ public class AudioStreamButtonControllerTest {
|
||||
|
||||
@Test
|
||||
public void testCallback_onReceiveStateChangedWithSourcePresent_updateButton() {
|
||||
mSetFlagsRule.enableFlags(FLAG_ENABLE_LE_AUDIO_SHARING);
|
||||
mSetFlagsRule.enableFlags(FLAG_AUDIO_SHARING_HYSTERESIS_MODE_FIX);
|
||||
String address = "11:22:33:44:55:66";
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ import static com.android.settings.connecteddevice.audiosharing.audiostreams.Aud
|
||||
import static com.android.settings.connecteddevice.audiosharing.audiostreams.AudioStreamHeaderController.AUDIO_STREAM_HEADER_NOT_LISTENING_SUMMARY;
|
||||
import static com.android.settings.connecteddevice.audiosharing.audiostreams.AudioStreamHeaderController.AUDIO_STREAM_HEADER_PRESENT_NOW_SUMMARY;
|
||||
import static com.android.settingslib.flags.Flags.FLAG_AUDIO_SHARING_HYSTERESIS_MODE_FIX;
|
||||
import static com.android.settingslib.flags.Flags.FLAG_ENABLE_LE_AUDIO_SHARING;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
@@ -28,9 +29,11 @@ import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.BluetoothLeBroadcastAssistant;
|
||||
import android.bluetooth.BluetoothLeBroadcastReceiveState;
|
||||
import android.bluetooth.BluetoothStatusCodes;
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.platform.test.flag.junit.SetFlagsRule;
|
||||
@@ -41,6 +44,7 @@ import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.settings.connecteddevice.audiosharing.audiostreams.testshadows.ShadowAudioStreamsHelper;
|
||||
import com.android.settings.connecteddevice.audiosharing.audiostreams.testshadows.ShadowEntityHeaderController;
|
||||
import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
|
||||
import com.android.settings.testutils.shadow.ShadowThreadUtils;
|
||||
import com.android.settings.widget.EntityHeaderController;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant;
|
||||
@@ -57,6 +61,7 @@ import org.mockito.junit.MockitoJUnit;
|
||||
import org.mockito.junit.MockitoRule;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.shadow.api.Shadow;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
@@ -69,6 +74,7 @@ import java.util.concurrent.Executor;
|
||||
ShadowEntityHeaderController.class,
|
||||
ShadowThreadUtils.class,
|
||||
ShadowAudioStreamsHelper.class,
|
||||
ShadowBluetoothAdapter.class,
|
||||
})
|
||||
public class AudioStreamHeaderControllerTest {
|
||||
@Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
|
||||
@@ -93,6 +99,13 @@ public class AudioStreamHeaderControllerTest {
|
||||
@Before
|
||||
public void setUp() {
|
||||
mSetFlagsRule.disableFlags(FLAG_AUDIO_SHARING_HYSTERESIS_MODE_FIX);
|
||||
ShadowBluetoothAdapter shadowBluetoothAdapter = Shadow.extract(
|
||||
BluetoothAdapter.getDefaultAdapter());
|
||||
shadowBluetoothAdapter.setEnabled(true);
|
||||
shadowBluetoothAdapter.setIsLeAudioBroadcastSourceSupported(
|
||||
BluetoothStatusCodes.FEATURE_SUPPORTED);
|
||||
shadowBluetoothAdapter.setIsLeAudioBroadcastAssistantSupported(
|
||||
BluetoothStatusCodes.FEATURE_SUPPORTED);
|
||||
|
||||
ShadowEntityHeaderController.setUseMock(mHeaderController);
|
||||
ShadowAudioStreamsHelper.setUseMock(mAudioStreamsHelper);
|
||||
@@ -260,6 +273,7 @@ public class AudioStreamHeaderControllerTest {
|
||||
|
||||
@Test
|
||||
public void testCallback_onReceiveStateChangedWithSourcePresent_updateButton() {
|
||||
mSetFlagsRule.enableFlags(FLAG_ENABLE_LE_AUDIO_SHARING);
|
||||
mSetFlagsRule.enableFlags(FLAG_AUDIO_SHARING_HYSTERESIS_MODE_FIX);
|
||||
String address = "11:22:33:44:55:66";
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.android.settings.connecteddevice.audiosharing.audiostreams;
|
||||
|
||||
import static com.android.settingslib.flags.Flags.FLAG_AUDIO_SHARING_HYSTERESIS_MODE_FIX;
|
||||
import static com.android.settingslib.flags.Flags.FLAG_ENABLE_LE_AUDIO_SHARING;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
@@ -31,6 +32,8 @@ import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothStatusCodes;
|
||||
import android.content.Context;
|
||||
import android.platform.test.flag.junit.SetFlagsRule;
|
||||
import android.text.SpannableString;
|
||||
@@ -38,6 +41,8 @@ import android.text.SpannableString;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
@@ -47,8 +52,14 @@ import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnit;
|
||||
import org.mockito.junit.MockitoRule;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.shadow.api.Shadow;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Config(
|
||||
shadows = {
|
||||
ShadowBluetoothAdapter.class,
|
||||
})
|
||||
public class AudioStreamStateHandlerTest {
|
||||
@Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
|
||||
@Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
|
||||
@@ -64,6 +75,13 @@ public class AudioStreamStateHandlerTest {
|
||||
@Before
|
||||
public void setUp() {
|
||||
mSetFlagsRule.disableFlags(FLAG_AUDIO_SHARING_HYSTERESIS_MODE_FIX);
|
||||
ShadowBluetoothAdapter shadowBluetoothAdapter = Shadow.extract(
|
||||
BluetoothAdapter.getDefaultAdapter());
|
||||
shadowBluetoothAdapter.setEnabled(true);
|
||||
shadowBluetoothAdapter.setIsLeAudioBroadcastSourceSupported(
|
||||
BluetoothStatusCodes.FEATURE_SUPPORTED);
|
||||
shadowBluetoothAdapter.setIsLeAudioBroadcastAssistantSupported(
|
||||
BluetoothStatusCodes.FEATURE_SUPPORTED);
|
||||
mHandler = spy(new AudioStreamStateHandler());
|
||||
}
|
||||
|
||||
@@ -109,6 +127,7 @@ public class AudioStreamStateHandlerTest {
|
||||
|
||||
@Test
|
||||
public void testHandleStateChange_setNewState_sourcePresent() {
|
||||
mSetFlagsRule.enableFlags(FLAG_ENABLE_LE_AUDIO_SHARING);
|
||||
mSetFlagsRule.enableFlags(FLAG_AUDIO_SHARING_HYSTERESIS_MODE_FIX);
|
||||
|
||||
when(mHandler.getStateEnum())
|
||||
|
||||
@@ -135,47 +135,47 @@ public class AudioStreamsCategoryControllerTest {
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_flagOn() {
|
||||
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_QR_CODE_PRIVATE_BROADCAST_SHARING);
|
||||
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
|
||||
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_flagOff() {
|
||||
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_QR_CODE_PRIVATE_BROADCAST_SHARING);
|
||||
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
|
||||
assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onStart_flagOff_doNothing() {
|
||||
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_QR_CODE_PRIVATE_BROADCAST_SHARING);
|
||||
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
|
||||
mController.onStart(mLifecycleOwner);
|
||||
verify(mBluetoothEventManager, never()).registerCallback(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onStart_flagOn_registerCallback() {
|
||||
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_QR_CODE_PRIVATE_BROADCAST_SHARING);
|
||||
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
|
||||
mController.onStart(mLifecycleOwner);
|
||||
verify(mBluetoothEventManager).registerCallback(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onStop_flagOff_doNothing() {
|
||||
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_QR_CODE_PRIVATE_BROADCAST_SHARING);
|
||||
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
|
||||
mController.onStop(mLifecycleOwner);
|
||||
verify(mBluetoothEventManager, never()).unregisterCallback(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onStop_flagOn_unregisterCallback() {
|
||||
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_QR_CODE_PRIVATE_BROADCAST_SHARING);
|
||||
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
|
||||
mController.onStop(mLifecycleOwner);
|
||||
verify(mBluetoothEventManager).unregisterCallback(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateVisibility_flagOff_invisible() {
|
||||
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_QR_CODE_PRIVATE_BROADCAST_SHARING);
|
||||
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
|
||||
mController.updateVisibility();
|
||||
shadowOf(Looper.getMainLooper()).idle();
|
||||
assertThat(mPreference.isVisible()).isFalse();
|
||||
@@ -183,7 +183,7 @@ public class AudioStreamsCategoryControllerTest {
|
||||
|
||||
@Test
|
||||
public void updateVisibility_noConnectedLe_invisible() {
|
||||
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_QR_CODE_PRIVATE_BROADCAST_SHARING);
|
||||
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
|
||||
mController.updateVisibility();
|
||||
shadowOf(Looper.getMainLooper()).idle();
|
||||
assertThat(mPreference.isVisible()).isFalse();
|
||||
@@ -191,7 +191,7 @@ public class AudioStreamsCategoryControllerTest {
|
||||
|
||||
@Test
|
||||
public void updateVisibility_isNotProfileReady_invisible() {
|
||||
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_QR_CODE_PRIVATE_BROADCAST_SHARING);
|
||||
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
|
||||
ShadowAudioStreamsHelper.setCachedBluetoothDeviceInSharingOrLeConnected(
|
||||
mCachedBluetoothDevice);
|
||||
when(mVolumeControl.isProfileReady()).thenReturn(false);
|
||||
@@ -202,7 +202,7 @@ public class AudioStreamsCategoryControllerTest {
|
||||
|
||||
@Test
|
||||
public void updateVisibility_isBroadcasting_invisible() {
|
||||
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_QR_CODE_PRIVATE_BROADCAST_SHARING);
|
||||
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
|
||||
ShadowAudioStreamsHelper.setCachedBluetoothDeviceInSharingOrLeConnected(
|
||||
mCachedBluetoothDevice);
|
||||
when(mBroadcast.isEnabled(any())).thenReturn(true);
|
||||
@@ -213,7 +213,7 @@ public class AudioStreamsCategoryControllerTest {
|
||||
|
||||
@Test
|
||||
public void updateVisibility_isBluetoothOff_invisible() {
|
||||
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_QR_CODE_PRIVATE_BROADCAST_SHARING);
|
||||
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
|
||||
ShadowAudioStreamsHelper.setCachedBluetoothDeviceInSharingOrLeConnected(
|
||||
mCachedBluetoothDevice);
|
||||
mShadowBluetoothAdapter.setEnabled(false);
|
||||
@@ -224,7 +224,7 @@ public class AudioStreamsCategoryControllerTest {
|
||||
|
||||
@Test
|
||||
public void updateVisibility_visible() {
|
||||
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_QR_CODE_PRIVATE_BROADCAST_SHARING);
|
||||
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
|
||||
ShadowAudioStreamsHelper.setCachedBluetoothDeviceInSharingOrLeConnected(
|
||||
mCachedBluetoothDevice);
|
||||
mController.displayPreference(mScreen);
|
||||
@@ -235,7 +235,7 @@ public class AudioStreamsCategoryControllerTest {
|
||||
|
||||
@Test
|
||||
public void onProfileConnectionStateChanged_updateVisibility() {
|
||||
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_QR_CODE_PRIVATE_BROADCAST_SHARING);
|
||||
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
|
||||
ArgumentCaptor<BluetoothCallback> argumentCaptor =
|
||||
ArgumentCaptor.forClass(BluetoothCallback.class);
|
||||
mController.onStart(mLifecycleOwner);
|
||||
|
||||
@@ -20,6 +20,7 @@ import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
|
||||
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
|
||||
|
||||
import static com.android.settingslib.flags.Flags.FLAG_AUDIO_SHARING_HYSTERESIS_MODE_FIX;
|
||||
import static com.android.settingslib.flags.Flags.FLAG_ENABLE_LE_AUDIO_SHARING;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
@@ -33,9 +34,11 @@ import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.BluetoothLeBroadcastMetadata;
|
||||
import android.bluetooth.BluetoothLeBroadcastReceiveState;
|
||||
import android.bluetooth.BluetoothStatusCodes;
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
@@ -45,6 +48,7 @@ import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
|
||||
import com.android.settings.testutils.shadow.ShadowThreadUtils;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
|
||||
@@ -65,6 +69,7 @@ import org.mockito.junit.MockitoJUnit;
|
||||
import org.mockito.junit.MockitoRule;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.shadow.api.Shadow;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
@@ -74,6 +79,7 @@ import java.util.List;
|
||||
@Config(
|
||||
shadows = {
|
||||
ShadowThreadUtils.class,
|
||||
ShadowBluetoothAdapter.class,
|
||||
})
|
||||
public class AudioStreamsHelperTest {
|
||||
@Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
|
||||
@@ -97,6 +103,13 @@ public class AudioStreamsHelperTest {
|
||||
@Before
|
||||
public void setUp() {
|
||||
mSetFlagsRule.disableFlags(FLAG_AUDIO_SHARING_HYSTERESIS_MODE_FIX);
|
||||
ShadowBluetoothAdapter shadowBluetoothAdapter = Shadow.extract(
|
||||
BluetoothAdapter.getDefaultAdapter());
|
||||
shadowBluetoothAdapter.setEnabled(true);
|
||||
shadowBluetoothAdapter.setIsLeAudioBroadcastSourceSupported(
|
||||
BluetoothStatusCodes.FEATURE_SUPPORTED);
|
||||
shadowBluetoothAdapter.setIsLeAudioBroadcastAssistantSupported(
|
||||
BluetoothStatusCodes.FEATURE_SUPPORTED);
|
||||
when(mLocalBluetoothManager.getProfileManager()).thenReturn(mLocalBluetoothProfileManager);
|
||||
when(mLocalBluetoothManager.getCachedDeviceManager()).thenReturn(mDeviceManager);
|
||||
when(mLocalBluetoothProfileManager.getLeAudioBroadcastAssistantProfile())
|
||||
@@ -229,6 +242,7 @@ public class AudioStreamsHelperTest {
|
||||
|
||||
@Test
|
||||
public void getAllPresentSources_noSource() {
|
||||
mSetFlagsRule.enableFlags(FLAG_ENABLE_LE_AUDIO_SHARING);
|
||||
mSetFlagsRule.enableFlags(FLAG_AUDIO_SHARING_HYSTERESIS_MODE_FIX);
|
||||
|
||||
List<BluetoothDevice> devices = new ArrayList<>();
|
||||
@@ -251,6 +265,7 @@ public class AudioStreamsHelperTest {
|
||||
|
||||
@Test
|
||||
public void getAllPresentSources_returnSource() {
|
||||
mSetFlagsRule.enableFlags(FLAG_ENABLE_LE_AUDIO_SHARING);
|
||||
mSetFlagsRule.enableFlags(FLAG_AUDIO_SHARING_HYSTERESIS_MODE_FIX);
|
||||
String address = "11:22:33:44:55:66";
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.android.settings.connecteddevice.audiosharing.audiostreams;
|
||||
|
||||
import static com.android.settingslib.flags.Flags.FLAG_AUDIO_SHARING_HYSTERESIS_MODE_FIX;
|
||||
import static com.android.settingslib.flags.Flags.FLAG_ENABLE_LE_AUDIO_SHARING;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
@@ -24,11 +25,18 @@ import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.BluetoothLeBroadcastMetadata;
|
||||
import android.bluetooth.BluetoothLeBroadcastReceiveState;
|
||||
import android.bluetooth.BluetoothStatusCodes;
|
||||
import android.content.Context;
|
||||
import android.platform.test.flag.junit.SetFlagsRule;
|
||||
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
@@ -37,15 +45,21 @@ import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnit;
|
||||
import org.mockito.junit.MockitoRule;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.shadow.api.Shadow;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Config(
|
||||
shadows = {
|
||||
ShadowBluetoothAdapter.class,
|
||||
})
|
||||
public class AudioStreamsProgressCategoryCallbackTest {
|
||||
@Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
|
||||
@Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
|
||||
|
||||
private final Context mContext = ApplicationProvider.getApplicationContext();
|
||||
@Mock private AudioStreamsProgressCategoryController mController;
|
||||
@Mock private BluetoothDevice mDevice;
|
||||
@Mock private BluetoothLeBroadcastReceiveState mState;
|
||||
@@ -56,7 +70,14 @@ public class AudioStreamsProgressCategoryCallbackTest {
|
||||
@Before
|
||||
public void setUp() {
|
||||
mSetFlagsRule.disableFlags(FLAG_AUDIO_SHARING_HYSTERESIS_MODE_FIX);
|
||||
mCallback = new AudioStreamsProgressCategoryCallback(mController);
|
||||
ShadowBluetoothAdapter shadowBluetoothAdapter = Shadow.extract(
|
||||
BluetoothAdapter.getDefaultAdapter());
|
||||
shadowBluetoothAdapter.setEnabled(true);
|
||||
shadowBluetoothAdapter.setIsLeAudioBroadcastSourceSupported(
|
||||
BluetoothStatusCodes.FEATURE_SUPPORTED);
|
||||
shadowBluetoothAdapter.setIsLeAudioBroadcastAssistantSupported(
|
||||
BluetoothStatusCodes.FEATURE_SUPPORTED);
|
||||
mCallback = new AudioStreamsProgressCategoryCallback(mContext, mController);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -71,6 +92,7 @@ public class AudioStreamsProgressCategoryCallbackTest {
|
||||
|
||||
@Test
|
||||
public void testOnReceiveStateChanged_sourcePresent() {
|
||||
mSetFlagsRule.enableFlags(FLAG_ENABLE_LE_AUDIO_SHARING);
|
||||
mSetFlagsRule.enableFlags(FLAG_AUDIO_SHARING_HYSTERESIS_MODE_FIX);
|
||||
String address = "11:22:33:44:55:66";
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ import static com.android.settings.connecteddevice.audiosharing.audiostreams.Aud
|
||||
import static com.android.settings.connecteddevice.audiosharing.audiostreams.AudioStreamsProgressCategoryController.UNSET_BROADCAST_ID;
|
||||
import static com.android.settings.core.BasePreferenceController.AVAILABLE;
|
||||
import static com.android.settingslib.flags.Flags.FLAG_AUDIO_SHARING_HYSTERESIS_MODE_FIX;
|
||||
import static com.android.settingslib.flags.Flags.FLAG_ENABLE_LE_AUDIO_SHARING;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
@@ -48,6 +49,7 @@ import android.bluetooth.BluetoothLeAudioContentMetadata;
|
||||
import android.bluetooth.BluetoothLeBroadcastMetadata;
|
||||
import android.bluetooth.BluetoothLeBroadcastReceiveState;
|
||||
import android.bluetooth.BluetoothProfile;
|
||||
import android.bluetooth.BluetoothStatusCodes;
|
||||
import android.content.Context;
|
||||
import android.os.Looper;
|
||||
import android.platform.test.flag.junit.SetFlagsRule;
|
||||
@@ -62,6 +64,7 @@ import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.connecteddevice.audiosharing.audiostreams.testshadows.ShadowAudioStreamsHelper;
|
||||
import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
|
||||
import com.android.settings.testutils.shadow.ShadowBluetoothUtils;
|
||||
import com.android.settings.testutils.shadow.ShadowThreadUtils;
|
||||
import com.android.settingslib.bluetooth.BluetoothEventManager;
|
||||
@@ -84,6 +87,7 @@ import org.mockito.junit.MockitoJUnit;
|
||||
import org.mockito.junit.MockitoRule;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.shadow.api.Shadow;
|
||||
import org.robolectric.shadows.ShadowAlertDialog;
|
||||
import org.robolectric.shadows.androidx.fragment.FragmentController;
|
||||
|
||||
@@ -97,6 +101,7 @@ import java.util.List;
|
||||
ShadowAudioStreamsHelper.class,
|
||||
ShadowThreadUtils.class,
|
||||
ShadowAlertDialog.class,
|
||||
ShadowBluetoothAdapter.class,
|
||||
})
|
||||
public class AudioStreamsProgressCategoryControllerTest {
|
||||
@Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
|
||||
@@ -129,6 +134,13 @@ public class AudioStreamsProgressCategoryControllerTest {
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
ShadowBluetoothAdapter shadowBluetoothAdapter = Shadow.extract(
|
||||
BluetoothAdapter.getDefaultAdapter());
|
||||
shadowBluetoothAdapter.setEnabled(true);
|
||||
shadowBluetoothAdapter.setIsLeAudioBroadcastSourceSupported(
|
||||
BluetoothStatusCodes.FEATURE_SUPPORTED);
|
||||
shadowBluetoothAdapter.setIsLeAudioBroadcastAssistantSupported(
|
||||
BluetoothStatusCodes.FEATURE_SUPPORTED);
|
||||
ShadowAudioStreamsHelper.setUseMock(mAudioStreamsHelper);
|
||||
when(mAudioStreamsHelper.getLeBroadcastAssistant()).thenReturn(mLeBroadcastAssistant);
|
||||
when(mAudioStreamsHelper.getAllConnectedSources()).thenReturn(emptyList());
|
||||
@@ -292,6 +304,7 @@ public class AudioStreamsProgressCategoryControllerTest {
|
||||
|
||||
@Test
|
||||
public void testOnStart_initHasDevice_getPresentSources() {
|
||||
mSetFlagsRule.enableFlags(FLAG_ENABLE_LE_AUDIO_SHARING);
|
||||
mSetFlagsRule.enableFlags(FLAG_AUDIO_SHARING_HYSTERESIS_MODE_FIX);
|
||||
|
||||
// Setup a device
|
||||
|
||||
@@ -17,68 +17,90 @@
|
||||
package com.android.settings.network
|
||||
|
||||
import android.content.Context
|
||||
import android.content.ContextWrapper
|
||||
import android.net.wifi.WifiManager
|
||||
import android.platform.test.flag.junit.SetFlagsRule
|
||||
import android.provider.Settings
|
||||
import android.provider.Settings.Secure.ADAPTIVE_CONNECTIVITY_ENABLED
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import com.android.settingslib.preference.createAndBindWidget
|
||||
import com.android.settingslib.widget.MainSwitchPreference
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.kotlin.atLeastOnce
|
||||
import org.mockito.kotlin.mock
|
||||
import org.mockito.kotlin.spy
|
||||
import org.mockito.kotlin.verify
|
||||
import org.mockito.kotlin.whenever
|
||||
|
||||
// LINT.IfChange
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class AdaptiveConnectivityTogglePreferenceTest {
|
||||
@get:Rule
|
||||
val setFlagsRule = SetFlagsRule()
|
||||
private val mockWifiManager = mock<WifiManager>()
|
||||
|
||||
private val appContext: Context = spy(ApplicationProvider.getApplicationContext()){}
|
||||
|
||||
private val mockWifiManager: WifiManager = mock()
|
||||
private val context: Context =
|
||||
object : ContextWrapper(ApplicationProvider.getApplicationContext()) {
|
||||
override fun getSystemService(name: String): Any? =
|
||||
when {
|
||||
name == getSystemServiceName(WifiManager::class.java) -> mockWifiManager
|
||||
else -> super.getSystemService(name)
|
||||
}
|
||||
}
|
||||
|
||||
private val adaptiveConnectivityTogglePreference = AdaptiveConnectivityTogglePreference()
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
whenever(appContext.getSystemService(WifiManager::class.java)).thenReturn(mockWifiManager)
|
||||
@Test
|
||||
fun switchClick_defaultDisabled_returnFalse() {
|
||||
setAdaptiveConnectivityEnabled(false)
|
||||
|
||||
assertThat(getMainSwitchPreference().isChecked).isFalse()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun setChecked_withTrue_shouldUpdateSetting() {
|
||||
Settings.Secure.putInt(
|
||||
appContext.contentResolver,
|
||||
Settings.Secure.ADAPTIVE_CONNECTIVITY_ENABLED, 0
|
||||
)
|
||||
fun switchClick_defaultEnabled_returnTrue() {
|
||||
setAdaptiveConnectivityEnabled(true)
|
||||
|
||||
val mainSwitchPreference = getMainSwitchPreferenceCompat().apply { performClick() }
|
||||
|
||||
assertThat(mainSwitchPreference.isChecked).isTrue()
|
||||
verify(mockWifiManager, atLeastOnce()).setWifiScoringEnabled(true)
|
||||
assertThat(getMainSwitchPreference().isChecked).isTrue()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun setChecked_withFalse_shouldUpdateSetting() {
|
||||
Settings.Secure.putInt(
|
||||
appContext.contentResolver,
|
||||
Settings.Secure.ADAPTIVE_CONNECTIVITY_ENABLED, 1
|
||||
)
|
||||
fun setChecked_defaultEnabled_updatesCorrectly() {
|
||||
val preference = getMainSwitchPreference()
|
||||
assertThat(preference.isChecked).isTrue()
|
||||
|
||||
val mainSwitchPreference = getMainSwitchPreferenceCompat().apply { performClick() }
|
||||
preference.performClick()
|
||||
|
||||
assertThat(mainSwitchPreference.isChecked).isFalse()
|
||||
assertThat(preference.isChecked).isFalse()
|
||||
|
||||
preference.performClick()
|
||||
|
||||
assertThat(preference.isChecked).isTrue()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun storeSetTrue_wifiManagerSetWifiScoringEnabled() {
|
||||
setAdaptiveConnectivityEnabled(true)
|
||||
|
||||
assertThat(getAdaptiveConnectivityEnabled()).isTrue()
|
||||
verify(mockWifiManager).setWifiScoringEnabled(true)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun storeSetFalse_wifiManagerSetWifiScoringDisabled() {
|
||||
setAdaptiveConnectivityEnabled(false)
|
||||
|
||||
assertThat(getAdaptiveConnectivityEnabled()).isFalse()
|
||||
verify(mockWifiManager).setWifiScoringEnabled(false)
|
||||
}
|
||||
|
||||
private fun getMainSwitchPreferenceCompat(): MainSwitchPreference =
|
||||
adaptiveConnectivityTogglePreference.createAndBindWidget(appContext)
|
||||
private fun getMainSwitchPreference(): MainSwitchPreference =
|
||||
adaptiveConnectivityTogglePreference.createAndBindWidget(context)
|
||||
|
||||
private fun setAdaptiveConnectivityEnabled(enabled: Boolean) =
|
||||
adaptiveConnectivityTogglePreference
|
||||
.storage(context)
|
||||
.setValue(ADAPTIVE_CONNECTIVITY_ENABLED, Boolean::class.javaObjectType, enabled)
|
||||
|
||||
private fun getAdaptiveConnectivityEnabled() =
|
||||
adaptiveConnectivityTogglePreference
|
||||
.storage(context)
|
||||
.getValue(ADAPTIVE_CONNECTIVITY_ENABLED, Boolean::class.javaObjectType)
|
||||
}
|
||||
// LINT.ThenChange(AdaptiveConnectivityTogglePreferenceControllerTest.java)
|
||||
|
||||
@@ -302,6 +302,26 @@ public class SoundPreferenceControllerTest {
|
||||
RingtoneManager.EXTRA_RINGTONE_TYPE, 0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnPreferenceTreeClick_noAudioAttributes() {
|
||||
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
|
||||
NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH);
|
||||
channel.setSound(null, null);
|
||||
mController.onResume(appRow, channel, null, null, null, null, null);
|
||||
|
||||
AttributeSet attributeSet = Robolectric.buildAttributeSet().build();
|
||||
NotificationSoundPreference pref =
|
||||
spy(new NotificationSoundPreference(mContext, attributeSet));
|
||||
pref.setKey(mController.getPreferenceKey());
|
||||
mController.handlePreferenceTreeClick(pref);
|
||||
|
||||
ArgumentCaptor<Intent> intentArgumentCaptor = ArgumentCaptor.forClass(Intent.class);
|
||||
verify(pref, times(1)).onPrepareRingtonePickerIntent(intentArgumentCaptor.capture());
|
||||
assertEquals(RingtoneManager.TYPE_NOTIFICATION,
|
||||
intentArgumentCaptor.getValue().getIntExtra(
|
||||
RingtoneManager.EXTRA_RINGTONE_TYPE, 0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnActivityResult() {
|
||||
NotificationSoundPreference pref = mock(NotificationSoundPreference.class);
|
||||
|
||||
@@ -20,7 +20,6 @@ import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.times;
|
||||
@@ -28,10 +27,8 @@ import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.app.Flags;
|
||||
import android.app.NotificationChannel;
|
||||
import android.content.Context;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.ParceledListSlice;
|
||||
import android.platform.test.annotations.EnableFlags;
|
||||
import android.platform.test.flag.junit.SetFlagsRule;
|
||||
|
||||
@@ -39,7 +36,6 @@ import androidx.fragment.app.Fragment;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceCategory;
|
||||
|
||||
import com.android.settings.notification.NotificationBackend;
|
||||
import com.android.settingslib.applications.ApplicationsState;
|
||||
|
||||
import org.junit.Before;
|
||||
@@ -54,6 +50,7 @@ import org.robolectric.RuntimeEnvironment;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@EnableFlags(Flags.FLAG_MODES_UI)
|
||||
@@ -66,7 +63,7 @@ public class ZenModeAllBypassingAppsPreferenceControllerTest {
|
||||
|
||||
private Context mContext;
|
||||
@Mock
|
||||
private NotificationBackend mBackend;
|
||||
private ZenHelperBackend mBackend;
|
||||
@Mock
|
||||
private PreferenceCategory mPreferenceCategory;
|
||||
@Mock
|
||||
@@ -102,18 +99,25 @@ public class ZenModeAllBypassingAppsPreferenceControllerTest {
|
||||
entry2.info.packageName = "test2";
|
||||
entry2.info.uid = 0;
|
||||
|
||||
ApplicationsState.AppEntry entry3= mock(ApplicationsState.AppEntry.class);
|
||||
entry3.info = new ApplicationInfo();
|
||||
entry3.info.packageName = "test3";
|
||||
entry3.info.uid = 0;
|
||||
|
||||
List<ApplicationsState.AppEntry> appEntries = new ArrayList<>();
|
||||
appEntries.add(entry1);
|
||||
appEntries.add(entry2);
|
||||
List<NotificationChannel> channelsBypassing = new ArrayList<>();
|
||||
channelsBypassing.add(mock(NotificationChannel.class));
|
||||
channelsBypassing.add(mock(NotificationChannel.class));
|
||||
when(mBackend.getNotificationChannelsBypassingDnd(anyString(),
|
||||
anyInt())).thenReturn(new ParceledListSlice<>(channelsBypassing));
|
||||
appEntries.add(entry3);
|
||||
when(mBackend.getPackagesBypassingDnd(anyInt())).thenReturn(
|
||||
Map.of("test", true, "test2", false));
|
||||
|
||||
// THEN there's are two preferences
|
||||
mController.updateAppList(appEntries);
|
||||
verify(mPreferenceCategory, times(2)).addPreference(any());
|
||||
ArgumentCaptor<Preference> captor = ArgumentCaptor.forClass(Preference.class);
|
||||
verify(mPreferenceCategory, times(2)).addPreference(captor.capture());
|
||||
List<Preference> prefs = captor.getAllValues();
|
||||
assertThat(prefs.get(0).getSummary().toString()).isEqualTo("All notifications");
|
||||
assertThat(prefs.get(1).getSummary().toString()).isEqualTo("Some notifications");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -77,6 +77,7 @@ import org.robolectric.RuntimeEnvironment;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@@ -200,8 +201,8 @@ public final class ZenModeAppsLinkPreferenceControllerTest {
|
||||
ApplicationsState.AppEntry app2 = createAppEntry("app2", mContext.getUserId());
|
||||
List<ApplicationsState.AppEntry> allApps = List.of(app1, app2);
|
||||
|
||||
when(mHelperBackend.getPackagesBypassingDnd(mContext.getUserId(),
|
||||
false)).thenReturn(List.of("app1"));
|
||||
when(mHelperBackend.getPackagesBypassingDnd(mContext.getUserId())).thenReturn(
|
||||
Map.of("app1", true));
|
||||
|
||||
assertThat(mController.getAppsBypassingDndSortedByName(allApps)).containsExactly(app1);
|
||||
}
|
||||
@@ -213,8 +214,8 @@ public final class ZenModeAppsLinkPreferenceControllerTest {
|
||||
ApplicationsState.AppEntry appB = createAppEntry("B", mContext.getUserId());
|
||||
List<ApplicationsState.AppEntry> allApps = List.of(appC, appA, appB);
|
||||
|
||||
when(mHelperBackend.getPackagesBypassingDnd(eq(mContext.getUserId()), anyBoolean()))
|
||||
.thenReturn(List.of("B", "C", "A"));
|
||||
when(mHelperBackend.getPackagesBypassingDnd(eq(mContext.getUserId())))
|
||||
.thenReturn(Map.of("B", true, "C", false, "A", true));
|
||||
|
||||
assertThat(mController.getAppsBypassingDndSortedByName(allApps))
|
||||
.containsExactly(appA, appB, appC).inOrder();
|
||||
@@ -234,10 +235,10 @@ public final class ZenModeAppsLinkPreferenceControllerTest {
|
||||
List<ApplicationsState.AppEntry> allApps = List.of(workCopy, personalCopy, otherPersonal,
|
||||
otherWork);
|
||||
|
||||
when(mHelperBackend.getPackagesBypassingDnd(eq(mContext.getUserId()), anyBoolean()))
|
||||
.thenReturn(List.of("app", "p2"));
|
||||
when(mHelperBackend.getPackagesBypassingDnd(eq(10), anyBoolean()))
|
||||
.thenReturn(List.of("app"));
|
||||
when(mHelperBackend.getPackagesBypassingDnd(eq(mContext.getUserId())))
|
||||
.thenReturn(Map.of("app", true, "p2", true));
|
||||
when(mHelperBackend.getPackagesBypassingDnd(eq(10)))
|
||||
.thenReturn(Map.of("app", false));
|
||||
|
||||
// Personal copy before work copy (names match).
|
||||
assertThat(mController.getAppsBypassingDndSortedByName(allApps))
|
||||
@@ -253,7 +254,7 @@ public final class ZenModeAppsLinkPreferenceControllerTest {
|
||||
mController.updateState(mPreference, zenMode);
|
||||
|
||||
verifyNoMoreInteractions(mSession);
|
||||
verify(mHelperBackend, never()).getPackagesBypassingDnd(anyInt(), anyBoolean());
|
||||
verify(mHelperBackend, never()).getPackagesBypassingDnd(anyInt());
|
||||
assertThat(String.valueOf(mPreference.getSummary())).isEqualTo("None");
|
||||
}
|
||||
|
||||
@@ -266,9 +267,8 @@ public final class ZenModeAppsLinkPreferenceControllerTest {
|
||||
ArrayList<ApplicationsState.AppEntry> appEntries = new ArrayList<>();
|
||||
appEntries.add(createAppEntry("test", mContext.getUserId()));
|
||||
|
||||
when(mHelperBackend.getPackagesBypassingDnd(
|
||||
mContext.getUserId(), false))
|
||||
.thenReturn(List.of("test"));
|
||||
when(mHelperBackend.getPackagesBypassingDnd(mContext.getUserId()))
|
||||
.thenReturn(Map.of("test", false));
|
||||
|
||||
// Updates the preference with the zen mode. We expect that this causes the app session
|
||||
// to trigger a rebuild (and display a temporary text in the meantime).
|
||||
@@ -286,8 +286,8 @@ public final class ZenModeAppsLinkPreferenceControllerTest {
|
||||
ZenMode zenMode = createPriorityChannelsZenMode();
|
||||
|
||||
mController.updateState(mPreference, zenMode);
|
||||
when(mHelperBackend.getPackagesBypassingDnd(anyInt(), anyBoolean()))
|
||||
.thenReturn(ImmutableList.of("test1", "test2"));
|
||||
when(mHelperBackend.getPackagesBypassingDnd(anyInt()))
|
||||
.thenReturn(Map.of("test1", false, "test2", false));
|
||||
ArrayList<ApplicationsState.AppEntry> appEntries = new ArrayList<>();
|
||||
appEntries.add(createAppEntry("test1", mContext.getUserId()));
|
||||
appEntries.add(createAppEntry("test2", mContext.getUserId()));
|
||||
@@ -328,8 +328,8 @@ public final class ZenModeAppsLinkPreferenceControllerTest {
|
||||
.build();
|
||||
ArrayList<ApplicationsState.AppEntry> appEntries = new ArrayList<>();
|
||||
appEntries.add(createAppEntry("test", mContext.getUserId()));
|
||||
when(mHelperBackend.getPackagesBypassingDnd(mContext.getUserId(), false))
|
||||
.thenReturn(List.of("test"));
|
||||
when(mHelperBackend.getPackagesBypassingDnd(mContext.getUserId()))
|
||||
.thenReturn(Map.of("test", true));
|
||||
|
||||
mController.updateState(mPreference, zenModeWithNone);
|
||||
|
||||
@@ -355,8 +355,8 @@ public final class ZenModeAppsLinkPreferenceControllerTest {
|
||||
.build();
|
||||
ArrayList<ApplicationsState.AppEntry> appEntries = new ArrayList<>();
|
||||
appEntries.add(createAppEntry("test", mContext.getUserId()));
|
||||
when(mHelperBackend.getPackagesBypassingDnd(mContext.getUserId(), false))
|
||||
.thenReturn(List.of("test"));
|
||||
when(mHelperBackend.getPackagesBypassingDnd(mContext.getUserId()))
|
||||
.thenReturn(Map.of("test", true));
|
||||
|
||||
mController.updateState(mPreference, zenModeWithPriority);
|
||||
|
||||
|
||||
@@ -16,12 +16,19 @@
|
||||
|
||||
package com.android.settings.notification.modes;
|
||||
|
||||
import static android.app.AutomaticZenRule.TYPE_SCHEDULE_TIME;
|
||||
import static android.service.notification.SystemZenRules.PACKAGE_ANDROID;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import android.app.Flags;
|
||||
import android.content.Context;
|
||||
import android.platform.test.annotations.EnableFlags;
|
||||
import android.platform.test.flag.junit.SetFlagsRule;
|
||||
import android.service.notification.SystemZenRules;
|
||||
import android.service.notification.ZenModeConfig;
|
||||
import android.text.Spanned;
|
||||
import android.text.style.TtsSpan;
|
||||
|
||||
import com.android.settingslib.notification.modes.TestModeBuilder;
|
||||
import com.android.settingslib.notification.modes.ZenIconLoader;
|
||||
@@ -37,6 +44,8 @@ import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
|
||||
import java.util.Calendar;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@EnableFlags(Flags.FLAG_MODES_UI)
|
||||
public class ZenModesListItemPreferenceTest {
|
||||
@@ -122,6 +131,31 @@ public class ZenModesListItemPreferenceTest {
|
||||
assertThat(preference.getIcon()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setZenMode_scheduleTime_hasCustomTtsInSummary() {
|
||||
ZenModeConfig.ScheduleInfo scheduleInfo = new ZenModeConfig.ScheduleInfo();
|
||||
scheduleInfo.days = new int[] { Calendar.MONDAY, Calendar.TUESDAY, Calendar.WEDNESDAY };
|
||||
scheduleInfo.startHour = 11;
|
||||
scheduleInfo.endHour = 15;
|
||||
ZenMode mode = new TestModeBuilder()
|
||||
.setPackage(PACKAGE_ANDROID)
|
||||
.setType(TYPE_SCHEDULE_TIME)
|
||||
.setConditionId(ZenModeConfig.toScheduleConditionId(scheduleInfo))
|
||||
.setTriggerDescription(
|
||||
SystemZenRules.getTriggerDescriptionForScheduleTime(mContext, scheduleInfo))
|
||||
.build();
|
||||
|
||||
ZenModesListItemPreference preference = newPreference(mode);
|
||||
|
||||
assertThat(preference.getSummary()).isInstanceOf(Spanned.class);
|
||||
Spanned summary = (Spanned) preference.getSummary();
|
||||
TtsSpan[] ttsSpans = summary.getSpans(0, summary.length(), TtsSpan.class);
|
||||
assertThat(ttsSpans).hasLength(1);
|
||||
assertThat(ttsSpans[0].getType()).isEqualTo(TtsSpan.TYPE_TEXT);
|
||||
assertThat(ttsSpans[0].getArgs().getString(TtsSpan.ARG_TEXT)).isEqualTo(
|
||||
"Monday to Wednesday, 11:00 AM - 3:00 PM");
|
||||
}
|
||||
|
||||
private ZenModesListItemPreference newPreference(ZenMode zenMode) {
|
||||
return new ZenModesListItemPreference(mContext, mIconLoader, MoreExecutors.directExecutor(),
|
||||
zenMode);
|
||||
|
||||
@@ -91,6 +91,68 @@ class ApnTypesTest {
|
||||
assertThat(apnType).isEqualTo("default,mms,supl,hipri,fota,cbs,xcap")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun hasAllApnTypes_allString() {
|
||||
val apnTypes = listOf(ApnSetting.TYPE_ALL_STRING)
|
||||
|
||||
val hasAllApnTypes = ApnTypes.hasAllApnTypes(apnTypes)
|
||||
|
||||
assertThat(hasAllApnTypes).isTrue()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun hasAllApnTypes_allTypes() {
|
||||
val apnTypes = listOf(
|
||||
ApnSetting.TYPE_DEFAULT_STRING,
|
||||
ApnSetting.TYPE_MMS_STRING,
|
||||
ApnSetting.TYPE_SUPL_STRING,
|
||||
ApnSetting.TYPE_DUN_STRING,
|
||||
ApnSetting.TYPE_HIPRI_STRING,
|
||||
ApnSetting.TYPE_FOTA_STRING,
|
||||
ApnSetting.TYPE_IMS_STRING,
|
||||
ApnSetting.TYPE_CBS_STRING,
|
||||
ApnSetting.TYPE_IA_STRING,
|
||||
ApnSetting.TYPE_EMERGENCY_STRING,
|
||||
ApnSetting.TYPE_MCX_STRING,
|
||||
ApnSetting.TYPE_XCAP_STRING,
|
||||
ApnSetting.TYPE_VSIM_STRING,
|
||||
ApnSetting.TYPE_BIP_STRING,
|
||||
ApnSetting.TYPE_ENTERPRISE_STRING,
|
||||
ApnSetting.TYPE_OEM_PAID_STRING,
|
||||
ApnSetting.TYPE_OEM_PRIVATE_STRING,
|
||||
)
|
||||
|
||||
val hasAllApnTypes = ApnTypes.hasAllApnTypes(apnTypes)
|
||||
|
||||
assertThat(hasAllApnTypes).isTrue()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun hasAllApnTypes_allTypesExceptDefault() {
|
||||
val apnTypes = listOf(
|
||||
ApnSetting.TYPE_MMS_STRING,
|
||||
ApnSetting.TYPE_SUPL_STRING,
|
||||
ApnSetting.TYPE_DUN_STRING,
|
||||
ApnSetting.TYPE_HIPRI_STRING,
|
||||
ApnSetting.TYPE_FOTA_STRING,
|
||||
ApnSetting.TYPE_IMS_STRING,
|
||||
ApnSetting.TYPE_CBS_STRING,
|
||||
ApnSetting.TYPE_IA_STRING,
|
||||
ApnSetting.TYPE_EMERGENCY_STRING,
|
||||
ApnSetting.TYPE_MCX_STRING,
|
||||
ApnSetting.TYPE_XCAP_STRING,
|
||||
ApnSetting.TYPE_VSIM_STRING,
|
||||
ApnSetting.TYPE_BIP_STRING,
|
||||
ApnSetting.TYPE_ENTERPRISE_STRING,
|
||||
ApnSetting.TYPE_OEM_PAID_STRING,
|
||||
ApnSetting.TYPE_OEM_PRIVATE_STRING,
|
||||
)
|
||||
|
||||
val hasAllApnTypes = ApnTypes.hasAllApnTypes(apnTypes)
|
||||
|
||||
assertThat(hasAllApnTypes).isFalse()
|
||||
}
|
||||
|
||||
private companion object {
|
||||
const val APN_TYPE = "type"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user