Snap for 12217053 from cc9a03437e to 24Q4-release

Change-Id: I9e45b6d42faca7fba89f5fde46d3bee8a3c93511
This commit is contained in:
Android Build Coastguard Worker
2024-08-12 23:26:04 +00:00
23 changed files with 756 additions and 126 deletions

View File

@@ -17,6 +17,7 @@
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/entity_header"
style="@style/EntityHeader"
android:layout_width="match_parent"
@@ -25,15 +26,41 @@
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:orientation="vertical">
<TextView
android:id="@+id/entity_header_title"
style="@style/TextAppearance.EntityHeaderTitle"
android:layout_width="wrap_content"
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:gravity="center"
android:ellipsize="marquee"
android:textDirection="locale"/>
android:gravity="center">
<TextView
android:id="@+id/entity_header_title"
style="@style/TextAppearance.EntityHeaderTitle"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:ellipsize="marquee"
android:textDirection="locale"
android:layout_marginStart="48dp"
android:layout_marginEnd="48dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constrainedWidth="true" />
<ImageButton
android:id="@+id/rename_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minWidth="@dimen/min_tap_target_size"
android:minHeight="@dimen/min_tap_target_size"
android:background="@android:color/transparent"
android:src="@drawable/ic_mode_edit"
android:contentDescription="@string/bluetooth_rename_button"
android:tint="@color/settingslib_materialColorOnSurface"
app:layout_constraintStart_toEndOf="@+id/entity_header_title"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:visibility="gone" />
</androidx.constraintlayout.widget.ConstraintLayout>
<TextView
android:id="@+id/entity_header_summary"

View File

@@ -0,0 +1,80 @@
<?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.
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/entity_header"
style="@style/EntityHeader"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:gravity="center_horizontal"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:orientation="vertical">
<ImageView
android:id="@+id/bt_header_icon"
android:importantForAccessibility="no"
style="@style/SettingsLibEntityHeaderIcon"/>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="8dp"
android:gravity="center">
<TextView
android:id="@+id/bt_header_device_name"
style="@style/TextAppearance.EntityHeaderTitle"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:gravity="center"
android:ellipsize="marquee"
android:textDirection="locale"
android:layout_marginStart="48dp"
android:layout_marginEnd="48dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constrainedWidth="true" />
<ImageButton
android:id="@+id/rename_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minWidth="@dimen/min_tap_target_size"
android:minHeight="@dimen/min_tap_target_size"
android:background="@android:color/transparent"
android:src="@drawable/ic_mode_edit"
android:contentDescription="@string/bluetooth_rename_button"
android:tint="@color/settingslib_materialColorOnSurface"
app:layout_constraintStart_toEndOf="@+id/bt_header_device_name"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<TextView
android:id="@+id/bt_header_connection_summary"
style="@style/TextAppearance.EntityHeaderSummary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:singleLine="false"
android:textAlignment="center"/>
</LinearLayout>

View File

@@ -17,6 +17,7 @@
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/entity_header"
style="@style/EntityHeader"
android:layout_width="match_parent"
@@ -27,15 +28,42 @@
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:orientation="vertical">
<TextView
android:id="@+id/entity_header_title"
style="@style/TextAppearance.EntityHeaderTitle"
android:layout_width="wrap_content"
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:gravity="center"
android:ellipsize="marquee"
android:textDirection="locale"/>
android:gravity="center">
<TextView
android:id="@+id/entity_header_title"
style="@style/TextAppearance.EntityHeaderTitle"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_gravity="center_horizontal"
android:gravity="center"
android:ellipsize="marquee"
android:textDirection="locale"
android:layout_marginStart="48dp"
android:layout_marginEnd="48dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constrainedWidth="true" />
<ImageButton
android:id="@+id/rename_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minWidth="@dimen/min_tap_target_size"
android:minHeight="@dimen/min_tap_target_size"
android:background="@android:color/transparent"
android:src="@drawable/ic_mode_edit"
android:contentDescription="@string/bluetooth_rename_button"
android:tint="@color/settingslib_materialColorOnSurface"
app:layout_constraintStart_toEndOf="@+id/entity_header_title"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:visibility="gone" />
</androidx.constraintlayout.widget.ConstraintLayout>
<TextView
android:id="@+id/entity_header_summary"

View File

@@ -24,7 +24,7 @@
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/icon_list"
android:layout_width="0dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clipToPadding="true"
android:nestedScrollingEnabled="false"

View File

@@ -17,10 +17,9 @@
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_width="@dimen/zen_mode_icon_list_item_size"
android:layout_height="@dimen/zen_mode_icon_list_item_size"
android:clickable="true">
<!-- width is match_parent to distribute remaining horizontal space -->
<ImageView
android:id="@+id/icon_image_view"

View File

@@ -510,9 +510,9 @@
<dimen name="zen_mode_blurb_text_size">16sp</dimen>
<dimen name="zen_mode_icon_list_header_circle_diameter">90dp</dimen>
<dimen name="zen_mode_icon_list_header_icon_size">48dp</dimen>
<dimen name="zen_mode_icon_list_item_size">96dp</dimen>
<dimen name="zen_mode_icon_list_item_circle_diameter">56dp</dimen>
<dimen name="zen_mode_icon_list_item_icon_size">32dp</dimen>
<dimen name="zen_mode_icon_list_item_size">76dp</dimen>
<dimen name="zen_mode_icon_list_item_circle_diameter">52dp</dimen>
<dimen name="zen_mode_icon_list_item_icon_size">28dp</dimen>
<!-- For the items in the CircularIconsPreference (contacts, apps, sound channels). -->
<dimen name="zen_mode_circular_icon_diameter">32dp</dimen>
<dimen name="zen_mode_circular_icon_inner_icon_size">20dp</dimen>

View File

@@ -26,6 +26,13 @@
settings:allowDividerBelow="true"
settings:searchable="false"/>
<com.android.settingslib.widget.LayoutPreference
android:key="general_bluetooth_device_header"
android:layout="@layout/general_bt_entity_header"
android:selectable="false"
settings:allowDividerBelow="true"
settings:searchable="false"/>
<com.android.settingslib.widget.LayoutPreference
android:key="advanced_bluetooth_device_header"
android:layout="@layout/advanced_bt_entity_header"

View File

@@ -37,12 +37,14 @@ import android.util.Log;
import android.util.Pair;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import androidx.annotation.VisibleForTesting;
import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.PreferenceScreen;
import com.android.settings.R;
@@ -97,6 +99,7 @@ public class AdvancedBluetoothDetailsHeaderController extends BasePreferenceCont
private static final int MAIN_DEVICE_ID = 4;
private static final float HALF_ALPHA = 0.5f;
PreferenceFragmentCompat mFragment;
@VisibleForTesting
LayoutPreference mLayoutPreference;
@VisibleForTesting
@@ -170,8 +173,11 @@ public class AdvancedBluetoothDetailsHeaderController extends BasePreferenceCont
mIconCache.clear();
}
public void init(CachedBluetoothDevice cachedBluetoothDevice) {
/** Initializes the controller. */
public void init(
CachedBluetoothDevice cachedBluetoothDevice, PreferenceFragmentCompat fragment) {
mCachedDevice = cachedBluetoothDevice;
mFragment = fragment;
}
private void registerBluetoothDevice() {
@@ -325,6 +331,14 @@ public class AdvancedBluetoothDetailsHeaderController extends BasePreferenceCont
MAIN_DEVICE_ID);
}
});
if (Flags.enableBluetoothDeviceDetailsPolish()) {
ImageButton renameButton = mLayoutPreference.findViewById(R.id.rename_button);
renameButton.setVisibility(View.VISIBLE);
renameButton.setOnClickListener(view -> {
RemoteDeviceNameDialogFragment.newInstance(mCachedDevice).show(
mFragment.getFragmentManager(), RemoteDeviceNameDialogFragment.TAG);
});
}
}
}

View File

@@ -26,6 +26,7 @@ import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.PreferenceScreen;
import com.android.settings.R;
import com.android.settings.flags.Flags;
import com.android.settings.widget.EntityHeaderController;
import com.android.settingslib.bluetooth.BluetoothUtils;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
@@ -47,6 +48,9 @@ public class BluetoothDetailsHeaderController extends BluetoothDetailsController
@Override
public boolean isAvailable() {
if (Flags.enableBluetoothDeviceDetailsPolish()) {
return false;
}
boolean hasLeAudio = mCachedDevice.getUiAccessibleProfiles()
.stream()
.anyMatch(profile -> profile.getProfileId() == BluetoothProfile.LE_AUDIO);

View File

@@ -50,6 +50,7 @@ import com.android.settings.R;
import com.android.settings.connecteddevice.stylus.StylusDevicesController;
import com.android.settings.core.SettingsUIDeviceConfig;
import com.android.settings.dashboard.RestrictedDashboardFragment;
import com.android.settings.flags.Flags;
import com.android.settings.inputmethod.KeyboardSettingsPreferenceController;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.slices.SlicePreferenceController;
@@ -213,8 +214,8 @@ public class BluetoothDeviceDetailsFragment extends RestrictedDashboardFragment
finish();
return;
}
use(AdvancedBluetoothDetailsHeaderController.class).init(mCachedDevice);
use(LeAudioBluetoothDetailsHeaderController.class).init(mCachedDevice, mManager);
use(AdvancedBluetoothDetailsHeaderController.class).init(mCachedDevice, this);
use(LeAudioBluetoothDetailsHeaderController.class).init(mCachedDevice, mManager, this);
use(KeyboardSettingsPreferenceController.class).init(mCachedDevice);
final BluetoothFeatureProvider featureProvider =
@@ -338,7 +339,7 @@ public class BluetoothDeviceDetailsFragment extends RestrictedDashboardFragment
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
if (!mUserManager.isGuestUser()) {
if (!Flags.enableBluetoothDeviceDetailsPolish() && !mUserManager.isGuestUser()) {
MenuItem item = menu.add(0, EDIT_DEVICE_NAME_ITEM_ID, 0,
R.string.bluetooth_rename_button);
item.setIcon(com.android.internal.R.drawable.ic_mode_edit);
@@ -365,6 +366,9 @@ public class BluetoothDeviceDetailsFragment extends RestrictedDashboardFragment
Lifecycle lifecycle = getSettingsLifecycle();
controllers.add(new BluetoothDetailsHeaderController(context, this, mCachedDevice,
lifecycle));
controllers.add(
new GeneralBluetoothDetailsHeaderController(
context, this, mCachedDevice, lifecycle));
controllers.add(new BluetoothDetailsButtonsController(context, this, mCachedDevice,
lifecycle));
controllers.add(new BluetoothDetailsCompanionAppsController(context, this,

View File

@@ -0,0 +1,108 @@
/*
* 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.bluetooth;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.util.Pair;
import android.view.View;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.PreferenceScreen;
import com.android.settings.R;
import com.android.settings.flags.Flags;
import com.android.settingslib.bluetooth.BluetoothUtils;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.widget.LayoutPreference;
/** This class adds a header with device name and status (connected/disconnected, etc.). */
public class GeneralBluetoothDetailsHeaderController extends BluetoothDetailsController {
private static final String KEY_GENERAL_DEVICE_HEADER = "general_bluetooth_device_header";
@Nullable
private LayoutPreference mLayoutPreference;
public GeneralBluetoothDetailsHeaderController(
Context context,
PreferenceFragmentCompat fragment,
CachedBluetoothDevice device,
Lifecycle lifecycle) {
super(context, fragment, device, lifecycle);
}
@Override
public boolean isAvailable() {
if (!Flags.enableBluetoothDeviceDetailsPolish()) {
return false;
}
boolean hasLeAudio =
mCachedDevice.getUiAccessibleProfiles().stream()
.anyMatch(profile -> profile.getProfileId() == BluetoothProfile.LE_AUDIO);
return !BluetoothUtils.isAdvancedDetailsHeader(mCachedDevice.getDevice()) && !hasLeAudio;
}
@Override
protected void init(PreferenceScreen screen) {
mLayoutPreference = screen.findPreference(KEY_GENERAL_DEVICE_HEADER);
}
@Override
protected void refresh() {
if (!isAvailable() || mLayoutPreference == null) {
return;
}
ImageView imageView = mLayoutPreference.findViewById(R.id.bt_header_icon);
if (imageView != null) {
final Pair<Drawable, String> pair =
BluetoothUtils.getBtRainbowDrawableWithDescription(mContext, mCachedDevice);
imageView.setImageDrawable(pair.first);
imageView.setContentDescription(pair.second);
}
TextView title = mLayoutPreference.findViewById(R.id.bt_header_device_name);
if (title != null) {
title.setText(mCachedDevice.getName());
}
TextView summary = mLayoutPreference.findViewById(R.id.bt_header_connection_summary);
if (summary != null) {
summary.setText(mCachedDevice.getConnectionSummary());
}
ImageButton renameButton = mLayoutPreference.findViewById(R.id.rename_button);
renameButton.setVisibility(View.VISIBLE);
renameButton.setOnClickListener(
view -> {
RemoteDeviceNameDialogFragment.newInstance(mCachedDevice)
.show(
mFragment.getFragmentManager(),
RemoteDeviceNameDialogFragment.TAG);
});
}
@Override
@NonNull
public String getPreferenceKey() {
return KEY_GENERAL_DEVICE_HEADER;
}
}

View File

@@ -27,14 +27,17 @@ import android.os.Looper;
import android.util.Log;
import android.util.Pair;
import android.view.View;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.VisibleForTesting;
import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.PreferenceScreen;
import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.flags.Flags;
import com.android.settings.fuelgauge.BatteryMeterView;
import com.android.settingslib.bluetooth.BluetoothUtils;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
@@ -86,6 +89,7 @@ public class LeAudioBluetoothDetailsHeaderController extends BasePreferenceContr
@VisibleForTesting
static final int INVALID_RESOURCE_ID = -1;
PreferenceFragmentCompat mFragment;
@VisibleForTesting
LayoutPreference mLayoutPreference;
LocalBluetoothManager mManager;
@@ -151,11 +155,12 @@ public class LeAudioBluetoothDetailsHeaderController extends BasePreferenceContr
}
public void init(CachedBluetoothDevice cachedBluetoothDevice,
LocalBluetoothManager bluetoothManager) {
LocalBluetoothManager bluetoothManager, PreferenceFragmentCompat fragment) {
mCachedDevice = cachedBluetoothDevice;
mManager = bluetoothManager;
mProfileManager = bluetoothManager.getProfileManager();
mCachedDeviceGroup = Utils.findAllCachedBluetoothDevicesByGroupId(mManager, mCachedDevice);
mFragment = fragment;
}
@VisibleForTesting
@@ -163,6 +168,14 @@ public class LeAudioBluetoothDetailsHeaderController extends BasePreferenceContr
if (mLayoutPreference == null || mCachedDevice == null) {
return;
}
if (Flags.enableBluetoothDeviceDetailsPolish()) {
ImageButton renameButton = mLayoutPreference.findViewById(R.id.rename_button);
renameButton.setVisibility(View.VISIBLE);
renameButton.setOnClickListener(view -> {
RemoteDeviceNameDialogFragment.newInstance(mCachedDevice).show(
mFragment.getFragmentManager(), RemoteDeviceNameDialogFragment.TAG);
});
}
final ImageView imageView = mLayoutPreference.findViewById(R.id.entity_header_icon);
if (imageView != null) {
final Pair<Drawable, String> pair =

View File

@@ -241,6 +241,8 @@ public class SubscriptionsPreferenceController extends AbstractPreferenceControl
if (mSubsGearPref == null) {
mPreferenceGroup.removeAll();
mSubsGearPref = new MutableGearPreference(mContext, null);
mSubsGearPref
.checkRestrictionAndSetDisabled(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS);
mSubsGearPref.setOnPreferenceClickListener(preference -> {
connectCarrierNetwork();
return true;

View File

@@ -202,7 +202,6 @@ public class MobileNetworkSettings extends AbstractMobileNetworkSettings impleme
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (mSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
Log.d(LOG_TAG, "Invalid subId, get the default subscription to show.");
SubscriptionInfo info = SubscriptionUtil.getSubscriptionOrDefault(context, mSubId);
@@ -341,6 +340,11 @@ public class MobileNetworkSettings extends AbstractMobileNetworkSettings impleme
setTelephonyAvailabilityStatus(getPreferenceControllersAsList());
super.onCreate(icicle);
if (isUiRestricted()) {
Log.d(LOG_TAG, "Mobile network page is disallowed.");
finish();
return;
}
final Context context = getContext();
mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
mTelephonyManager = context.getSystemService(TelephonyManager.class)

View File

@@ -82,8 +82,8 @@ class IconUtil {
}
/**
* Returns a variant of the supplied {@code icon} to be used as the header in the icon picker.
* The inner icon is 48x48dp and it's contained in a circle of diameter 90dp.
* Returns a variant of the supplied {@code icon} to be used as the header in the icon picker
* (large icon within large circle, with the "material secondary" color combination).
*/
static Drawable makeIconPickerHeader(@NonNull Context context, Drawable icon) {
return composeIconCircle(
@@ -99,9 +99,9 @@ class IconUtil {
}
/**
* Returns a variant of the supplied {@code icon} to be used as an option in the icon picker.
* The inner icon is 36x36dp and it's contained in a circle of diameter 54dp. It's also set up
* so that selection and pressed states are represented in the color.
* Returns a variant of the supplied {@code icon} to be used as an option in the icon picker
* (small icon in small circle, with "material secondary" colors for the normal state and
* "material primary" colors for the selected state).
*/
static Drawable makeIconPickerItem(@NonNull Context context, @DrawableRes int iconResId) {
return composeIconCircle(

View File

@@ -18,6 +18,7 @@ package com.android.settings.system.reset
import android.app.ProgressDialog
import android.app.settings.SettingsEnums
import android.content.DialogInterface
import android.os.Bundle
import android.os.Looper
import android.telephony.SubscriptionManager
@@ -56,7 +57,8 @@ import kotlinx.coroutines.withContext
* This is the confirmation screen.
*/
class ResetNetworkConfirm : InstrumentedFragment() {
@VisibleForTesting lateinit var resetNetworkRequest: ResetNetworkRequest
@VisibleForTesting
lateinit var resetNetworkRequest: ResetNetworkRequest
private var progressDialog: ProgressDialog? = null
private var alertDialog: AlertDialog? = null
private var resetStarted = false
@@ -87,10 +89,7 @@ class ResetNetworkConfirm : InstrumentedFragment() {
/** Configure the UI for the final confirmation interaction */
private fun View.establishFinalConfirmationState() {
requireViewById<View>(R.id.execute_reset_network).setOnClickListener {
if (!Utils.isMonkeyRunning() && !resetStarted) {
resetStarted = true
viewLifecycleOwner.lifecycleScope.launch { onResetClicked() }
}
showResetInternetDialog();
}
}
@@ -118,10 +117,10 @@ class ResetNetworkConfirm : InstrumentedFragment() {
private fun invalidSubIdFlow(): Flow<Int> {
val subIdsInRequest =
listOf(
resetNetworkRequest.resetTelephonyAndNetworkPolicyManager,
resetNetworkRequest.resetApnSubId,
resetNetworkRequest.resetImsSubId,
)
resetNetworkRequest.resetTelephonyAndNetworkPolicyManager,
resetNetworkRequest.resetApnSubId,
resetNetworkRequest.resetImsSubId,
)
.distinct()
.filter(SubscriptionManager::isUsableSubscriptionId)
@@ -162,6 +161,24 @@ class ResetNetworkConfirm : InstrumentedFragment() {
}
}
private fun showResetInternetDialog() {
val builder = AlertDialog.Builder(requireContext())
val resetInternetClickListener =
DialogInterface.OnClickListener { dialog, which ->
if (!Utils.isMonkeyRunning() && !resetStarted) {
resetStarted = true
viewLifecycleOwner.lifecycleScope.launch { onResetClicked() }
}
}
builder.setTitle(R.string.reset_your_internet_title)
.setMessage(R.string.reset_internet_text)
.setPositiveButton(R.string.tts_reset, resetInternetClickListener)
.setNegativeButton(android.R.string.cancel, null)
.create()
.show()
}
/**
* Do all reset task.
*
@@ -173,7 +190,8 @@ class ResetNetworkConfirm : InstrumentedFragment() {
withContext(Dispatchers.Default) {
val builder =
resetNetworkRequest.toResetNetworkOperationBuilder(
requireContext(), Looper.getMainLooper())
requireContext(), Looper.getMainLooper()
)
resetNetworkRequest.resetEsimPackageName?.let { resetEsimPackageName ->
builder.resetEsim(resetEsimPackageName)
builder.resetEsimResultCallback { resetEsimSuccess = it }
@@ -199,8 +217,8 @@ class ResetNetworkConfirm : InstrumentedFragment() {
} else {
Toast.makeText(activity, R.string.reset_network_complete_toast, Toast.LENGTH_SHORT)
.show()
activity.finish()
}
activity.finish()
}
override fun onDestroy() {

View File

@@ -651,7 +651,7 @@ public class AppRestrictionsFragment extends SettingsPreferenceFragment implemen
int requestCode = generateCustomActivityRequestCode(
RestrictionsResultReceiver.this.preference);
AppRestrictionsFragment.this.startActivityForResult(
restrictionsIntent, requestCode);
new Intent(restrictionsIntent), requestCode);
}
}
}

View File

@@ -41,11 +41,13 @@ public class MutableGearPreference extends GearPreference {
@Override
public void setGearEnabled(boolean enabled) {
boolean state = false;
if (mGear != null) {
mGear.setEnabled(enabled);
mGear.setImageAlpha(enabled ? VALUE_ENABLED_ALPHA : mDisabledAlphaValue);
state = enabled && !(isDisabledByAdmin() || isDisabledByEcm());
mGear.setEnabled(state);
mGear.setImageAlpha(state ? VALUE_ENABLED_ALPHA : mDisabledAlphaValue);
}
mGearState = enabled;
mGearState = state;
}
@Override

View File

@@ -371,12 +371,20 @@ public class WifiTetherSettings extends RestrictedDashboardFragment
|| !mWifiRestriction.isHotspotAvailable(context)) {
keys.add(KEY_WIFI_TETHER_NETWORK_NAME);
keys.add(KEY_WIFI_TETHER_SECURITY);
keys.add(KEY_WIFI_HOTSPOT_SECURITY);
keys.add(KEY_WIFI_TETHER_NETWORK_PASSWORD);
keys.add(KEY_WIFI_TETHER_AUTO_OFF);
keys.add(KEY_WIFI_TETHER_MAXIMIZE_COMPATIBILITY);
keys.add(KEY_WIFI_HOTSPOT_SPEED);
keys.add(KEY_INSTANT_HOTSPOT);
} else if (!mIsInstantHotspotEnabled) {
keys.add(KEY_INSTANT_HOTSPOT);
} else {
if (!isSpeedFeatureAvailable()) {
keys.add(KEY_WIFI_HOTSPOT_SECURITY);
keys.add(KEY_WIFI_HOTSPOT_SPEED);
}
if (!mIsInstantHotspotEnabled) {
keys.add(KEY_INSTANT_HOTSPOT);
}
}
// Remove duplicate
@@ -400,6 +408,12 @@ public class WifiTetherSettings extends RestrictedDashboardFragment
public List<AbstractPreferenceController> createPreferenceControllers(Context context) {
return buildPreferenceControllers(context, null /* listener */);
}
@VisibleForTesting
boolean isSpeedFeatureAvailable() {
return FeatureFactory.getFeatureFactory().getWifiFeatureProvider()
.getWifiHotspotRepository().isSpeedFeatureAvailable();
}
}
@VisibleForTesting

View File

@@ -28,15 +28,19 @@ import android.bluetooth.BluetoothDevice;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
import android.provider.DeviceConfig;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import androidx.preference.PreferenceFragmentCompat;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.core.BasePreferenceController;
@@ -93,6 +97,8 @@ public class AdvancedBluetoothDetailsHeaderControllerTest {
private CachedBluetoothDevice mCachedDevice;
@Mock
private BluetoothAdapter mBluetoothAdapter;
@Mock
private PreferenceFragmentCompat mFragment;
private AdvancedBluetoothDetailsHeaderController mController;
private LayoutPreference mLayoutPreference;
@@ -103,7 +109,7 @@ public class AdvancedBluetoothDetailsHeaderControllerTest {
mContext = Robolectric.buildActivity(SettingsActivity.class).get();
mController = new AdvancedBluetoothDetailsHeaderController(mContext, "pref_Key");
when(mCachedDevice.getDevice()).thenReturn(mBluetoothDevice);
mController.init(mCachedDevice);
mController.init(mCachedDevice, mFragment);
mLayoutPreference = new LayoutPreference(mContext,
LayoutInflater.from(mContext).inflate(R.layout.advanced_bt_entity_header, null));
mController.mLayoutPreference = mLayoutPreference;
@@ -540,6 +546,22 @@ public class AdvancedBluetoothDetailsHeaderControllerTest {
rightBatteryPrediction);
}
@Test
@EnableFlags(Flags.FLAG_ENABLE_BLUETOOTH_DEVICE_DETAILS_POLISH)
public void enablePolishFlag_renameButtonShown() {
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SETTINGS_UI,
SettingsUIDeviceConfig.BT_ADVANCED_HEADER_ENABLED, "true", true);
when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET))
.thenReturn("true".getBytes());
Set<CachedBluetoothDevice> cacheBluetoothDevices = new HashSet<>();
when(mCachedDevice.getMemberDevice()).thenReturn(cacheBluetoothDevices);
mController.onStart();
ImageButton button = mLayoutPreference.findViewById(R.id.rename_button);
assertThat(button.getVisibility()).isEqualTo(View.VISIBLE);
}
private void assertBatteryPredictionVisible(LinearLayout linearLayout, int visible) {
final TextView textView = linearLayout.findViewById(R.id.bt_battery_prediction);
assertThat(textView.getVisibility()).isEqualTo(visible);

View File

@@ -0,0 +1,180 @@
/*
* 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.bluetooth;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.when;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
import android.platform.test.annotations.DisableFlags;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
import android.widget.TextView;
import com.android.settings.R;
import com.android.settings.core.SettingsUIDeviceConfig;
import com.android.settings.flags.Flags;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.shadow.ShadowDeviceConfig;
import com.android.settings.testutils.shadow.ShadowEntityHeaderController;
import com.android.settingslib.bluetooth.LeAudioProfile;
import com.android.settingslib.widget.LayoutPreference;
import org.junit.After;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
import java.util.List;
@RunWith(RobolectricTestRunner.class)
@Config(shadows = {ShadowDeviceConfig.class})
public class GeneralBluetoothDetailsHeaderControllerTest
extends BluetoothDetailsControllerTestBase {
@Rule
public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
private GeneralBluetoothDetailsHeaderController mController;
private LayoutPreference mPreference;
@Mock private BluetoothDevice mBluetoothDevice;
@Mock private LeAudioProfile mLeAudioProfile;
@Override
public void setUp() {
super.setUp();
FakeFeatureFactory.setupForTest();
android.provider.DeviceConfig.setProperty(
android.provider.DeviceConfig.NAMESPACE_SETTINGS_UI,
SettingsUIDeviceConfig.BT_ADVANCED_HEADER_ENABLED,
"true",
true);
mController =
new GeneralBluetoothDetailsHeaderController(
mContext, mFragment, mCachedDevice, mLifecycle);
mPreference = new LayoutPreference(mContext, R.layout.general_bt_entity_header);
mPreference.setKey(mController.getPreferenceKey());
mScreen.addPreference(mPreference);
setupDevice(mDeviceConfig);
when(mCachedDevice.getDevice()).thenReturn(mBluetoothDevice);
when(mLeAudioProfile.getProfileId()).thenReturn(BluetoothProfile.LE_AUDIO);
}
@After
public void tearDown() {
ShadowEntityHeaderController.reset();
}
/**
* Test to verify the current test context object works so that we are not checking null against
* null
*/
@Test
public void testContextMock() {
assertThat(mContext.getString(com.android.settingslib.R.string.bluetooth_connected))
.isNotNull();
}
@Test
@EnableFlags(Flags.FLAG_ENABLE_BLUETOOTH_DEVICE_DETAILS_POLISH)
public void header() {
when(mCachedDevice.getName()).thenReturn("device name");
when(mCachedDevice.getConnectionSummary()).thenReturn("Active");
showScreen(mController);
TextView deviceName = mPreference.findViewById(R.id.bt_header_device_name);
TextView summary = mPreference.findViewById(R.id.bt_header_connection_summary);
assertThat(deviceName.getText().toString()).isEqualTo("device name");
assertThat(summary.getText().toString()).isEqualTo("Active");
}
@Test
@EnableFlags(Flags.FLAG_ENABLE_BLUETOOTH_DEVICE_DETAILS_POLISH)
public void connectionStatusChangesWhileScreenOpen() {
TextView summary = mPreference.findViewById(R.id.bt_header_connection_summary);
when(mCachedDevice.getConnectionSummary())
.thenReturn(
mContext.getString(com.android.settingslib.R.string.bluetooth_connected));
showScreen(mController);
String summaryText1 = summary.getText().toString();
when(mCachedDevice.getConnectionSummary()).thenReturn(null);
mController.onDeviceAttributesChanged();
String summaryText2 = summary.getText().toString();
when(mCachedDevice.getConnectionSummary())
.thenReturn(
mContext.getString(com.android.settingslib.R.string.bluetooth_connecting));
mController.onDeviceAttributesChanged();
String summaryText3 = summary.getText().toString();
assertThat(summaryText1)
.isEqualTo(
mContext.getString(com.android.settingslib.R.string.bluetooth_connected));
assertThat(summaryText2).isEqualTo("");
assertThat(summaryText3)
.isEqualTo(
mContext.getString(com.android.settingslib.R.string.bluetooth_connecting));
}
@Test
@EnableFlags(Flags.FLAG_ENABLE_BLUETOOTH_DEVICE_DETAILS_POLISH)
public void isAvailable_untetheredHeadset_returnFalse() {
when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET))
.thenReturn("true".getBytes());
assertThat(mController.isAvailable()).isFalse();
}
@Test
@EnableFlags(Flags.FLAG_ENABLE_BLUETOOTH_DEVICE_DETAILS_POLISH)
public void isAvailable_notUntetheredHeadset_returnTrue() {
when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET))
.thenReturn("false".getBytes());
assertThat(mController.isAvailable()).isTrue();
}
@Test
@EnableFlags(Flags.FLAG_ENABLE_BLUETOOTH_DEVICE_DETAILS_POLISH)
public void isAvailable_leAudioDevice_returnFalse() {
when(mCachedDevice.getUiAccessibleProfiles())
.thenReturn(List.of(mLeAudioProfile));
assertThat(mController.isAvailable()).isFalse();
}
@Test
@EnableFlags(Flags.FLAG_ENABLE_BLUETOOTH_DEVICE_DETAILS_POLISH)
public void isAvailable_flagEnabled_returnTrue() {
when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET))
.thenReturn("false".getBytes());
assertThat(mController.isAvailable()).isTrue();
}
@Test
@DisableFlags(Flags.FLAG_ENABLE_BLUETOOTH_DEVICE_DETAILS_POLISH)
public void iaAvailable_flagDisabled_returnFalse() {
assertThat(mController.isAvailable()).isFalse();
}
}

View File

@@ -263,91 +263,114 @@ public class WifiTetherSettingsTest {
@Test
public void getNonIndexableKeys_tetherAvailable_keysNotReturned() {
when(mWifiRestriction.isTetherAvailable(mContext)).thenReturn(true);
when(mWifiRestriction.isHotspotAvailable(mContext)).thenReturn(true);
WifiTetherSettings.SearchIndexProvider searchIndexProvider =
new WifiTetherSettings.SearchIndexProvider(XML_RES, mWifiRestriction,
true /* isInstantHotspotEnabled */);
WifiTetherSettings.SearchIndexProvider searchIndexProvider = createSearchIndexProvider(
true /* isTetherAvailable */, true /* isHotspotAvailable */,
true /* isInstantHotspotEnabled */, true /* isSpeedFeatureAvailable */);
final List<String> keys = searchIndexProvider.getNonIndexableKeys(mContext);
assertThat(keys).doesNotContain(WifiTetherSettings.KEY_WIFI_TETHER_NETWORK_NAME);
assertThat(keys).doesNotContain(WifiTetherSettings.KEY_WIFI_TETHER_SECURITY);
assertThat(keys).doesNotContain(WifiTetherSettings.KEY_WIFI_HOTSPOT_SECURITY);
assertThat(keys).doesNotContain(WifiTetherSettings.KEY_WIFI_TETHER_NETWORK_PASSWORD);
assertThat(keys).doesNotContain(WifiTetherSettings.KEY_WIFI_TETHER_AUTO_OFF);
assertThat(keys).doesNotContain(WifiTetherSettings.KEY_WIFI_TETHER_MAXIMIZE_COMPATIBILITY);
assertThat(keys).doesNotContain(WifiTetherSettings.KEY_WIFI_HOTSPOT_SPEED);
assertThat(keys).doesNotContain(WifiTetherSettings.KEY_INSTANT_HOTSPOT);
}
@Test
public void getNonIndexableKeys_tetherNotAvailable_keysReturned() {
WifiTetherSettings.SearchIndexProvider searchIndexProvider = createSearchIndexProvider(
false /* isTetherAvailable */, true /* isHotspotAvailable */,
true /* isInstantHotspotEnabled */, true /* isSpeedFeatureAvailable */);
final List<String> keys = searchIndexProvider.getNonIndexableKeys(mContext);
assertThat(keys).contains(WifiTetherSettings.KEY_WIFI_TETHER_NETWORK_NAME);
assertThat(keys).contains(WifiTetherSettings.KEY_WIFI_TETHER_SECURITY);
assertThat(keys).contains(WifiTetherSettings.KEY_WIFI_HOTSPOT_SECURITY);
assertThat(keys).contains(WifiTetherSettings.KEY_WIFI_TETHER_NETWORK_PASSWORD);
assertThat(keys).contains(WifiTetherSettings.KEY_WIFI_TETHER_AUTO_OFF);
assertThat(keys).contains(WifiTetherSettings.KEY_WIFI_TETHER_MAXIMIZE_COMPATIBILITY);
assertThat(keys).contains(WifiTetherSettings.KEY_WIFI_HOTSPOT_SPEED);
assertThat(keys).contains(WifiTetherSettings.KEY_INSTANT_HOTSPOT);
}
@Test
public void getNonIndexableKeys_hotspotNotAvailable_keysReturned() {
WifiTetherSettings.SearchIndexProvider searchIndexProvider = createSearchIndexProvider(
true /* isTetherAvailable */, false /* isHotspotAvailable */,
true /* isInstantHotspotEnabled */, true /* isSpeedFeatureAvailable */);
final List<String> keys = searchIndexProvider.getNonIndexableKeys(mContext);
assertThat(keys).contains(WifiTetherSettings.KEY_WIFI_TETHER_NETWORK_NAME);
assertThat(keys).contains(WifiTetherSettings.KEY_WIFI_TETHER_SECURITY);
assertThat(keys).contains(WifiTetherSettings.KEY_WIFI_HOTSPOT_SECURITY);
assertThat(keys).contains(WifiTetherSettings.KEY_WIFI_TETHER_NETWORK_PASSWORD);
assertThat(keys).contains(WifiTetherSettings.KEY_WIFI_TETHER_AUTO_OFF);
assertThat(keys).contains(WifiTetherSettings.KEY_WIFI_TETHER_MAXIMIZE_COMPATIBILITY);
assertThat(keys).contains(WifiTetherSettings.KEY_WIFI_HOTSPOT_SPEED);
assertThat(keys).contains(WifiTetherSettings.KEY_INSTANT_HOTSPOT);
}
@Test
public void getNonIndexableKeys_tetherAndHotspotNotAvailable_keysReturned() {
WifiTetherSettings.SearchIndexProvider searchIndexProvider = createSearchIndexProvider(
false /* isTetherAvailable */, false /* isHotspotAvailable */,
true /* isInstantHotspotEnabled */, true /* isSpeedFeatureAvailable */);
final List<String> keys = searchIndexProvider.getNonIndexableKeys(mContext);
assertThat(keys).contains(WifiTetherSettings.KEY_WIFI_TETHER_NETWORK_NAME);
assertThat(keys).contains(WifiTetherSettings.KEY_WIFI_TETHER_SECURITY);
assertThat(keys).contains(WifiTetherSettings.KEY_WIFI_HOTSPOT_SECURITY);
assertThat(keys).contains(WifiTetherSettings.KEY_WIFI_TETHER_NETWORK_PASSWORD);
assertThat(keys).contains(WifiTetherSettings.KEY_WIFI_TETHER_AUTO_OFF);
assertThat(keys).contains(WifiTetherSettings.KEY_WIFI_TETHER_MAXIMIZE_COMPATIBILITY);
assertThat(keys).contains(WifiTetherSettings.KEY_WIFI_HOTSPOT_SPEED);
assertThat(keys).contains(WifiTetherSettings.KEY_INSTANT_HOTSPOT);
}
@Test
public void getNonIndexableKeys_instantHotspotNotAvailableOnly_keysContainInstantHotspotOnly() {
WifiTetherSettings.SearchIndexProvider searchIndexProvider = createSearchIndexProvider(
true /* isTetherAvailable */, true /* isHotspotAvailable */,
false /* isInstantHotspotEnabled */, true /* isSpeedFeatureAvailable */);
final List<String> keys = searchIndexProvider.getNonIndexableKeys(mContext);
// doesNotContain
assertThat(keys).doesNotContain(WifiTetherSettings.KEY_WIFI_TETHER_NETWORK_NAME);
assertThat(keys).doesNotContain(WifiTetherSettings.KEY_WIFI_TETHER_SECURITY);
assertThat(keys).doesNotContain(WifiTetherSettings.KEY_WIFI_HOTSPOT_SECURITY);
assertThat(keys).doesNotContain(WifiTetherSettings.KEY_WIFI_TETHER_NETWORK_PASSWORD);
assertThat(keys).doesNotContain(WifiTetherSettings.KEY_WIFI_TETHER_AUTO_OFF);
assertThat(keys).doesNotContain(WifiTetherSettings.KEY_WIFI_TETHER_MAXIMIZE_COMPATIBILITY);
assertThat(keys).doesNotContain(WifiTetherSettings.KEY_WIFI_HOTSPOT_SPEED);
// contains
assertThat(keys).contains(WifiTetherSettings.KEY_INSTANT_HOTSPOT);
}
@Test
public void getNonIndexableKeys_speedFeatureNotAvailableOnly_keysContainInstantHotspotOnly() {
WifiTetherSettings.SearchIndexProvider searchIndexProvider = createSearchIndexProvider(
true /* isTetherAvailable */, true /* isHotspotAvailable */,
true /* isInstantHotspotEnabled */, false /* isSpeedFeatureAvailable */);
final List<String> keys = searchIndexProvider.getNonIndexableKeys(mContext);
// doesNotContain
assertThat(keys).doesNotContain(WifiTetherSettings.KEY_WIFI_TETHER_NETWORK_NAME);
assertThat(keys).doesNotContain(WifiTetherSettings.KEY_WIFI_TETHER_SECURITY);
assertThat(keys).doesNotContain(WifiTetherSettings.KEY_WIFI_TETHER_NETWORK_PASSWORD);
assertThat(keys).doesNotContain(WifiTetherSettings.KEY_WIFI_TETHER_AUTO_OFF);
assertThat(keys).doesNotContain(WifiTetherSettings.KEY_WIFI_TETHER_MAXIMIZE_COMPATIBILITY);
assertThat(keys).doesNotContain(WifiTetherSettings.KEY_INSTANT_HOTSPOT);
}
@Test
public void getNonIndexableKeys_tetherNotAvailable_keysReturned() {
when(mWifiRestriction.isTetherAvailable(mContext)).thenReturn(false);
when(mWifiRestriction.isHotspotAvailable(mContext)).thenReturn(true);
WifiTetherSettings.SearchIndexProvider searchIndexProvider =
new WifiTetherSettings.SearchIndexProvider(XML_RES, mWifiRestriction,
true /* isInstantHotspotEnabled */);
final List<String> keys = searchIndexProvider.getNonIndexableKeys(mContext);
assertThat(keys).contains(WifiTetherSettings.KEY_WIFI_TETHER_NETWORK_NAME);
assertThat(keys).contains(WifiTetherSettings.KEY_WIFI_TETHER_SECURITY);
assertThat(keys).contains(WifiTetherSettings.KEY_WIFI_TETHER_NETWORK_PASSWORD);
assertThat(keys).contains(WifiTetherSettings.KEY_WIFI_TETHER_AUTO_OFF);
assertThat(keys).contains(WifiTetherSettings.KEY_WIFI_TETHER_MAXIMIZE_COMPATIBILITY);
assertThat(keys).contains(WifiTetherSettings.KEY_INSTANT_HOTSPOT);
}
@Test
public void getNonIndexableKeys_hotspotNotAvailable_keysReturned() {
when(mWifiRestriction.isTetherAvailable(mContext)).thenReturn(true);
when(mWifiRestriction.isHotspotAvailable(mContext)).thenReturn(false);
WifiTetherSettings.SearchIndexProvider searchIndexProvider =
new WifiTetherSettings.SearchIndexProvider(XML_RES, mWifiRestriction,
true /* isInstantHotspotEnabled */);
final List<String> keys = searchIndexProvider.getNonIndexableKeys(mContext);
assertThat(keys).contains(WifiTetherSettings.KEY_WIFI_TETHER_NETWORK_NAME);
assertThat(keys).contains(WifiTetherSettings.KEY_WIFI_TETHER_SECURITY);
assertThat(keys).contains(WifiTetherSettings.KEY_WIFI_TETHER_NETWORK_PASSWORD);
assertThat(keys).contains(WifiTetherSettings.KEY_WIFI_TETHER_AUTO_OFF);
assertThat(keys).contains(WifiTetherSettings.KEY_WIFI_TETHER_MAXIMIZE_COMPATIBILITY);
assertThat(keys).contains(WifiTetherSettings.KEY_INSTANT_HOTSPOT);
}
@Test
public void getNonIndexableKeys_tetherAndHotspotNotAvailable_keysReturned() {
when(mWifiRestriction.isTetherAvailable(mContext)).thenReturn(false);
when(mWifiRestriction.isHotspotAvailable(mContext)).thenReturn(false);
WifiTetherSettings.SearchIndexProvider searchIndexProvider =
new WifiTetherSettings.SearchIndexProvider(XML_RES, mWifiRestriction,
true /* isInstantHotspotEnabled */);
final List<String> keys = searchIndexProvider.getNonIndexableKeys(mContext);
assertThat(keys).contains(WifiTetherSettings.KEY_WIFI_TETHER_NETWORK_NAME);
assertThat(keys).contains(WifiTetherSettings.KEY_WIFI_TETHER_SECURITY);
assertThat(keys).contains(WifiTetherSettings.KEY_WIFI_TETHER_NETWORK_PASSWORD);
assertThat(keys).contains(WifiTetherSettings.KEY_WIFI_TETHER_AUTO_OFF);
assertThat(keys).contains(WifiTetherSettings.KEY_WIFI_TETHER_MAXIMIZE_COMPATIBILITY);
}
@Test
public void getNonIndexableKeys_instantHotspotNotAvailableOnly_keysContainInstantHotspotOnly() {
when(mWifiRestriction.isTetherAvailable(mContext)).thenReturn(true);
when(mWifiRestriction.isHotspotAvailable(mContext)).thenReturn(true);
WifiTetherSettings.SearchIndexProvider searchIndexProvider =
new WifiTetherSettings.SearchIndexProvider(XML_RES, mWifiRestriction,
false /* isInstantHotspotEnabled */);
final List<String> keys = searchIndexProvider.getNonIndexableKeys(mContext);
assertThat(keys).doesNotContain(WifiTetherSettings.KEY_WIFI_TETHER_NETWORK_NAME);
assertThat(keys).doesNotContain(WifiTetherSettings.KEY_WIFI_TETHER_SECURITY);
assertThat(keys).doesNotContain(WifiTetherSettings.KEY_WIFI_TETHER_NETWORK_PASSWORD);
assertThat(keys).doesNotContain(WifiTetherSettings.KEY_WIFI_TETHER_AUTO_OFF);
assertThat(keys).doesNotContain(WifiTetherSettings.KEY_WIFI_TETHER_MAXIMIZE_COMPATIBILITY);
assertThat(keys).contains(WifiTetherSettings.KEY_INSTANT_HOTSPOT);
// contains
assertThat(keys).contains(WifiTetherSettings.KEY_WIFI_HOTSPOT_SECURITY);
assertThat(keys).contains(WifiTetherSettings.KEY_WIFI_HOTSPOT_SPEED);
}
@Test
@@ -506,6 +529,18 @@ public class WifiTetherSettingsTest {
mSettings.onCreate(Bundle.EMPTY);
}
private WifiTetherSettings.SearchIndexProvider createSearchIndexProvider(
boolean isTetherAvailable, boolean isHotspotAvailable, boolean isInstantHotspotEnabled,
boolean isSpeedFeatureAvailable) {
when(mWifiRestriction.isTetherAvailable(mContext)).thenReturn(isTetherAvailable);
when(mWifiRestriction.isHotspotAvailable(mContext)).thenReturn(isHotspotAvailable);
WifiTetherSettings.SearchIndexProvider provider =
spy(new WifiTetherSettings.SearchIndexProvider(XML_RES, mWifiRestriction,
isInstantHotspotEnabled));
when(provider.isSpeedFeatureAvailable()).thenReturn(isSpeedFeatureAvailable);
return provider;
}
@Implements(RestrictedDashboardFragment.class)
public static final class ShadowRestrictedDashboardFragment {

View File

@@ -20,15 +20,33 @@ import static android.os.UserManager.DISALLOW_ADD_WIFI_CONFIG;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.anyString;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.mock;
import android.content.Context;
import android.content.Intent;
import android.os.UserManager;
import android.platform.test.annotations.DisableFlags;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
import androidx.test.annotation.UiThreadTest;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.settings.flags.Flags;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.wifi.factory.WifiFeatureProvider;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -44,18 +62,36 @@ public class WifiDppConfiguratorActivityTest {
@Rule
public final MockitoRule mMockitoRule = MockitoJUnit.rule();
@Rule
public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
@Spy
private final Context mContext = ApplicationProvider.getApplicationContext();
@Mock
private UserManager mUserManager;
@Mock
private FragmentManager mFragmentManager;
// Mock, created by FakeFeatureFactory
private WifiFeatureProvider mWifiFeatureProviderMock;
@Spy
private WifiDppConfiguratorActivity mActivity;
@Before
public void setUp() {
when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager);
mActivity = new WifiDppConfiguratorActivity();
mActivity.mFragmentManager = mFragmentManager;
doReturn(mContext).when(mActivity).getApplicationContext();
FragmentTransaction mockTransaction = mock(FragmentTransaction.class);
when(mFragmentManager.beginTransaction()).thenReturn(mockTransaction);
when(mockTransaction.replace(anyInt(), any(Fragment.class), anyString()))
.thenReturn(mockTransaction);
FakeFeatureFactory featureFactory = FakeFeatureFactory.setupForTest();
mWifiFeatureProviderMock = featureFactory.mWifiFeatureProvider;
}
@Test
@@ -71,4 +107,37 @@ public class WifiDppConfiguratorActivityTest {
assertThat(mActivity.isAddWifiConfigAllowed(mContext)).isFalse();
}
@Test
@EnableFlags(Flags.FLAG_ENABLE_WIFI_SHARING_RUNTIME_FRAGMENT)
public void showQrCodeGeneratorFragment_shouldUseFeatureFactory() {
when(mUserManager.isGuestUser()).thenReturn(false);
when(mWifiFeatureProviderMock.getWifiDppQrCodeGeneratorFragment())
.thenReturn(new WifiDppQrCodeGeneratorFragment());
mActivity.handleIntent(createQrCodeGeneratorIntent());
verify(mWifiFeatureProviderMock).getWifiDppQrCodeGeneratorFragment();
}
@Test
@DisableFlags(Flags.FLAG_ENABLE_WIFI_SHARING_RUNTIME_FRAGMENT)
public void showQrCodeGeneratorFragment_shouldNotUseFeatureFactory() {
when(mUserManager.isGuestUser()).thenReturn(false);
mActivity.handleIntent(createQrCodeGeneratorIntent());
verify(mWifiFeatureProviderMock, never())
.getWifiDppQrCodeGeneratorFragment();
}
private static Intent createQrCodeGeneratorIntent() {
Intent intent = new Intent(
WifiDppConfiguratorActivity.ACTION_CONFIGURATOR_QR_CODE_GENERATOR);
intent.putExtra(WifiDppUtils.EXTRA_WIFI_SSID, "GoogleGuest");
intent.putExtra(WifiDppUtils.EXTRA_WIFI_SECURITY, "WPA");
intent.putExtra(WifiDppUtils.EXTRA_WIFI_PRE_SHARED_KEY, "\\012345678,");
return intent;
}
}