Merge "Hide new Hotspot preferences if feature is disabled" into main
diff --git a/res/drawable/battery_tips_all_rounded_bg.xml b/res/drawable/battery_tips_all_rounded_bg.xml
deleted file mode 100644
index ba164b9..0000000
--- a/res/drawable/battery_tips_all_rounded_bg.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2023 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.
- -->
-
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="rectangle">
- <solid android:color="@color/settingslib_materialColorSurfaceBright" />
- <corners android:radius="@dimen/battery_tips_card_corner_radius_normal" />
-</shape>
\ No newline at end of file
diff --git a/res/drawable/battery_tips_all_rounded_bg_ripple.xml b/res/drawable/battery_tips_all_rounded_bg_ripple.xml
deleted file mode 100644
index 3180570..0000000
--- a/res/drawable/battery_tips_all_rounded_bg_ripple.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2023 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.
- -->
-
-<ripple xmlns:android="http://schemas.android.com/apk/res/android"
- android:color="?android:attr/colorControlHighlight">
- <item android:drawable="@drawable/battery_tips_all_rounded_bg"/>
-</ripple>
\ No newline at end of file
diff --git a/res/drawable/battery_tips_half_rounded_bottom_bg.xml b/res/drawable/battery_tips_half_rounded_bottom_bg.xml
deleted file mode 100644
index 7766de6..0000000
--- a/res/drawable/battery_tips_half_rounded_bottom_bg.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2023 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.
- -->
-
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="rectangle">
- <solid android:color="@color/settingslib_dialog_background"/>
- <corners
- android:topLeftRadius="@dimen/battery_tips_card_corner_radius_small"
- android:topRightRadius="@dimen/battery_tips_card_corner_radius_small"
- android:bottomLeftRadius="@dimen/battery_tips_card_corner_radius_normal"
- android:bottomRightRadius="@dimen/battery_tips_card_corner_radius_normal"
- />
-</shape>
\ No newline at end of file
diff --git a/res/drawable/battery_tips_half_rounded_top_bg.xml b/res/drawable/battery_tips_half_rounded_top_bg.xml
deleted file mode 100644
index aba1a4f..0000000
--- a/res/drawable/battery_tips_half_rounded_top_bg.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2023 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.
- -->
-
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="rectangle">
- <solid android:color="@color/settingslib_dialog_background"/>
- <corners
- android:topLeftRadius="@dimen/battery_tips_card_corner_radius_normal"
- android:topRightRadius="@dimen/battery_tips_card_corner_radius_normal"
- android:bottomLeftRadius="@dimen/battery_tips_card_corner_radius_small"
- android:bottomRightRadius="@dimen/battery_tips_card_corner_radius_small"
- />
-</shape>
\ No newline at end of file
diff --git a/res/layout/battery_tips_card.xml b/res/layout/battery_tips_card.xml
deleted file mode 100644
index 18c326f..0000000
--- a/res/layout/battery_tips_card.xml
+++ /dev/null
@@ -1,61 +0,0 @@
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto"
- android:id="@+id/battery_tips_card"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginStart="?android:attr/listPreferredItemPaddingStart"
- android:layout_marginEnd="?android:attr/listPreferredItemPaddingEnd"
- android:background="@drawable/battery_tips_all_rounded_bg_ripple"
- android:orientation="vertical"
- android:padding="20dp">
-
- <ImageView
- android:id="@+id/icon"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center_vertical|start"
- android:contentDescription="@string/battery_usage_anomaly_content_description"
- android:src="@drawable/ic_battery_tips_lightbulb" />
-
- <TextView
- android:id="@+id/title"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="8dp"
- android:textAlignment="viewStart"
- android:textAppearance="@style/TextAppearance.Material3.TitleMedium"
- android:textColor="@color/settingslib_materialColorOnSurface" />
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="8dp"
- android:gravity="end"
- android:orientation="horizontal">
-
- <com.google.android.material.button.MaterialButton
- android:id="@+id/dismiss_button"
- style="@style/Widget.Material3.Button.TextButton"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="end|center_vertical"
- android:layout_marginEnd="8dp"
- android:paddingHorizontal="16dp"
- android:text="@string/battery_tips_card_dismiss_button"
- android:textAppearance="@style/TextAppearance.MaterialComponents.Subtitle2"
- android:textColor="@color/color_accent_selector" />
-
- <com.google.android.material.button.MaterialButton
- android:id="@+id/main_button"
- style="@style/Widget.Material3.Button"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="end|center_vertical"
- android:paddingHorizontal="16dp"
- android:text="@string/battery_tips_card_action_button"
- android:textAppearance="@style/TextAppearance.MaterialComponents.Subtitle2"
- android:textColor="@color/settingslib_materialColorOnPrimary"
- app:backgroundTint="@color/color_accent_selector" />
- </LinearLayout>
-</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/dialog_custom_body_audio_sharing.xml b/res/layout/dialog_custom_body_audio_sharing.xml
index 528bfbb..ba7f643 100644
--- a/res/layout/dialog_custom_body_audio_sharing.xml
+++ b/res/layout/dialog_custom_body_audio_sharing.xml
@@ -44,6 +44,7 @@
android:layout_height="wrap_content"
android:layout_gravity="center"
android:contentDescription="@null"
+ android:paddingBottom="24dp"
android:visibility="gone" />
<androidx.recyclerview.widget.RecyclerView
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 1d60218..6c018c2 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -937,7 +937,7 @@
<!-- Message showing that multiple fingerprints, face, and the current watch is set up. Shown for a menu item that launches fingerprint, face, and active unlock settings or enrollment. [CHAR LIMIT=80]-->
<string name="security_settings_fingerprint_multiple_face_watch_preference_summary">Face, fingerprints, and <xliff:g id="watch" example="Dani's Watch">%s</xliff:g> added</string>
<!-- Description for mandatory biometrics prompt-->
- <string name="mandatory_biometrics_prompt_description">This is needed since Identity Check is on</string>
+ <string name="mandatory_biometrics_prompt_description">Identity Check is on</string>
<!-- RemoteAuth unlock enrollment and settings --><skip />
<!-- Title shown for menu item that launches watch unlock settings. [CHAR LIMIT=40] -->
<string name ="security_settings_remoteauth_preference_title">Remote Authenticator Unlock</string>
diff --git a/res/xml/mobile_network_settings.xml b/res/xml/mobile_network_settings.xml
index 539c145..eb80ac8 100644
--- a/res/xml/mobile_network_settings.xml
+++ b/res/xml/mobile_network_settings.xml
@@ -152,6 +152,7 @@
android:summary="@string/contact_discovery_opt_in_summary"
settings:controller="com.android.settings.network.telephony.ContactDiscoveryPreferenceController"/>
+ <!-- Settings search is handled by PreferredNetworkModeSearchItem. -->
<ListPreference
android:key="preferred_network_mode_key"
android:title="@string/preferred_network_mode_title"
@@ -159,8 +160,10 @@
android:entries="@array/preferred_network_mode_choices"
android:entryValues="@array/preferred_network_mode_values"
android:dialogTitle="@string/preferred_network_mode_dialogtitle"
+ settings:searchable="false"
settings:controller="com.android.settings.network.telephony.PreferredNetworkModePreferenceController"/>
+ <!-- Settings search is handled by EnabledNetworkModeSearchItem. -->
<ListPreference
android:key="enabled_networks_key"
android:title="@string/preferred_network_mode_title"
@@ -168,6 +171,7 @@
android:entries="@array/enabled_networks_choices"
android:entryValues="@array/enabled_networks_values"
android:dialogTitle="@string/preferred_network_mode_dialogtitle"
+ settings:searchable="false"
settings:controller="com.android.settings.network.telephony.EnabledNetworkModePreferenceController"/>
<Preference
diff --git a/res/xml/power_usage_advanced.xml b/res/xml/power_usage_advanced.xml
index c129453..f0104e5 100644
--- a/res/xml/power_usage_advanced.xml
+++ b/res/xml/power_usage_advanced.xml
@@ -27,7 +27,7 @@
"com.android.settings.fuelgauge.batteryusage.BatteryTipsController"
settings:isPreferenceVisible="false">
- <com.android.settings.fuelgauge.batteryusage.BatteryTipsCardPreference
+ <com.android.settings.widget.TipCardPreference
android:key="battery_tips_card"
settings:isPreferenceVisible="false" />
diff --git a/src/com/android/settings/accessibility/ScreenFlashNotificationColorDialogFragment.java b/src/com/android/settings/accessibility/ScreenFlashNotificationColorDialogFragment.java
index 5094154..2be843c 100644
--- a/src/com/android/settings/accessibility/ScreenFlashNotificationColorDialogFragment.java
+++ b/src/com/android/settings/accessibility/ScreenFlashNotificationColorDialogFragment.java
@@ -28,11 +28,13 @@
import android.graphics.Color;
import android.os.Bundle;
import android.os.UserHandle;
+import android.provider.Settings;
import android.view.View;
import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.DialogFragment;
@@ -40,8 +42,6 @@
import java.util.Timer;
import java.util.TimerTask;
-import java.util.function.Consumer;
-
/**
* DialogFragment for Screen flash notification color picker.
@@ -49,29 +49,33 @@
public class ScreenFlashNotificationColorDialogFragment extends DialogFragment implements
ColorSelectorLayout.OnCheckedChangeListener {
+ private static final int DEFAULT_COLOR = Color.TRANSPARENT;
private static final int PREVIEW_LONG_TIME_MS = 5000;
private static final int BETWEEN_STOP_AND_START_DELAY_MS = 250;
private static final int MARGIN_FOR_STOP_DELAY_MS = 100;
+ @VisibleForTesting
+ static final String EXTRA_COLOR = "extra_color";
@ColorInt
- private int mCurrentColor = Color.TRANSPARENT;
- private Consumer<Integer> mConsumer;
+ private int mCurrentColor = DEFAULT_COLOR;
private Timer mTimer = null;
private Boolean mIsPreview = false;
- static ScreenFlashNotificationColorDialogFragment getInstance(int initialColor,
- Consumer<Integer> colorConsumer) {
+ static ScreenFlashNotificationColorDialogFragment getInstance(int initialColor) {
final ScreenFlashNotificationColorDialogFragment result =
new ScreenFlashNotificationColorDialogFragment();
- result.mCurrentColor = initialColor;
- result.mConsumer = colorConsumer != null ? colorConsumer : i -> {};
+ Bundle bundle = new Bundle();
+ bundle.putInt(EXTRA_COLOR, initialColor);
+ result.setArguments(bundle);
return result;
}
@NonNull
@Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
+ mCurrentColor = getArguments().getInt(EXTRA_COLOR, DEFAULT_COLOR);
+
final View dialogView = getLayoutInflater().inflate(R.layout.layout_color_selector_dialog,
null);
@@ -90,7 +94,8 @@
})
.setPositiveButton(R.string.color_selector_dialog_save, (dialog, which) -> {
mCurrentColor = colorSelectorLayout.getCheckedColor(DEFAULT_SCREEN_FLASH_COLOR);
- mConsumer.accept(mCurrentColor);
+ Settings.System.putInt(getContext().getContentResolver(),
+ Settings.System.SCREEN_FLASH_NOTIFICATION_COLOR, mCurrentColor);
})
.create();
createdDialog.setOnShowListener(
diff --git a/src/com/android/settings/accessibility/ScreenFlashNotificationPreferenceController.java b/src/com/android/settings/accessibility/ScreenFlashNotificationPreferenceController.java
index bd54aca..3ebcd1c 100644
--- a/src/com/android/settings/accessibility/ScreenFlashNotificationPreferenceController.java
+++ b/src/com/android/settings/accessibility/ScreenFlashNotificationPreferenceController.java
@@ -21,10 +21,17 @@
import static com.android.settings.accessibility.FlashNotificationsUtil.DEFAULT_SCREEN_FLASH_COLOR;
import android.content.Context;
+import android.database.ContentObserver;
import android.graphics.Color;
+import android.net.Uri;
+import android.os.Handler;
import android.provider.Settings;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
+import androidx.lifecycle.DefaultLifecycleObserver;
+import androidx.lifecycle.LifecycleOwner;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
@@ -32,18 +39,21 @@
import com.android.settings.core.TogglePreferenceController;
import com.android.settings.overlay.FeatureFactory;
-import java.util.function.Consumer;
-
/**
* Controller for Screen flash notification.
*/
-public class ScreenFlashNotificationPreferenceController extends TogglePreferenceController {
+public class ScreenFlashNotificationPreferenceController extends
+ TogglePreferenceController implements DefaultLifecycleObserver {
+
+ private final FlashNotificationColorContentObserver mFlashNotificationColorContentObserver;
private Fragment mParentFragment;
private Preference mPreference;
public ScreenFlashNotificationPreferenceController(Context context, String preferenceKey) {
super(context, preferenceKey);
+ mFlashNotificationColorContentObserver = new FlashNotificationColorContentObserver(
+ new Handler(mContext.getMainLooper()));
}
public void setParentFragment(Fragment parentFragment) {
@@ -51,6 +61,16 @@
}
@Override
+ public void onStart(@NonNull LifecycleOwner owner) {
+ mFlashNotificationColorContentObserver.register(mContext);
+ }
+
+ @Override
+ public void onStop(@NonNull LifecycleOwner owner) {
+ mFlashNotificationColorContentObserver.unregister(mContext);
+ }
+
+ @Override
public int getAvailabilityStatus() {
return AVAILABLE;
}
@@ -100,14 +120,8 @@
Settings.System.SCREEN_FLASH_NOTIFICATION_COLOR,
DEFAULT_SCREEN_FLASH_COLOR);
- final Consumer<Integer> consumer = color -> {
- Settings.System.putInt(mContext.getContentResolver(),
- Settings.System.SCREEN_FLASH_NOTIFICATION_COLOR, color);
- refreshColorSummary();
- };
-
ScreenFlashNotificationColorDialogFragment
- .getInstance(initialColor, consumer)
+ .getInstance(initialColor)
.show(mParentFragment.getParentFragmentManager(),
ScreenFlashNotificationColorDialogFragment.class.getSimpleName());
return true;
@@ -128,4 +142,37 @@
private void refreshColorSummary() {
if (mPreference != null) mPreference.setSummary(getSummary());
}
+
+ private final class FlashNotificationColorContentObserver extends ContentObserver {
+ private final Uri mColorUri = Settings.System.getUriFor(
+ Settings.System.SCREEN_FLASH_NOTIFICATION_COLOR);
+
+ FlashNotificationColorContentObserver(Handler handler) {
+ super(handler);
+ }
+
+ /**
+ * Register this observer to given {@link Context}, to be called from lifecycle
+ * {@code onStart} method.
+ */
+ public void register(@NonNull Context context) {
+ context.getContentResolver().registerContentObserver(
+ mColorUri, /* notifyForDescendants= */ false, this);
+ }
+
+ /**
+ * Unregister this observer from given {@link Context}, to be called from lifecycle
+ * {@code onStop} method.
+ */
+ public void unregister(@NonNull Context context) {
+ context.getContentResolver().unregisterContentObserver(this);
+ }
+
+ @Override
+ public void onChange(boolean selfChange, @Nullable Uri uri) {
+ if (mColorUri.equals(uri)) {
+ refreshColorSummary();
+ }
+ }
+ }
}
diff --git a/src/com/android/settings/accessibility/shortcuts/EditShortcutsPreferenceFragment.java b/src/com/android/settings/accessibility/shortcuts/EditShortcutsPreferenceFragment.java
index bdf7857..d04b34a 100644
--- a/src/com/android/settings/accessibility/shortcuts/EditShortcutsPreferenceFragment.java
+++ b/src/com/android/settings/accessibility/shortcuts/EditShortcutsPreferenceFragment.java
@@ -20,6 +20,7 @@
import static android.provider.Settings.Secure.ACCESSIBILITY_BUTTON_MODE;
import static android.provider.Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS;
import static android.provider.Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED;
+import static android.provider.Settings.Secure.ACCESSIBILITY_GESTURE_TARGETS;
import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_TWO_FINGER_TRIPLE_TAP_ENABLED;
import static android.provider.Settings.Secure.ACCESSIBILITY_QS_TARGETS;
import static android.provider.Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE;
@@ -93,7 +94,8 @@
Settings.Secure.getUriFor(ACCESSIBILITY_BUTTON_MODE);
private static final Uri BUTTON_SHORTCUT_SETTING =
Settings.Secure.getUriFor(ACCESSIBILITY_BUTTON_TARGETS);
-
+ private static final Uri GESTURE_SHORTCUT_SETTING =
+ Settings.Secure.getUriFor(ACCESSIBILITY_GESTURE_TARGETS);
private static final Uri TRIPLE_TAP_SHORTCUT_SETTING =
Settings.Secure.getUriFor(ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED);
private static final Uri TWO_FINGERS_DOUBLE_TAP_SHORTCUT_SETTING =
@@ -107,6 +109,7 @@
VOLUME_KEYS_SHORTCUT_SETTING,
BUTTON_SHORTCUT_MODE_SETTING,
BUTTON_SHORTCUT_SETTING,
+ GESTURE_SHORTCUT_SETTING,
TRIPLE_TAP_SHORTCUT_SETTING,
TWO_FINGERS_DOUBLE_TAP_SHORTCUT_SETTING,
QUICK_SETTINGS_SHORTCUT_SETTING,
@@ -173,6 +176,8 @@
} else if (BUTTON_SHORTCUT_MODE_SETTING.equals(uri)
|| BUTTON_SHORTCUT_SETTING.equals(uri)) {
refreshSoftwareShortcutControllers();
+ } else if (GESTURE_SHORTCUT_SETTING.equals(uri)) {
+ refreshPreferenceController(GestureShortcutOptionController.class);
} else if (TRIPLE_TAP_SHORTCUT_SETTING.equals(uri)) {
refreshPreferenceController(TripleTapShortcutOptionController.class);
} else if (TWO_FINGERS_DOUBLE_TAP_SHORTCUT_SETTING.equals(uri)) {
diff --git a/src/com/android/settings/accessibility/shortcuts/FloatingButtonShortcutOptionController.java b/src/com/android/settings/accessibility/shortcuts/FloatingButtonShortcutOptionController.java
index 2242cab..20ff12d 100644
--- a/src/com/android/settings/accessibility/shortcuts/FloatingButtonShortcutOptionController.java
+++ b/src/com/android/settings/accessibility/shortcuts/FloatingButtonShortcutOptionController.java
@@ -50,7 +50,14 @@
@Override
protected boolean isShortcutAvailable() {
- return AccessibilityUtil.isFloatingMenuEnabled(mContext);
+ if (android.provider.Flags.a11yStandaloneGestureEnabled()) {
+ // FAB should be available when in gesture navigation mode,
+ // or if we're in the FAB button mode while in navbar navigation mode.
+ return AccessibilityUtil.isGestureNavigateEnabled(mContext)
+ || AccessibilityUtil.isFloatingMenuEnabled(mContext);
+ } else {
+ return AccessibilityUtil.isFloatingMenuEnabled(mContext);
+ }
}
@Nullable
diff --git a/src/com/android/settings/accessibility/shortcuts/GestureShortcutOptionController.java b/src/com/android/settings/accessibility/shortcuts/GestureShortcutOptionController.java
index e65aab9..3c19b5d 100644
--- a/src/com/android/settings/accessibility/shortcuts/GestureShortcutOptionController.java
+++ b/src/com/android/settings/accessibility/shortcuts/GestureShortcutOptionController.java
@@ -16,6 +16,8 @@
package com.android.settings.accessibility.shortcuts;
+import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.GESTURE;
+
import android.content.Context;
import android.text.SpannableStringBuilder;
@@ -52,10 +54,21 @@
}
@Override
+ protected int getShortcutType() {
+ return android.provider.Flags.a11yStandaloneGestureEnabled()
+ ? GESTURE : super.getShortcutType();
+ }
+
+ @Override
protected boolean isShortcutAvailable() {
- return !isInSetupWizard()
- && !AccessibilityUtil.isFloatingMenuEnabled(mContext)
- && AccessibilityUtil.isGestureNavigateEnabled(mContext);
+ if (android.provider.Flags.a11yStandaloneGestureEnabled()) {
+ return !isInSetupWizard()
+ && AccessibilityUtil.isGestureNavigateEnabled(mContext);
+ } else {
+ return !isInSetupWizard()
+ && AccessibilityUtil.isGestureNavigateEnabled(mContext)
+ && !AccessibilityUtil.isFloatingMenuEnabled(mContext);
+ }
}
@Override
@@ -68,9 +81,8 @@
final SpannableStringBuilder sb = new SpannableStringBuilder();
sb.append(instruction);
- if (!isInSetupWizard()) {
- sb.append("\n\n");
- sb.append(getCustomizeAccessibilityButtonLink());
+ if (!isInSetupWizard() && !android.provider.Flags.a11yStandaloneGestureEnabled()) {
+ sb.append("\n\n").append(getCustomizeAccessibilityButtonLink());
}
return sb;
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java b/src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java
index 65d9366..526ae8f6 100644
--- a/src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java
@@ -42,6 +42,8 @@
import android.os.Handler;
import android.os.UserHandle;
import android.os.UserManager;
+import android.os.VibrationEffect;
+import android.os.Vibrator;
import android.text.InputFilter;
import android.text.Spanned;
import android.text.TextUtils;
@@ -109,6 +111,9 @@
private static final int RESULT_FINISHED = BiometricEnrollBase.RESULT_FINISHED;
private static final int RESULT_SKIP = BiometricEnrollBase.RESULT_SKIP;
private static final int RESULT_TIMEOUT = BiometricEnrollBase.RESULT_TIMEOUT;
+ @VisibleForTesting
+ static final VibrationEffect SUCCESS_VIBRATION_EFFECT =
+ VibrationEffect.get(VibrationEffect.EFFECT_CLICK);
@Override
public Intent getIntent() {
@@ -285,6 +290,7 @@
private FingerprintAuthenticateSidecar mAuthenticateSidecar;
private FingerprintRemoveSidecar mRemovalSidecar;
private HashMap<Integer, String> mFingerprintsRenaming;
+ private Vibrator mVibrator;
@Nullable
private UdfpsEnrollCalibrator mCalibrator;
@@ -367,8 +373,8 @@
break;
case MSG_FINGER_AUTH_HELP: {
// Not used
+ break;
}
- break;
}
}
};
@@ -511,6 +517,7 @@
addFirstFingerprint(null);
}
}
+ mVibrator = getContext().getSystemService(Vibrator.class);
final PreferenceScreen root = getPreferenceScreen();
root.removeAll();
addPreferencesFromResource(getPreferenceScreenResId());
@@ -1095,6 +1102,7 @@
}
private void highlightFingerprintItem(int fpId) {
+ mVibrator.vibrate(SUCCESS_VIBRATION_EFFECT);
String prefName = genKey(fpId);
FingerprintPreference fpref = (FingerprintPreference) findPreference(prefName);
final Drawable highlight = getHighlightDrawable();
diff --git a/src/com/android/settings/bluetooth/BluetoothDetailsProfilesController.java b/src/com/android/settings/bluetooth/BluetoothDetailsProfilesController.java
index 2b74684..0897a43 100644
--- a/src/com/android/settings/bluetooth/BluetoothDetailsProfilesController.java
+++ b/src/com/android/settings/bluetooth/BluetoothDetailsProfilesController.java
@@ -89,7 +89,7 @@
private LocalBluetoothManager mManager;
private LocalBluetoothProfileManager mProfileManager;
private CachedBluetoothDevice mCachedDevice;
- private List<CachedBluetoothDevice> mAllOfCachedDevices;
+ private Set<CachedBluetoothDevice> mCachedDeviceGroup;
private Map<String, List<CachedBluetoothDevice>> mProfileDeviceMap =
new HashMap<String, List<CachedBluetoothDevice>>();
private boolean mIsLeContactSharingEnabled = false;
@@ -105,7 +105,7 @@
mManager = manager;
mProfileManager = mManager.getProfileManager();
mCachedDevice = device;
- mAllOfCachedDevices = Utils.getAllOfCachedBluetoothDevices(mManager, mCachedDevice);
+ mCachedDeviceGroup = Utils.findAllCachedBluetoothDevicesByGroupId(mManager, mCachedDevice);
}
@Override
@@ -310,10 +310,10 @@
private List<LocalBluetoothProfile> getProfiles() {
List<LocalBluetoothProfile> result = new ArrayList<>();
mProfileDeviceMap.clear();
- if (mAllOfCachedDevices == null || mAllOfCachedDevices.isEmpty()) {
+ if (mCachedDeviceGroup == null || mCachedDeviceGroup.isEmpty()) {
return result;
}
- for (CachedBluetoothDevice cachedItem : mAllOfCachedDevices) {
+ for (CachedBluetoothDevice cachedItem : mCachedDeviceGroup) {
List<LocalBluetoothProfile> tmpResult = cachedItem.getUiAccessibleProfiles();
for (LocalBluetoothProfile profile : tmpResult) {
if (mProfileDeviceMap.containsKey(profile.toString())) {
@@ -514,7 +514,7 @@
@Override
public void onPause() {
- for (CachedBluetoothDevice item : mAllOfCachedDevices) {
+ for (CachedBluetoothDevice item : mCachedDeviceGroup) {
item.unregisterCallback(this);
}
mProfileManager.removeServiceListener(this);
@@ -523,7 +523,7 @@
@Override
public void onResume() {
updateLeAudioConfig();
- for (CachedBluetoothDevice item : mAllOfCachedDevices) {
+ for (CachedBluetoothDevice item : mCachedDeviceGroup) {
item.registerCallback(this);
}
mProfileManager.addServiceListener(this);
@@ -545,11 +545,11 @@
@Override
public void onDeviceAttributesChanged() {
- for (CachedBluetoothDevice item : mAllOfCachedDevices) {
+ for (CachedBluetoothDevice item : mCachedDeviceGroup) {
item.unregisterCallback(this);
}
- mAllOfCachedDevices = Utils.getAllOfCachedBluetoothDevices(mManager, mCachedDevice);
- for (CachedBluetoothDevice item : mAllOfCachedDevices) {
+ mCachedDeviceGroup = Utils.findAllCachedBluetoothDevicesByGroupId(mManager, mCachedDevice);
+ for (CachedBluetoothDevice item : mCachedDeviceGroup) {
item.registerCallback(this);
}
diff --git a/src/com/android/settings/bluetooth/BluetoothDevicePreference.java b/src/com/android/settings/bluetooth/BluetoothDevicePreference.java
index ac0c63b..209c900 100644
--- a/src/com/android/settings/bluetooth/BluetoothDevicePreference.java
+++ b/src/com/android/settings/bluetooth/BluetoothDevicePreference.java
@@ -46,6 +46,7 @@
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.widget.GearPreference;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
+import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
import com.android.settingslib.utils.ThreadUtils;
@@ -55,6 +56,7 @@
import java.util.Set;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.atomic.AtomicInteger;
+import java.util.stream.Collectors;
/**
* BluetoothDevicePreference is the preference type used to display each remote
@@ -76,7 +78,10 @@
}
private final CachedBluetoothDevice mCachedDevice;
+ private Set<CachedBluetoothDevice> mCachedDeviceGroup;
+
private final UserManager mUserManager;
+ private final LocalBluetoothManager mLocalBtManager;
private Set<BluetoothDevice> mBluetoothDevices;
@VisibleForTesting
@@ -113,6 +118,21 @@
@Override
public void onDeviceAttributesChanged() {
onPreferenceAttributesChanged();
+ Set<CachedBluetoothDevice> newCachedDeviceGroup = new HashSet<>(
+ Utils.findAllCachedBluetoothDevicesByGroupId(mLocalBtManager, mCachedDevice));
+ if (!mCachedDeviceGroup.equals(newCachedDeviceGroup)) {
+ for (CachedBluetoothDevice cachedBluetoothDevice : mCachedDeviceGroup) {
+ cachedBluetoothDevice.unregisterCallback(this);
+ }
+ unregisterMetadataChangedListener();
+
+ mCachedDeviceGroup = newCachedDeviceGroup;
+
+ for (CachedBluetoothDevice cachedBluetoothDevice : mCachedDeviceGroup) {
+ cachedBluetoothDevice.registerCallback(getContext().getMainExecutor(), this);
+ }
+ registerMetadataChangedListener();
+ }
}
}
@@ -121,6 +141,7 @@
super(context, null);
mResources = getContext().getResources();
mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
+ mLocalBtManager = Utils.getLocalBluetoothManager(context);
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
mShowDevicesWithoutNames = showDeviceWithoutNames;
@@ -131,6 +152,8 @@
}
mCachedDevice = cachedDevice;
+ mCachedDeviceGroup = new HashSet<>(
+ Utils.findAllCachedBluetoothDevicesByGroupId(mLocalBtManager, mCachedDevice));
mCallback = new BluetoothDevicePreferenceCallback();
mId = sNextId.getAndIncrement();
mType = type;
@@ -164,7 +187,9 @@
protected void onPrepareForRemoval() {
super.onPrepareForRemoval();
if (!mIsCallbackRemoved) {
- mCachedDevice.unregisterCallback(mCallback);
+ for (CachedBluetoothDevice cachedBluetoothDevice : mCachedDeviceGroup) {
+ cachedBluetoothDevice.unregisterCallback(mCallback);
+ }
unregisterMetadataChangedListener();
mIsCallbackRemoved = true;
}
@@ -178,7 +203,9 @@
public void onAttached() {
super.onAttached();
if (mIsCallbackRemoved) {
- mCachedDevice.registerCallback(mCallback);
+ for (CachedBluetoothDevice cachedBluetoothDevice : mCachedDeviceGroup) {
+ cachedBluetoothDevice.registerCallback(getContext().getMainExecutor(), mCallback);
+ }
registerMetadataChangedListener();
mIsCallbackRemoved = false;
}
@@ -189,7 +216,9 @@
public void onDetached() {
super.onDetached();
if (!mIsCallbackRemoved) {
- mCachedDevice.unregisterCallback(mCallback);
+ for (CachedBluetoothDevice cachedBluetoothDevice : mCachedDeviceGroup) {
+ cachedBluetoothDevice.unregisterCallback(mCallback);
+ }
unregisterMetadataChangedListener();
mIsCallbackRemoved = true;
}
@@ -200,16 +229,11 @@
Log.d(TAG, "No mBluetoothAdapter");
return;
}
- if (mBluetoothDevices == null) {
- mBluetoothDevices = new HashSet<>();
- }
- mBluetoothDevices.clear();
- if (mCachedDevice.getDevice() != null) {
- mBluetoothDevices.add(mCachedDevice.getDevice());
- }
- for (CachedBluetoothDevice cbd : mCachedDevice.getMemberDevice()) {
- mBluetoothDevices.add(cbd.getDevice());
- }
+
+ mBluetoothDevices = mCachedDeviceGroup.stream()
+ .map(CachedBluetoothDevice::getDevice)
+ .collect(Collectors.toCollection(HashSet::new));
+
if (mBluetoothDevices.isEmpty()) {
Log.d(TAG, "No BT device to register.");
return;
diff --git a/src/com/android/settings/bluetooth/LeAudioBluetoothDetailsHeaderController.java b/src/com/android/settings/bluetooth/LeAudioBluetoothDetailsHeaderController.java
index 4be4d63..a5e9cde 100644
--- a/src/com/android/settings/bluetooth/LeAudioBluetoothDetailsHeaderController.java
+++ b/src/com/android/settings/bluetooth/LeAudioBluetoothDetailsHeaderController.java
@@ -47,7 +47,7 @@
import com.android.settingslib.core.lifecycle.events.OnStop;
import com.android.settingslib.widget.LayoutPreference;
-import java.util.List;
+import java.util.Set;
/**
* This class adds a header with device name and status (connected/disconnected, etc.).
@@ -90,7 +90,7 @@
LayoutPreference mLayoutPreference;
LocalBluetoothManager mManager;
private CachedBluetoothDevice mCachedDevice;
- private List<CachedBluetoothDevice> mAllOfCachedDevices;
+ private Set<CachedBluetoothDevice> mCachedDeviceGroup;
@VisibleForTesting
Handler mHandler = new Handler(Looper.getMainLooper());
@VisibleForTesting
@@ -128,7 +128,7 @@
return;
}
mIsRegisterCallback = true;
- for (CachedBluetoothDevice item : mAllOfCachedDevices) {
+ for (CachedBluetoothDevice item : mCachedDeviceGroup) {
item.registerCallback(this);
}
refresh();
@@ -139,7 +139,7 @@
if (!mIsRegisterCallback) {
return;
}
- for (CachedBluetoothDevice item : mAllOfCachedDevices) {
+ for (CachedBluetoothDevice item : mCachedDeviceGroup) {
item.unregisterCallback(this);
}
@@ -155,7 +155,7 @@
mCachedDevice = cachedBluetoothDevice;
mManager = bluetoothManager;
mProfileManager = bluetoothManager.getProfileManager();
- mAllOfCachedDevices = Utils.getAllOfCachedBluetoothDevices(mManager, mCachedDevice);
+ mCachedDeviceGroup = Utils.findAllCachedBluetoothDevicesByGroupId(mManager, mCachedDevice);
}
@VisibleForTesting
@@ -230,7 +230,7 @@
// Init the battery layouts.
hideAllOfBatteryLayouts();
LeAudioProfile leAudioProfile = mProfileManager.getLeAudioProfile();
- if (mAllOfCachedDevices.isEmpty()) {
+ if (mCachedDeviceGroup.isEmpty()) {
Log.e(TAG, "There is no LeAudioProfile.");
return;
}
@@ -244,7 +244,7 @@
return;
}
- for (CachedBluetoothDevice cachedDevice : mAllOfCachedDevices) {
+ for (CachedBluetoothDevice cachedDevice : mCachedDeviceGroup) {
int deviceId = leAudioProfile.getAudioLocation(cachedDevice.getDevice());
Log.d(TAG, "LeAudioDevices:" + cachedDevice.getDevice().getAnonymizedAddress()
+ ", deviceId:" + deviceId);
@@ -300,15 +300,15 @@
@Override
public void onDeviceAttributesChanged() {
- for (CachedBluetoothDevice item : mAllOfCachedDevices) {
+ for (CachedBluetoothDevice item : mCachedDeviceGroup) {
item.unregisterCallback(this);
}
- mAllOfCachedDevices = Utils.getAllOfCachedBluetoothDevices(mManager, mCachedDevice);
- for (CachedBluetoothDevice item : mAllOfCachedDevices) {
+ mCachedDeviceGroup = Utils.findAllCachedBluetoothDevicesByGroupId(mManager, mCachedDevice);
+ for (CachedBluetoothDevice item : mCachedDeviceGroup) {
item.registerCallback(this);
}
- if (!mAllOfCachedDevices.isEmpty()) {
+ if (!mCachedDeviceGroup.isEmpty()) {
refresh();
}
}
diff --git a/src/com/android/settings/bluetooth/Utils.java b/src/com/android/settings/bluetooth/Utils.java
index f6288b2..b1d9de7 100644
--- a/src/com/android/settings/bluetooth/Utils.java
+++ b/src/com/android/settings/bluetooth/Utils.java
@@ -48,8 +48,9 @@
import com.google.common.base.Supplier;
-import java.util.ArrayList;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
@@ -239,12 +240,12 @@
* @param cachedBluetoothDevice The main cachedBluetoothDevice.
* @return all cachedBluetoothDevices with the same groupId.
*/
- public static List<CachedBluetoothDevice> getAllOfCachedBluetoothDevices(
+ public static Set<CachedBluetoothDevice> findAllCachedBluetoothDevicesByGroupId(
LocalBluetoothManager localBtMgr,
CachedBluetoothDevice cachedBluetoothDevice) {
- List<CachedBluetoothDevice> cachedBluetoothDevices = new ArrayList<>();
+ Set<CachedBluetoothDevice> cachedBluetoothDevices = new HashSet<>();
if (cachedBluetoothDevice == null) {
- Log.e(TAG, "getAllOfCachedBluetoothDevices: no cachedBluetoothDevice");
+ Log.e(TAG, "findAllCachedBluetoothDevicesByGroupId: no cachedBluetoothDevice");
return cachedBluetoothDevices;
}
int deviceGroupId = cachedBluetoothDevice.getGroupId();
@@ -254,7 +255,7 @@
}
if (localBtMgr == null) {
- Log.e(TAG, "getAllOfCachedBluetoothDevices: no LocalBluetoothManager");
+ Log.e(TAG, "findAllCachedBluetoothDevicesByGroupId: no LocalBluetoothManager");
return cachedBluetoothDevices;
}
CachedBluetoothDevice mainDevice =
@@ -262,16 +263,14 @@
.filter(cachedDevice -> cachedDevice.getGroupId() == deviceGroupId)
.findFirst().orElse(null);
if (mainDevice == null) {
- Log.e(TAG, "getAllOfCachedBluetoothDevices: groupId = " + deviceGroupId
+ Log.e(TAG, "findAllCachedBluetoothDevicesByGroupId: groupId = " + deviceGroupId
+ ", no main device.");
return cachedBluetoothDevices;
}
cachedBluetoothDevice = mainDevice;
cachedBluetoothDevices.add(cachedBluetoothDevice);
- for (CachedBluetoothDevice member : cachedBluetoothDevice.getMemberDevice()) {
- cachedBluetoothDevices.add(member);
- }
- Log.d(TAG, "getAllOfCachedBluetoothDevices: groupId = " + deviceGroupId
+ cachedBluetoothDevices.addAll(cachedBluetoothDevice.getMemberDevice());
+ Log.d(TAG, "findAllCachedBluetoothDevicesByGroupId: groupId = " + deviceGroupId
+ " , cachedBluetoothDevice = " + cachedBluetoothDevice
+ " , deviceList = " + cachedBluetoothDevices);
return cachedBluetoothDevices;
diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogFragment.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogFragment.java
index 6f62ed9..1ae541c 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogFragment.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogFragment.java
@@ -30,6 +30,9 @@
import androidx.fragment.app.FragmentManager;
import com.android.settings.R;
+import com.android.settings.bluetooth.BluetoothPairingDetail;
+import com.android.settings.connecteddevice.audiosharing.audiostreams.AudioStreamsQrCodeFragment;
+import com.android.settings.core.SubSettingLauncher;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
import com.android.settingslib.bluetooth.BluetoothUtils;
@@ -130,9 +133,27 @@
builder.setTitle(R.string.audio_sharing_share_dialog_title)
.setCustomImage(R.drawable.audio_sharing_guidance)
.setCustomMessage(R.string.audio_sharing_dialog_connect_device_content)
- .setNegativeButton(
- R.string.audio_sharing_close_button_label,
- (dig, which) -> onCancelClick());
+ .setCustomPositiveButton(
+ R.string.audio_sharing_pair_button_label,
+ v -> {
+ dismiss();
+ new SubSettingLauncher(getContext())
+ .setDestination(BluetoothPairingDetail.class.getName())
+ .setSourceMetricsCategory(getMetricsCategory())
+ .launch();
+ logDialogPositiveBtnClick();
+ })
+ .setCustomNegativeButton(
+ R.string.audio_sharing_qrcode_button_label,
+ v -> {
+ dismiss();
+ new SubSettingLauncher(getContext())
+ .setTitleRes(R.string.audio_streams_qr_code_page_title)
+ .setDestination(AudioStreamsQrCodeFragment.class.getName())
+ .setSourceMetricsCategory(getMetricsCategory())
+ .launch();
+ logDialogNegativeBtnClick();
+ });
} else if (deviceItems.size() == 1) {
AudioSharingDeviceItem deviceItem = Iterables.getOnlyElement(deviceItems);
builder.setTitle(
@@ -145,11 +166,7 @@
v -> {
if (sListener != null) {
sListener.onItemClick(deviceItem);
- mMetricsFeatureProvider.action(
- getContext(),
- SettingsEnums
- .ACTION_AUDIO_SHARING_DIALOG_POSITIVE_BTN_CLICKED,
- sEventData);
+ logDialogPositiveBtnClick();
}
dismiss();
})
@@ -165,6 +182,7 @@
(AudioSharingDeviceItem item) -> {
if (sListener != null) {
sListener.onItemClick(item);
+ logDialogPositiveBtnClick();
}
dismiss();
},
@@ -178,11 +196,22 @@
private void onCancelClick() {
if (sListener != null) {
sListener.onCancelClick();
- mMetricsFeatureProvider.action(
- getContext(),
- SettingsEnums.ACTION_AUDIO_SHARING_DIALOG_NEGATIVE_BTN_CLICKED,
- sEventData);
+ logDialogNegativeBtnClick();
}
dismiss();
}
+
+ private void logDialogPositiveBtnClick() {
+ mMetricsFeatureProvider.action(
+ getContext(),
+ SettingsEnums.ACTION_AUDIO_SHARING_DIALOG_POSITIVE_BTN_CLICKED,
+ sEventData);
+ }
+
+ private void logDialogNegativeBtnClick() {
+ mMetricsFeatureProvider.action(
+ getContext(),
+ SettingsEnums.ACTION_AUDIO_SHARING_DIALOG_NEGATIVE_BTN_CLICKED,
+ sEventData);
+ }
}
diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogHandler.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogHandler.java
index 4ee405d..14c19de 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogHandler.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogHandler.java
@@ -499,7 +499,7 @@
private void removeSourceForGroup(
int groupId, Map<Integer, List<BluetoothDevice>> groupedDevices) {
if (mAssistant == null) {
- Log.d(TAG, "Fail to add source due to null profiles, group = " + groupId);
+ Log.d(TAG, "Fail to remove source due to null profiles, group = " + groupId);
return;
}
if (!groupedDevices.containsKey(groupId)) {
diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingReceiver.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingReceiver.java
index b43a544..371613f 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingReceiver.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingReceiver.java
@@ -81,9 +81,15 @@
break;
case ACTION_LE_AUDIO_SHARING_STOP:
LocalBluetoothManager manager = Utils.getLocalBtManager(context);
- AudioSharingUtils.stopBroadcasting(manager);
- metricsFeatureProvider.action(
- context, SettingsEnums.ACTION_STOP_AUDIO_SHARING_FROM_NOTIFICATION);
+ if (BluetoothUtils.isBroadcasting(manager)) {
+ AudioSharingUtils.stopBroadcasting(manager);
+ metricsFeatureProvider.action(
+ context, SettingsEnums.ACTION_STOP_AUDIO_SHARING_FROM_NOTIFICATION);
+ } else {
+ cancelSharingNotification(context);
+ metricsFeatureProvider.action(
+ context, SettingsEnums.ACTION_CANCEL_AUDIO_SHARING_NOTIFICATION);
+ }
break;
default:
Log.w(TAG, "Received unexpected intent " + intent.getAction());
diff --git a/src/com/android/settings/datetime/AutoTimePreferenceController.java b/src/com/android/settings/datetime/AutoTimePreferenceController.java
index 434eba9..2942acb 100644
--- a/src/com/android/settings/datetime/AutoTimePreferenceController.java
+++ b/src/com/android/settings/datetime/AutoTimePreferenceController.java
@@ -39,6 +39,11 @@
public AutoTimePreferenceController(Context context, String preferenceKey) {
super(context, preferenceKey);
mTimeManager = context.getSystemService(TimeManager.class);
+ // This is a no-op implementation of UpdateTimeAndDateCallback to avoid a NPE when
+ // setTimeAndDateCallback() isn't called, e.g. for slices and other cases where the
+ // controller is instantiated outside of the context of the real Date & Time settings
+ // screen.
+ mCallback = (c) -> {};
}
public void setDateAndTimeCallback(UpdateTimeAndDateCallback callback) {
diff --git a/src/com/android/settings/datetime/AutoTimeZonePreferenceController.java b/src/com/android/settings/datetime/AutoTimeZonePreferenceController.java
index 011cc97..3a1f995 100644
--- a/src/com/android/settings/datetime/AutoTimeZonePreferenceController.java
+++ b/src/com/android/settings/datetime/AutoTimeZonePreferenceController.java
@@ -40,6 +40,11 @@
public AutoTimeZonePreferenceController(Context context, String preferenceKey) {
super(context, preferenceKey);
mTimeManager = context.getSystemService(TimeManager.class);
+ // This is a no-op implementation of UpdateTimeAndDateCallback to avoid a NPE when
+ // setTimeAndDateCallback() isn't called, e.g. for slices and other cases where the
+ // controller is instantiated outside of the context of the real Date & Time settings
+ // screen.
+ mCallback = (c) -> {};
}
/**
diff --git a/src/com/android/settings/datetime/TimeFormatPreferenceController.java b/src/com/android/settings/datetime/TimeFormatPreferenceController.java
index 22f7509..19805ad 100644
--- a/src/com/android/settings/datetime/TimeFormatPreferenceController.java
+++ b/src/com/android/settings/datetime/TimeFormatPreferenceController.java
@@ -43,6 +43,11 @@
public TimeFormatPreferenceController(Context context, String key) {
super(context, key);
mDummyDate = Calendar.getInstance();
+ // This is a no-op implementation of UpdateTimeAndDateCallback to avoid a NPE when
+ // setTimeAndDateCallback() isn't called, e.g. for slices and other cases where the
+ // controller is instantiated outside of the context of the real Date & Time settings
+ // screen.
+ mUpdateTimeAndDateCallback = (c) -> {};
}
/**
diff --git a/src/com/android/settings/fuelgauge/batteryusage/AnomalyEventWrapper.java b/src/com/android/settings/fuelgauge/batteryusage/AnomalyEventWrapper.java
index be5de06..c62728b 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/AnomalyEventWrapper.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/AnomalyEventWrapper.java
@@ -28,10 +28,11 @@
import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.core.SubSettingLauncher;
+import com.android.settings.widget.TipCardPreference;
import java.util.function.Function;
-final class AnomalyEventWrapper {
+class AnomalyEventWrapper {
private static final String TAG = "AnomalyEventWrapper";
private final Context mContext;
@@ -235,16 +236,16 @@
return mHighlightSlotPair;
}
- boolean updateTipsCardPreference(BatteryTipsCardPreference preference) {
+ boolean updateTipsCardPreference(TipCardPreference preference) {
final String titleString = getTitleString();
if (TextUtils.isEmpty(titleString)) {
return false;
}
preference.setTitle(titleString);
- preference.setIconResourceId(getIconResId());
- preference.setButtonColorResourceId(getColorResId());
- preference.setMainButtonLabel(getMainBtnString());
- preference.setDismissButtonLabel(getDismissBtnString());
+ preference.setIconResId(getIconResId());
+ preference.setTintColorResId(getColorResId());
+ preference.setPrimaryButtonText(getDismissBtnString());
+ preference.setSecondaryButtonText(getMainBtnString());
return true;
}
diff --git a/src/com/android/settings/fuelgauge/batteryusage/BatteryTipsCardPreference.java b/src/com/android/settings/fuelgauge/batteryusage/BatteryTipsCardPreference.java
deleted file mode 100644
index bbd1099..0000000
--- a/src/com/android/settings/fuelgauge/batteryusage/BatteryTipsCardPreference.java
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * Copyright (C) 2023 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.fuelgauge.batteryusage;
-
-import android.content.Context;
-import android.text.TextUtils;
-import android.util.AttributeSet;
-import android.view.View;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-import android.widget.TextView;
-
-import androidx.annotation.VisibleForTesting;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceViewHolder;
-
-import com.android.settings.R;
-
-import com.google.android.material.button.MaterialButton;
-
-/** A preference for displaying the battery tips card view. */
-public class BatteryTipsCardPreference extends Preference implements View.OnClickListener {
-
- private static final String TAG = "BatteryTipsCardPreference";
-
- interface OnConfirmListener {
- void onConfirm();
- }
-
- interface OnRejectListener {
- void onReject();
- }
-
- private OnConfirmListener mOnConfirmListener;
- private OnRejectListener mOnRejectListener;
- private int mIconResourceId = 0;
- private int mButtonColorResourceId = 0;
-
- @VisibleForTesting CharSequence mMainButtonLabel;
- @VisibleForTesting CharSequence mDismissButtonLabel;
-
- public BatteryTipsCardPreference(Context context, AttributeSet attrs) {
- super(context, attrs);
- setLayoutResource(R.layout.battery_tips_card);
- setViewId(R.id.battery_tips_card);
- setSelectable(false);
- }
-
- public void setOnConfirmListener(OnConfirmListener listener) {
- mOnConfirmListener = listener;
- }
-
- public void setOnRejectListener(OnRejectListener listener) {
- mOnRejectListener = listener;
- }
-
- /**
- * Sets the icon in tips card.
- */
- public void setIconResourceId(int resourceId) {
- if (mIconResourceId != resourceId) {
- mIconResourceId = resourceId;
- notifyChanged();
- }
- }
-
- /**
- * Sets the background color for main button and the text color for dismiss button.
- */
- public void setButtonColorResourceId(int resourceId) {
- if (mButtonColorResourceId != resourceId) {
- mButtonColorResourceId = resourceId;
- notifyChanged();
- }
- }
-
- /**
- * Sets the label of main button in tips card.
- */
- public void setMainButtonLabel(CharSequence label) {
- if (!TextUtils.equals(mMainButtonLabel, label)) {
- mMainButtonLabel = label;
- notifyChanged();
- }
- }
-
- /**
- * Sets the label of dismiss button in tips card.
- */
- public void setDismissButtonLabel(CharSequence label) {
- if (!TextUtils.equals(mDismissButtonLabel, label)) {
- mDismissButtonLabel = label;
- notifyChanged();
- }
- }
-
- @Override
- public void onClick(View view) {
- final int viewId = view.getId();
- if (viewId == R.id.main_button || viewId == R.id.battery_tips_card) {
- if (mOnConfirmListener != null) {
- mOnConfirmListener.onConfirm();
- }
- } else if (viewId == R.id.dismiss_button) {
- if (mOnRejectListener != null) {
- mOnRejectListener.onReject();
- }
- }
- }
-
- @Override
- public void onBindViewHolder(PreferenceViewHolder view) {
- super.onBindViewHolder(view);
-
- ((TextView) view.findViewById(R.id.title)).setText(getTitle());
-
- final LinearLayout tipsCard = (LinearLayout) view.findViewById(R.id.battery_tips_card);
- tipsCard.setOnClickListener(this);
- final MaterialButton mainButton = (MaterialButton) view.findViewById(R.id.main_button);
- mainButton.setOnClickListener(this);
- mainButton.setText(mMainButtonLabel);
- final MaterialButton dismissButton =
- (MaterialButton) view.findViewById(R.id.dismiss_button);
- dismissButton.setOnClickListener(this);
- dismissButton.setText(mDismissButtonLabel);
- if (mButtonColorResourceId != 0) {
- final int colorInt = getContext().getColor(mButtonColorResourceId);
- mainButton.setBackgroundColor(colorInt);
- dismissButton.setTextColor(colorInt);
- }
-
- if (mIconResourceId != 0) {
- ((ImageView) view.findViewById(R.id.icon)).setImageResource(mIconResourceId);
- }
- }
-}
diff --git a/src/com/android/settings/fuelgauge/batteryusage/BatteryTipsController.java b/src/com/android/settings/fuelgauge/batteryusage/BatteryTipsController.java
index 821c868..405b786 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/BatteryTipsController.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/BatteryTipsController.java
@@ -25,6 +25,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.overlay.FeatureFactory;
+import com.android.settings.widget.TipCardPreference;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
/** Controls the update for battery tips card */
@@ -50,10 +51,9 @@
void onAnomalyReject();
}
- private OnAnomalyConfirmListener mOnAnomalyConfirmListener;
- private OnAnomalyRejectListener mOnAnomalyRejectListener;
-
- @VisibleForTesting BatteryTipsCardPreference mCardPreference;
+ @VisibleForTesting OnAnomalyConfirmListener mOnAnomalyConfirmListener;
+ @VisibleForTesting OnAnomalyRejectListener mOnAnomalyRejectListener;
+ @VisibleForTesting TipCardPreference mCardPreference;
@VisibleForTesting AnomalyEventWrapper mAnomalyEventWrapper = null;
@VisibleForTesting Boolean mIsAcceptable = false;
@@ -117,42 +117,20 @@
return;
}
- // Set battery tips card listener
- mCardPreference.setOnConfirmListener(
+ mCardPreference.setPrimaryButtonAction(
() -> {
- mCardPreference.setVisible(false);
- if (mOnAnomalyConfirmListener != null) {
- mOnAnomalyConfirmListener.onAnomalyConfirm();
- } else if (mAnomalyEventWrapper.updateSystemSettingsIfAvailable()
- || mAnomalyEventWrapper.launchSubSetting()) {
- mMetricsFeatureProvider.action(
- /* attribution= */ SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
- /* action= */ SettingsEnums.ACTION_BATTERY_TIPS_CARD_ACCEPT,
- /* pageId= */ SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
- /* key= */ ANOMALY_KEY,
- /* value= */ anomalyKeyNumber);
- }
+ onBatteryTipsCardDismiss(anomalyKeyNumber);
+ return null;
});
- mCardPreference.setOnRejectListener(
+ mCardPreference.setSecondaryButtonAction(
() -> {
- mCardPreference.setVisible(false);
- if (mOnAnomalyRejectListener != null) {
- mOnAnomalyRejectListener.onAnomalyReject();
- }
- // For anomaly events with same record key, dismissed until next time full
- // charged.
- final String dismissRecordKey = mAnomalyEventWrapper.getDismissRecordKey();
- if (!TextUtils.isEmpty(dismissRecordKey)) {
- DatabaseUtils.setDismissedPowerAnomalyKeys(mContext, dismissRecordKey);
- }
- mMetricsFeatureProvider.action(
- /* attribution= */ SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
- /* action= */ SettingsEnums.ACTION_BATTERY_TIPS_CARD_DISMISS,
- /* pageId= */ SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
- /* key= */ ANOMALY_KEY,
- /* value= */ anomalyKeyNumber);
+ onBatteryTipsCardAccept(anomalyKeyNumber);
+ return null;
});
+ mCardPreference.setPrimaryButtonVisibility(true);
+ mCardPreference.setSecondaryButtonVisibility(true);
+ mCardPreference.buildContent();
mCardPreference.setVisible(true);
mMetricsFeatureProvider.action(
/* attribution= */ SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
@@ -161,4 +139,37 @@
/* key= */ ANOMALY_KEY,
/* value= */ anomalyKeyNumber);
}
+
+ private void onBatteryTipsCardDismiss(final int anomalyKeyNumber) {
+ mCardPreference.setVisible(false);
+ if (mOnAnomalyRejectListener != null) {
+ mOnAnomalyRejectListener.onAnomalyReject();
+ }
+ // For anomaly events with same record key, dismissed until next time full charged.
+ final String dismissRecordKey = mAnomalyEventWrapper.getDismissRecordKey();
+ if (!TextUtils.isEmpty(dismissRecordKey)) {
+ DatabaseUtils.setDismissedPowerAnomalyKeys(mContext, dismissRecordKey);
+ }
+ mMetricsFeatureProvider.action(
+ /* attribution= */ SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
+ /* action= */ SettingsEnums.ACTION_BATTERY_TIPS_CARD_DISMISS,
+ /* pageId= */ SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
+ /* key= */ ANOMALY_KEY,
+ /* value= */ anomalyKeyNumber);
+ }
+
+ private void onBatteryTipsCardAccept(final int anomalyKeyNumber) {
+ mCardPreference.setVisible(false);
+ if (mOnAnomalyConfirmListener != null) {
+ mOnAnomalyConfirmListener.onAnomalyConfirm();
+ } else if (mAnomalyEventWrapper.updateSystemSettingsIfAvailable()
+ || mAnomalyEventWrapper.launchSubSetting()) {
+ mMetricsFeatureProvider.action(
+ /* attribution= */ SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
+ /* action= */ SettingsEnums.ACTION_BATTERY_TIPS_CARD_ACCEPT,
+ /* pageId= */ SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
+ /* key= */ ANOMALY_KEY,
+ /* value= */ anomalyKeyNumber);
+ }
+ }
}
diff --git a/src/com/android/settings/fuelgauge/datasaver/DynamicDenylistManager.java b/src/com/android/settings/fuelgauge/datasaver/DynamicDenylistManager.java
index b77d5eb..ecb2a48 100644
--- a/src/com/android/settings/fuelgauge/datasaver/DynamicDenylistManager.java
+++ b/src/com/android/settings/fuelgauge/datasaver/DynamicDenylistManager.java
@@ -78,6 +78,11 @@
return;
}
+ if (mNetworkPolicyManager == null) {
+ Log.w(TAG, "syncPolicyIfNeeded: invalid mNetworkPolicyManager");
+ return;
+ }
+
final SharedPreferences.Editor editor = getManualDenylistPref().edit();
final int[] existedUids = mNetworkPolicyManager
.getUidsWithPolicy(POLICY_REJECT_METERED_BACKGROUND);
@@ -91,6 +96,11 @@
/** Set policy flags for specific UID. */
public void setUidPolicyLocked(int uid, int policy) {
+ if (mNetworkPolicyManager == null) {
+ Log.w(TAG, "setUidPolicyLocked: invalid mNetworkPolicyManager");
+ return;
+ }
+
Log.i(TAG, "setUidPolicyLocked: uid=" + uid + " policy=" + policy);
synchronized (mLock) {
mNetworkPolicyManager.setUidPolicy(uid, policy);
@@ -100,7 +110,7 @@
/** Suggest a list of package to set as POLICY_REJECT. */
public void setDenylist(Set<Integer> denylistTargetUids) {
- if (denylistTargetUids == null) {
+ if (denylistTargetUids == null || mNetworkPolicyManager == null) {
return;
}
final Set<Integer> manualDenylistUids = getDenylistAllUids(getManualDenylistPref());
@@ -164,6 +174,12 @@
Log.w(TAG, "resetDenylistIfNeeded: invalid conditions");
return;
}
+
+ if (mNetworkPolicyManager == null) {
+ Log.w(TAG, "setUidPolicyLocked: invalid mNetworkPolicyManager");
+ return;
+ }
+
synchronized (mLock) {
final int[] uids = mNetworkPolicyManager
.getUidsWithPolicy(POLICY_REJECT_METERED_BACKGROUND);
diff --git a/src/com/android/settings/network/SubscriptionsPreferenceController.java b/src/com/android/settings/network/SubscriptionsPreferenceController.java
index b7ed31e..cdbf456 100644
--- a/src/com/android/settings/network/SubscriptionsPreferenceController.java
+++ b/src/com/android/settings/network/SubscriptionsPreferenceController.java
@@ -241,6 +241,8 @@
if (mSubsGearPref == null) {
mPreferenceGroup.removeAll();
mSubsGearPref = new MutableGearPreference(mContext, null);
+ mSubsGearPref
+ .checkRestrictionAndSetDisabled(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS);
mSubsGearPref.setOnPreferenceClickListener(preference -> {
connectCarrierNetwork();
return true;
diff --git a/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java b/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java
index e92d999..7d5230d 100644
--- a/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java
+++ b/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java
@@ -19,9 +19,11 @@
import static androidx.lifecycle.Lifecycle.Event.ON_START;
import static androidx.lifecycle.Lifecycle.Event.ON_STOP;
+import static com.android.settings.network.telephony.EnabledNetworkModePreferenceControllerHelperKt.getNetworkModePreferenceType;
import static com.android.settings.network.telephony.EnabledNetworkModePreferenceControllerHelperKt.setAllowedNetworkTypes;
import android.content.Context;
+import android.content.res.Resources;
import android.os.PersistableBundle;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionInfo;
@@ -44,6 +46,7 @@
import com.android.internal.telephony.flags.Flags;
import com.android.settings.R;
+import com.android.settings.core.BasePreferenceController;
import com.android.settings.network.AllowedNetworkTypesListener;
import com.android.settings.network.CarrierConfigCache;
import com.android.settings.network.SubscriptionsChangeListener;
@@ -61,16 +64,17 @@
* Preference controller for "Enabled network mode"
*/
public class EnabledNetworkModePreferenceController extends
- TelephonyBasePreferenceController implements
+ BasePreferenceController implements
ListPreference.OnPreferenceChangeListener, LifecycleObserver,
SubscriptionsChangeListener.SubscriptionsChangeListenerClient {
private static final String LOG_TAG = "EnabledNetworkMode";
+
+ private int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
private AllowedNetworkTypesListener mAllowedNetworkTypesListener;
private Preference mPreference;
private PreferenceScreen mPreferenceScreen;
private TelephonyManager mTelephonyManager;
- private CarrierConfigCache mCarrierConfigCache;
private PreferenceEntriesBuilder mBuilder;
private SubscriptionsChangeListener mSubscriptionsListener;
private int mCallState = TelephonyManager.CALL_STATE_IDLE;
@@ -81,36 +85,16 @@
public EnabledNetworkModePreferenceController(Context context, String key) {
super(context, key);
mSubscriptionsListener = new SubscriptionsChangeListener(context, this);
- mCarrierConfigCache = CarrierConfigCache.getInstance(context);
if (mTelephonyCallback == null) {
mTelephonyCallback = new PhoneCallStateTelephonyCallback();
}
}
@Override
- public int getAvailabilityStatus(int subId) {
- boolean visible;
-
- final PersistableBundle carrierConfig = mCarrierConfigCache.getConfigForSubId(subId);
- if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
- visible = false;
- } else if (carrierConfig == null
- || !CarrierConfigManager.isConfigForIdentifiedCarrier(carrierConfig)) {
- visible = false;
- } else if (carrierConfig.getBoolean(
- CarrierConfigManager.KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL)
- || carrierConfig.getBoolean(
- CarrierConfigManager.KEY_HIDE_PREFERRED_NETWORK_TYPE_BOOL)) {
- visible = false;
- } else if (carrierConfig.getBoolean(CarrierConfigManager.KEY_WORLD_PHONE_BOOL)) {
- visible = false;
- } else if (!isCallStateIdle()) {
- return AVAILABLE_UNSEARCHABLE;
- } else {
- visible = true;
- }
-
- return visible ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
+ public int getAvailabilityStatus() {
+ return getNetworkModePreferenceType(mContext, mSubId)
+ == NetworkModePreferenceType.EnabledNetworkMode
+ ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
}
protected boolean isCallStateIdle() {
@@ -953,9 +937,14 @@
}
}
+ /**
+ * Returns the resources associated with Subscription.
+ *
+ * @return Resources associated with Subscription.
+ */
@VisibleForTesting
- PhoneCallStateTelephonyCallback getTelephonyCallback() {
- return mTelephonyCallback;
+ Resources getResourcesForSubId() {
+ return SubscriptionManager.getResourcesForSubId(mContext, mSubId);
}
@Override
diff --git a/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceControllerHelper.kt b/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceControllerHelper.kt
index eab5d74..d297e1c 100644
--- a/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceControllerHelper.kt
+++ b/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceControllerHelper.kt
@@ -16,9 +16,15 @@
package com.android.settings.network.telephony
+import android.content.Context
+import android.telephony.CarrierConfigManager
+import android.telephony.SubscriptionManager
import android.telephony.TelephonyManager
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.lifecycleScope
+import com.android.settings.R
+import com.android.settings.network.telephony.MobileNetworkSettingsSearchIndex.MobileNetworkSettingsSearchItem
+import com.android.settings.network.telephony.MobileNetworkSettingsSearchIndex.MobileNetworkSettingsSearchResult
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@@ -33,3 +39,62 @@
)
}
}
+
+enum class NetworkModePreferenceType {
+ EnabledNetworkMode,
+ PreferredNetworkMode,
+ None,
+}
+
+fun getNetworkModePreferenceType(context: Context, subId: Int): NetworkModePreferenceType {
+ if (!SubscriptionManager.isValidSubscriptionId(subId)) return NetworkModePreferenceType.None
+ data class Config(
+ val carrierConfigApplied: Boolean,
+ val hideCarrierNetworkSettings: Boolean,
+ val hidePreferredNetworkType: Boolean,
+ val worldPhone: Boolean,
+ )
+
+ val config =
+ CarrierConfigRepository(context).transformConfig(subId) {
+ Config(
+ carrierConfigApplied =
+ getBoolean(CarrierConfigManager.KEY_CARRIER_CONFIG_APPLIED_BOOL),
+ hideCarrierNetworkSettings =
+ getBoolean(CarrierConfigManager.KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL),
+ hidePreferredNetworkType =
+ getBoolean(CarrierConfigManager.KEY_HIDE_PREFERRED_NETWORK_TYPE_BOOL),
+ worldPhone = getBoolean(CarrierConfigManager.KEY_WORLD_PHONE_BOOL),
+ )
+ }
+
+ return when {
+ !config.carrierConfigApplied ||
+ config.hideCarrierNetworkSettings ||
+ config.hidePreferredNetworkType -> NetworkModePreferenceType.None
+ config.worldPhone -> NetworkModePreferenceType.PreferredNetworkMode
+ else -> NetworkModePreferenceType.EnabledNetworkMode
+ }
+}
+
+class PreferredNetworkModeSearchItem(private val context: Context) :
+ MobileNetworkSettingsSearchItem {
+ private val title: String = context.getString(R.string.preferred_network_mode_title)
+
+ override fun getSearchResult(subId: Int): MobileNetworkSettingsSearchResult? =
+ when (getNetworkModePreferenceType(context, subId)) {
+ NetworkModePreferenceType.PreferredNetworkMode ->
+ MobileNetworkSettingsSearchResult(
+ key = "preferred_network_mode_key",
+ title = title,
+ )
+
+ NetworkModePreferenceType.EnabledNetworkMode ->
+ MobileNetworkSettingsSearchResult(
+ key = "enabled_networks_key",
+ title = title,
+ )
+
+ else -> null
+ }
+}
diff --git a/src/com/android/settings/network/telephony/MmsMessagePreferenceController.kt b/src/com/android/settings/network/telephony/MmsMessagePreferenceController.kt
index c929d5c..220218c 100644
--- a/src/com/android/settings/network/telephony/MmsMessagePreferenceController.kt
+++ b/src/com/android/settings/network/telephony/MmsMessagePreferenceController.kt
@@ -20,11 +20,13 @@
import android.telephony.SubscriptionManager
import android.telephony.TelephonyManager
import android.telephony.data.ApnSetting
+import androidx.annotation.VisibleForTesting
import androidx.lifecycle.LifecycleOwner
import androidx.preference.PreferenceScreen
import com.android.settings.R
import com.android.settings.Settings.MobileNetworkActivity.EXTRA_MMS_MESSAGE
import com.android.settings.core.TogglePreferenceController
+import com.android.settings.network.telephony.MobileNetworkSettingsSearchIndex.MobileNetworkSettingsSearchResult
import com.android.settings.network.telephony.MobileNetworkSettingsSearchIndex.MobileNetworkSettingsSearchItem
import com.android.settingslib.spa.framework.util.collectLatestWithLifecycle
import kotlinx.coroutines.flow.combine
@@ -109,7 +111,7 @@
}
class MmsMessageSearchItem(
- context: Context,
+ private val context: Context,
private val getDefaultDataSubId: () -> Int = {
SubscriptionManager.getDefaultDataSubscriptionId()
},
@@ -117,12 +119,18 @@
private var telephonyManager: TelephonyManager =
context.getSystemService(TelephonyManager::class.java)!!
- override val key: String = EXTRA_MMS_MESSAGE
- override val title: String = context.getString(R.string.mms_message_title)
-
- override fun isAvailable(subId: Int): Boolean =
+ @VisibleForTesting
+ fun isAvailable(subId: Int): Boolean =
getAvailabilityStatus(
telephonyManager.createForSubscriptionId(subId), subId, getDefaultDataSubId)
+
+ override fun getSearchResult(subId: Int): MobileNetworkSettingsSearchResult? {
+ if (!isAvailable(subId)) return null
+ return MobileNetworkSettingsSearchResult(
+ key = EXTRA_MMS_MESSAGE,
+ title = context.getString(R.string.mms_message_title),
+ )
+ }
}
}
}
diff --git a/src/com/android/settings/network/telephony/MobileNetworkSettings.java b/src/com/android/settings/network/telephony/MobileNetworkSettings.java
index ee1485e..acf674f 100644
--- a/src/com/android/settings/network/telephony/MobileNetworkSettings.java
+++ b/src/com/android/settings/network/telephony/MobileNetworkSettings.java
@@ -202,6 +202,11 @@
@Override
public void onAttach(Context context) {
super.onAttach(context);
+ if (isUiRestricted()) {
+ Log.d(LOG_TAG, "Mobile network page is disallowed.");
+ finish();
+ return;
+ }
if (mSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
Log.d(LOG_TAG, "Invalid subId, get the default subscription to show.");
diff --git a/src/com/android/settings/network/telephony/MobileNetworkSettingsSearchIndex.kt b/src/com/android/settings/network/telephony/MobileNetworkSettingsSearchIndex.kt
index 4e97d31..58661f0 100644
--- a/src/com/android/settings/network/telephony/MobileNetworkSettingsSearchIndex.kt
+++ b/src/com/android/settings/network/telephony/MobileNetworkSettingsSearchIndex.kt
@@ -39,15 +39,14 @@
private val searchItemsFactory: (context: Context) -> List<MobileNetworkSettingsSearchItem> =
::createSearchItems,
) {
+ data class MobileNetworkSettingsSearchResult(
+ val key: String,
+ val title: String,
+ val keywords: String? = null,
+ )
+
interface MobileNetworkSettingsSearchItem {
- val key: String
-
- val title: String
-
- val keywords: String?
- get() = null
-
- fun isAvailable(subId: Int): Boolean
+ fun getSearchResult(subId: Int): MobileNetworkSettingsSearchResult?
}
fun createSearchIndexableData(): SearchIndexableData {
@@ -71,13 +70,15 @@
searchItem: MobileNetworkSettingsSearchItem,
subInfos: List<SubscriptionInfo>
): List<SearchIndexableRaw> =
- subInfos
- .filter { searchItem.isAvailable(it.subscriptionId) }
- .map { subInfo -> searchIndexableRaw(context, searchItem, subInfo) }
+ subInfos.mapNotNull { subInfo ->
+ searchItem.getSearchResult(subInfo.subscriptionId)?.let { searchResult ->
+ searchIndexableRaw(context, searchResult, subInfo)
+ }
+ }
private fun searchIndexableRaw(
context: Context,
- searchItem: MobileNetworkSettingsSearchItem,
+ searchResult: MobileNetworkSettingsSearchResult,
subInfo: SubscriptionInfo,
): SearchIndexableRaw {
val key =
@@ -85,7 +86,7 @@
.setFragment(
SpaSearchLandingFragment.newBuilder()
.setFragmentName(MobileNetworkSettings::class.java.name)
- .setPreferenceKey(searchItem.key)
+ .setPreferenceKey(searchResult.key)
.putArguments(
Settings.EXTRA_SUB_ID,
BundleValue.newBuilder().setIntValue(subInfo.subscriptionId).build()))
@@ -94,8 +95,8 @@
return createSearchIndexableRaw(
context = context,
spaSearchLandingKey = key,
- itemTitle = searchItem.title,
- keywords = searchItem.keywords,
+ itemTitle = searchResult.title,
+ keywords = searchResult.keywords,
indexableClass = MobileNetworkSettings::class.java,
pageTitle = "$simsTitle > ${subInfo.displayName}",
)
@@ -115,6 +116,7 @@
listOf(
MmsMessageSearchItem(context),
NrAdvancedCallingSearchItem(context),
+ PreferredNetworkModeSearchItem(context),
RoamingSearchItem(context),
WifiCallingSearchItem(context),
)
diff --git a/src/com/android/settings/network/telephony/NrAdvancedCallingPreferenceController.kt b/src/com/android/settings/network/telephony/NrAdvancedCallingPreferenceController.kt
index 5c94e84..0d8766e 100644
--- a/src/com/android/settings/network/telephony/NrAdvancedCallingPreferenceController.kt
+++ b/src/com/android/settings/network/telephony/NrAdvancedCallingPreferenceController.kt
@@ -25,6 +25,7 @@
import androidx.compose.ui.res.stringResource
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.android.settings.R
+import com.android.settings.network.telephony.MobileNetworkSettingsSearchIndex.MobileNetworkSettingsSearchResult
import com.android.settings.network.telephony.MobileNetworkSettingsSearchIndex.MobileNetworkSettingsSearchItem
import com.android.settings.spa.preference.ComposePreferenceController
import com.android.settingslib.spa.widget.preference.SwitchPreference
@@ -79,12 +80,17 @@
companion object {
class NrAdvancedCallingSearchItem(private val context: Context) :
MobileNetworkSettingsSearchItem {
- override val key = "nr_advanced_calling"
- override val title: String = context.getString(R.string.nr_advanced_calling_title)
- override val keywords: String = context.getString(R.string.keywords_nr_advanced_calling)
- override fun isAvailable(subId: Int): Boolean =
- VoNrRepository(context, subId).isVoNrAvailable()
+ fun isAvailable(subId: Int): Boolean = VoNrRepository(context, subId).isVoNrAvailable()
+
+ override fun getSearchResult(subId: Int): MobileNetworkSettingsSearchResult? {
+ if (!isAvailable(subId)) return null
+ return MobileNetworkSettingsSearchResult(
+ key = "nr_advanced_calling",
+ title = context.getString(R.string.nr_advanced_calling_title),
+ keywords = context.getString(R.string.keywords_nr_advanced_calling),
+ )
+ }
}
}
}
diff --git a/src/com/android/settings/network/telephony/PreferredNetworkModePreferenceController.java b/src/com/android/settings/network/telephony/PreferredNetworkModePreferenceController.java
index bdfeace..210cd87 100644
--- a/src/com/android/settings/network/telephony/PreferredNetworkModePreferenceController.java
+++ b/src/com/android/settings/network/telephony/PreferredNetworkModePreferenceController.java
@@ -16,6 +16,8 @@
package com.android.settings.network.telephony;
+import static com.android.settings.network.telephony.EnabledNetworkModePreferenceControllerHelperKt.getNetworkModePreferenceType;
+
import android.content.Context;
import android.os.PersistableBundle;
import android.telephony.CarrierConfigManager;
@@ -27,16 +29,18 @@
import androidx.preference.Preference;
import com.android.settings.R;
+import com.android.settings.core.BasePreferenceController;
import com.android.settings.network.CarrierConfigCache;
import com.android.settings.network.telephony.TelephonyConstants.TelephonyManagerConstants;
/**
* Preference controller for "Preferred network mode"
*/
-public class PreferredNetworkModePreferenceController extends TelephonyBasePreferenceController
+public class PreferredNetworkModePreferenceController extends BasePreferenceController
implements ListPreference.OnPreferenceChangeListener {
private static final String TAG = "PrefNetworkModeCtrl";
+ private int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
private CarrierConfigCache mCarrierConfigCache;
private TelephonyManager mTelephonyManager;
private boolean mIsGlobalCdma;
@@ -47,25 +51,10 @@
}
@Override
- public int getAvailabilityStatus(int subId) {
- final PersistableBundle carrierConfig = mCarrierConfigCache.getConfigForSubId(subId);
- boolean visible;
- if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
- visible = false;
- } else if (carrierConfig == null) {
- visible = false;
- } else if (carrierConfig.getBoolean(
- CarrierConfigManager.KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL)
- || carrierConfig.getBoolean(
- CarrierConfigManager.KEY_HIDE_PREFERRED_NETWORK_TYPE_BOOL)) {
- visible = false;
- } else if (carrierConfig.getBoolean(CarrierConfigManager.KEY_WORLD_PHONE_BOOL)) {
- visible = true;
- } else {
- visible = false;
- }
-
- return visible ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
+ public int getAvailabilityStatus() {
+ return getNetworkModePreferenceType(mContext, mSubId)
+ == NetworkModePreferenceType.PreferredNetworkMode
+ ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
}
@Override
diff --git a/src/com/android/settings/network/telephony/RoamingPreferenceController.kt b/src/com/android/settings/network/telephony/RoamingPreferenceController.kt
index 7633677..a5ac7d6 100644
--- a/src/com/android/settings/network/telephony/RoamingPreferenceController.kt
+++ b/src/com/android/settings/network/telephony/RoamingPreferenceController.kt
@@ -29,6 +29,7 @@
import androidx.fragment.app.FragmentManager
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.android.settings.R
+import com.android.settings.network.telephony.MobileNetworkSettingsSearchIndex.MobileNetworkSettingsSearchResult
import com.android.settings.network.telephony.MobileNetworkSettingsSearchIndex.MobileNetworkSettingsSearchItem
import com.android.settings.spa.preference.ComposePreferenceController
import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel
@@ -98,16 +99,21 @@
companion object {
private const val DIALOG_TAG = "MobileDataDialog"
- class RoamingSearchItem(context: Context) : MobileNetworkSettingsSearchItem {
- override val key = "button_roaming_key"
- override val title: String = context.getString(R.string.roaming)
-
+ class RoamingSearchItem(private val context: Context) : MobileNetworkSettingsSearchItem {
private val carrierConfigRepository = CarrierConfigRepository(context)
- override fun isAvailable(subId: Int): Boolean =
+ fun isAvailable(subId: Int): Boolean =
SubscriptionManager.isValidSubscriptionId(subId) &&
!carrierConfigRepository.getBoolean(
subId, CarrierConfigManager.KEY_FORCE_HOME_NETWORK_BOOL)
+
+ override fun getSearchResult(subId: Int): MobileNetworkSettingsSearchResult? {
+ if (!isAvailable(subId)) return null
+ return MobileNetworkSettingsSearchResult(
+ key = "button_roaming_key",
+ title = context.getString(R.string.roaming),
+ )
+ }
}
}
}
diff --git a/src/com/android/settings/network/telephony/TelephonyBasePreferenceController.java b/src/com/android/settings/network/telephony/TelephonyBasePreferenceController.java
index 3972f39..ee15520 100644
--- a/src/com/android/settings/network/telephony/TelephonyBasePreferenceController.java
+++ b/src/com/android/settings/network/telephony/TelephonyBasePreferenceController.java
@@ -17,9 +17,6 @@
package com.android.settings.network.telephony;
import android.content.Context;
-import android.content.res.Resources;
-import android.os.PersistableBundle;
-import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
import com.android.settings.core.BasePreferenceController;
@@ -59,29 +56,4 @@
public void unsetAvailabilityStatus() {
mSetSessionCount.getAndDecrement();
}
-
- /**
- * Get carrier config based on specific subscription id.
- *
- * @param subId is the subscription id
- * @return {@link PersistableBundle} of carrier config, or {@code null} when carrier config
- * is not available.
- */
- public PersistableBundle getCarrierConfigForSubId(int subId) {
- if (!SubscriptionManager.isValidSubscriptionId(subId)) {
- return null;
- }
- final CarrierConfigManager carrierConfigMgr =
- mContext.getSystemService(CarrierConfigManager.class);
- return carrierConfigMgr.getConfigForSubId(subId);
- }
-
- /**
- * Returns the resources associated with Subscription.
- *
- * @return Resources associated with Subscription.
- */
- public Resources getResourcesForSubId() {
- return SubscriptionManager.getResourcesForSubId(mContext, mSubId);
- }
}
diff --git a/src/com/android/settings/network/telephony/WifiCallingPreferenceController.kt b/src/com/android/settings/network/telephony/WifiCallingPreferenceController.kt
index 7e8e58c..e04763a 100644
--- a/src/com/android/settings/network/telephony/WifiCallingPreferenceController.kt
+++ b/src/com/android/settings/network/telephony/WifiCallingPreferenceController.kt
@@ -27,6 +27,7 @@
import androidx.preference.PreferenceScreen
import com.android.settings.R
import com.android.settings.core.BasePreferenceController
+import com.android.settings.network.telephony.MobileNetworkSettingsSearchIndex.MobileNetworkSettingsSearchResult
import com.android.settings.network.telephony.MobileNetworkSettingsSearchIndex.MobileNetworkSettingsSearchItem
import com.android.settings.network.telephony.wificalling.WifiCallingRepository
import com.android.settingslib.spa.framework.util.collectLatestWithLifecycle
@@ -132,12 +133,17 @@
class WifiCallingSearchItem(
private val context: Context,
) : MobileNetworkSettingsSearchItem {
- override val key: String = "wifi_calling"
- override val title: String = context.getString(R.string.wifi_calling_settings_title)
-
- override fun isAvailable(subId: Int): Boolean = runBlocking {
+ private fun isAvailable(subId: Int): Boolean = runBlocking {
WifiCallingRepository(context, subId).wifiCallingReadyFlow().first()
}
+
+ override fun getSearchResult(subId: Int): MobileNetworkSettingsSearchResult? {
+ if (!isAvailable(subId)) return null
+ return MobileNetworkSettingsSearchResult(
+ key = "wifi_calling",
+ title = context.getString(R.string.wifi_calling_settings_title),
+ )
+ }
}
}
}
diff --git a/src/com/android/settings/password/BiometricFragment.java b/src/com/android/settings/password/BiometricFragment.java
index a7a039e..5030b6a 100644
--- a/src/com/android/settings/password/BiometricFragment.java
+++ b/src/com/android/settings/password/BiometricFragment.java
@@ -19,7 +19,6 @@
import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_ERROR_USER_CANCELED;
import android.app.settings.SettingsEnums;
-import android.content.ComponentName;
import android.hardware.biometrics.BiometricManager;
import android.hardware.biometrics.BiometricPrompt;
import android.hardware.biometrics.BiometricPrompt.AuthenticationCallback;
@@ -44,7 +43,6 @@
private static final String TAG = "ConfirmDeviceCredential/BiometricFragment";
private static final String KEY_PROMPT_INFO = "prompt_info";
- private static final String KEY_CALLING_ACTIVITY = "calling_activity";
// Re-set by the application. Should be done upon orientation changes, etc
private Executor mClientExecutor;
@@ -94,13 +92,10 @@
* @param promptInfo
* @return
*/
- public static BiometricFragment newInstance(PromptInfo promptInfo,
- ComponentName callingActivity) {
+ public static BiometricFragment newInstance(PromptInfo promptInfo) {
BiometricFragment biometricFragment = new BiometricFragment();
final Bundle bundle = new Bundle();
bundle.putParcelable(KEY_PROMPT_INFO, promptInfo);
-
- bundle.putParcelable(KEY_CALLING_ACTIVITY, callingActivity);
biometricFragment.setArguments(bundle);
return biometricFragment;
}
@@ -135,8 +130,6 @@
final Bundle bundle = getArguments();
final PromptInfo promptInfo = bundle.getParcelable(KEY_PROMPT_INFO);
- final ComponentName callingActivity = bundle.getParcelable(KEY_CALLING_ACTIVITY);
-
BiometricPrompt.Builder promptBuilder = new BiometricPrompt.Builder(getContext())
.setTitle(promptInfo.getTitle())
.setUseDefaultTitle() // use default title if title is null/empty
@@ -152,7 +145,8 @@
promptInfo.isDisallowBiometricsIfPolicyExists())
.setShowEmergencyCallButton(promptInfo.isShowEmergencyCallButton())
.setReceiveSystemEvents(true)
- .setComponentNameForConfirmDeviceCredentialActivity(callingActivity);
+ .setRealCallerForConfirmDeviceCredentialActivity(
+ promptInfo.getRealCallerForConfirmDeviceCredentialActivity());
if (promptInfo.getLogoRes() != 0){
promptBuilder.setLogoRes(promptInfo.getLogoRes());
}
diff --git a/src/com/android/settings/password/ConfirmDeviceCredentialActivity.java b/src/com/android/settings/password/ConfirmDeviceCredentialActivity.java
index 4f35532..d7d1531 100644
--- a/src/com/android/settings/password/ConfirmDeviceCredentialActivity.java
+++ b/src/com/android/settings/password/ConfirmDeviceCredentialActivity.java
@@ -104,6 +104,7 @@
private boolean mForceVerifyPath = false;
private boolean mGoingToBackground;
private boolean mWaitingForBiometricCallback;
+ private int mBiometricsAuthenticators;
private Executor mExecutor = (runnable -> {
mHandler.post(runnable);
@@ -122,8 +123,14 @@
Log.i(TAG, "Finishing, user no longer valid: " + mUserId);
finish();
} else {
- // All other errors go to some version of CC
- showConfirmCredentials();
+ if ((mBiometricsAuthenticators
+ & BiometricManager.Authenticators.DEVICE_CREDENTIAL) != 0) {
+ // All other errors go to some version of CC
+ showConfirmCredentials();
+ } else {
+ Log.i(TAG, "Finishing, device credential not requested");
+ finish();
+ }
}
} else if (mWaitingForBiometricCallback) { // mGoingToBackground is true
mWaitingForBiometricCallback = false;
@@ -188,7 +195,7 @@
mDetails = intent.getCharSequenceExtra(KeyguardManager.EXTRA_DESCRIPTION);
String alternateButton = intent.getStringExtra(
KeyguardManager.EXTRA_ALTERNATE_BUTTON_LABEL);
- final int authenticators = intent.getIntExtra(BIOMETRIC_PROMPT_AUTHENTICATORS,
+ mBiometricsAuthenticators = intent.getIntExtra(BIOMETRIC_PROMPT_AUTHENTICATORS,
BiometricManager.Authenticators.DEVICE_CREDENTIAL
| BiometricManager.Authenticators.BIOMETRIC_WEAK);
final String negativeButtonText = intent.getStringExtra(
@@ -229,8 +236,9 @@
promptInfo.setTitle(mTitle);
promptInfo.setDescription(mDetails);
promptInfo.setDisallowBiometricsIfPolicyExists(mCheckDevicePolicyManager);
- promptInfo.setAuthenticators(authenticators);
+ promptInfo.setAuthenticators(mBiometricsAuthenticators);
promptInfo.setNegativeButtonText(negativeButtonText);
+ promptInfo.setRealCallerForConfirmDeviceCredentialActivity(getCallingActivity());
if (android.multiuser.Flags.enablePrivateSpaceFeatures()
&& android.multiuser.Flags.usePrivateSpaceIconInBiometricPrompt()
@@ -496,8 +504,7 @@
boolean newFragment = false;
if (mBiometricFragment == null) {
- mBiometricFragment = BiometricFragment.newInstance(promptInfo,
- getCallingActivity());
+ mBiometricFragment = BiometricFragment.newInstance(promptInfo);
newFragment = true;
}
mBiometricFragment.setCallbacks(mExecutor, mAuthenticationCallback);
diff --git a/src/com/android/settings/password/SetNewPasswordActivity.java b/src/com/android/settings/password/SetNewPasswordActivity.java
index 0ba52ea..36756f9 100644
--- a/src/com/android/settings/password/SetNewPasswordActivity.java
+++ b/src/com/android/settings/password/SetNewPasswordActivity.java
@@ -124,9 +124,7 @@
@Override
public void launchChooseLock(Bundle chooseLockFingerprintExtras) {
- final boolean isInSetupWizard = WizardManagerHelper.isAnySetupWizard(getIntent());
- Intent intent = isInSetupWizard ? new Intent(this, SetupChooseLockGeneric.class)
- : new Intent(this, ChooseLockGeneric.class);
+ final Intent intent = new Intent(this, SetupChooseLockGeneric.class);
intent.setAction(mNewPasswordAction);
intent.putExtras(chooseLockFingerprintExtras);
intent.putExtra(EXTRA_KEY_CHOOSE_LOCK_SCREEN_TITLE,
diff --git a/src/com/android/settings/system/reset/ResetNetworkConfirm.kt b/src/com/android/settings/system/reset/ResetNetworkConfirm.kt
index 34b9909..e040356 100644
--- a/src/com/android/settings/system/reset/ResetNetworkConfirm.kt
+++ b/src/com/android/settings/system/reset/ResetNetworkConfirm.kt
@@ -18,6 +18,7 @@
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 @@
* 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 @@
/** 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 @@
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 @@
}
}
+ 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 @@
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 @@
} else {
Toast.makeText(activity, R.string.reset_network_complete_toast, Toast.LENGTH_SHORT)
.show()
+ activity.finish()
}
- activity.finish()
}
override fun onDestroy() {
diff --git a/src/com/android/settings/users/UserSettings.java b/src/com/android/settings/users/UserSettings.java
index 0cf01e3..c387d9e 100644
--- a/src/com/android/settings/users/UserSettings.java
+++ b/src/com/android/settings/users/UserSettings.java
@@ -919,7 +919,7 @@
d = mCreateUserDialogController.createDialog(
getActivity(),
this::startActivityForResult,
- UserManager.isMultipleAdminEnabled(),
+ canCreateAdminUser(),
(userName, userIcon, isAdmin) -> {
mPendingUserIcon = userIcon;
mPendingUserName = userName;
@@ -937,6 +937,19 @@
return d;
}
+ /**
+ * Checks if the creation of a new admin user is allowed.
+ * @return {@code true} if creating a new admin is allowed, {@code false} otherwise.
+ */
+ private boolean canCreateAdminUser() {
+ if (Flags.unicornModeRefactoringForHsumReadOnly()) {
+ return UserManager.isMultipleAdminEnabled()
+ && !mUserManager.hasUserRestriction(UserManager.DISALLOW_GRANT_ADMIN);
+ } else {
+ return UserManager.isMultipleAdminEnabled();
+ }
+ }
+
@Override
public int getDialogMetricsCategory(int dialogId) {
switch (dialogId) {
diff --git a/src/com/android/settings/widget/MutableGearPreference.java b/src/com/android/settings/widget/MutableGearPreference.java
index b0804eb..73491f0 100644
--- a/src/com/android/settings/widget/MutableGearPreference.java
+++ b/src/com/android/settings/widget/MutableGearPreference.java
@@ -41,11 +41,13 @@
@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
diff --git a/src/com/android/settings/widget/TipCardPreference.kt b/src/com/android/settings/widget/TipCardPreference.kt
index 0ae7d2a..0ca0272 100644
--- a/src/com/android/settings/widget/TipCardPreference.kt
+++ b/src/com/android/settings/widget/TipCardPreference.kt
@@ -19,6 +19,7 @@
import android.content.Context
import android.content.res.Resources
import android.util.AttributeSet
+import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.res.vectorResource
import com.android.settings.spa.preference.ComposePreference
@@ -37,6 +38,9 @@
/** A icon resource id for displaying icon on tips card. */
var iconResId: Int? = null
+ /** A color resource id for displaying icon and button text on tips card. */
+ var tintColorResId: Int? = null
+
/** The primary button's text. */
var primaryButtonText: String = ""
@@ -85,6 +89,8 @@
title = title?.toString() ?: "",
text = summary?.toString() ?: "",
buttons = listOfNotNull(configPrimaryButton(), configSecondaryButton()),
+ tintColor = tintColorResId?.let { Color(context.getColor(it)) }
+ ?: Color.Unspecified,
onDismiss = onDismiss,
imageVector =
iconResId
diff --git a/src/com/android/settings/wifi/dpp/WifiQrCode.java b/src/com/android/settings/wifi/dpp/WifiQrCode.java
index 9b93480..78e0625 100644
--- a/src/com/android/settings/wifi/dpp/WifiQrCode.java
+++ b/src/com/android/settings/wifi/dpp/WifiQrCode.java
@@ -46,6 +46,7 @@
*
*/
public class WifiQrCode {
+ private static final String TAG = "WifiQrCode";
static final String SCHEME_DPP = "DPP";
static final String SCHEME_ZXING_WIFI_NETWORK_CONFIG = "WIFI";
static final String PREFIX_DPP = "DPP:";
@@ -119,13 +120,13 @@
try {
wifiQrCode = new WifiQrCode(qrCode);
} catch(IllegalArgumentException e) {
+ Log.e(TAG, "Failed to create WifiQrCode!", e);
return null;
}
-
- if (SCHEME_DPP.equals(wifiQrCode.getScheme())) {
- return wifiQrCode;
+ if (wifiQrCode.getScheme() != UriParserResults.URI_SCHEME_DPP) {
+ Log.e(TAG, "wifiQrCode scheme is not DPP!");
+ return null;
}
-
- return null;
+ return wifiQrCode;
}
}
diff --git a/tests/robotests/src/com/android/settings/accessibility/ScreenFlashNotificationColorDialogFragmentTest.java b/tests/robotests/src/com/android/settings/accessibility/ScreenFlashNotificationColorDialogFragmentTest.java
index f3fa69d..ea48253 100644
--- a/tests/robotests/src/com/android/settings/accessibility/ScreenFlashNotificationColorDialogFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/ScreenFlashNotificationColorDialogFragmentTest.java
@@ -37,10 +37,13 @@
import android.content.Intent;
import android.graphics.Color;
+import android.os.Bundle;
+import android.provider.Settings;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.testing.FragmentScenario;
import androidx.lifecycle.Lifecycle;
+import androidx.test.core.app.ApplicationProvider;
import com.android.settings.R;
import com.android.settings.testutils.FakeTimer;
@@ -56,23 +59,26 @@
import java.util.List;
import java.util.Timer;
-import java.util.function.Consumer;
@RunWith(RobolectricTestRunner.class)
public class ScreenFlashNotificationColorDialogFragmentTest {
+ private static final int DEFAULT_COLOR = ROSE.mColorInt;
+
private FragmentScenario<TestScreenFlashNotificationColorDialogFragment> mFragmentScenario;
private ScreenFlashNotificationColorDialogFragment mDialogFragment;
private AlertDialog mAlertDialog;
private ColorSelectorLayout mColorSelectorLayout;
- private int mCurrentColor;
@Before
public void setUp() {
- mCurrentColor = ROSE.mColorInt;
+ Settings.System.putInt(ApplicationProvider.getApplicationContext().getContentResolver(),
+ Settings.System.SCREEN_FLASH_NOTIFICATION_COLOR, DEFAULT_COLOR);
+ Bundle fragmentArgs = new Bundle();
+ fragmentArgs.putInt(ScreenFlashNotificationColorDialogFragment.EXTRA_COLOR, DEFAULT_COLOR);
mFragmentScenario = FragmentScenario.launch(
TestScreenFlashNotificationColorDialogFragment.class,
- /* fragmentArgs= */ null,
+ fragmentArgs,
R.style.Theme_AlertDialog_SettingsLib,
Lifecycle.State.INITIALIZED);
setupFragment();
@@ -99,7 +105,7 @@
performClickOnDialog(BUTTON_NEUTRAL);
getTimerFromFragment().runOneTask();
- assertStartPreview(ROSE.mColorInt);
+ assertStartPreview(DEFAULT_COLOR);
}
@Test
@@ -168,20 +174,26 @@
}
@Test
- public void clickColorAndClickNegative_assertColor() {
+ public void clickColorAndClickNegative_assertDefaultColor() {
checkColorButton(AZURE);
performClickOnDialog(BUTTON_NEGATIVE);
assertThat(getTimerFromFragment()).isNull();
- assertThat(mCurrentColor).isEqualTo(ROSE.mColorInt);
+ assertThat(Settings.System.getInt(
+ ApplicationProvider.getApplicationContext().getContentResolver(),
+ Settings.System.SCREEN_FLASH_NOTIFICATION_COLOR, AZURE.mColorInt)).isEqualTo(
+ DEFAULT_COLOR);
}
@Test
- public void clickColorAndClickPositive_assertColor() {
+ public void clickColorAndClickPositive_assertSameColor() {
checkColorButton(BLUE);
performClickOnDialog(BUTTON_POSITIVE);
- assertThat(mCurrentColor).isEqualTo(BLUE.mColorInt);
+ assertThat(Settings.System.getInt(
+ ApplicationProvider.getApplicationContext().getContentResolver(),
+ Settings.System.SCREEN_FLASH_NOTIFICATION_COLOR, DEFAULT_COLOR)).isEqualTo(
+ BLUE.mColorInt);
}
private void checkColorButton(ScreenFlashNotificationColor color) {
@@ -201,11 +213,6 @@
}
private void setupFragment() {
- mFragmentScenario.onFragment(fragment -> {
- ReflectionHelpers.setField(fragment, "mCurrentColor", mCurrentColor);
- ReflectionHelpers.setField(fragment, "mConsumer",
- (Consumer<Integer>) selectedColor -> mCurrentColor = selectedColor);
- });
mFragmentScenario.moveToState(Lifecycle.State.RESUMED);
mFragmentScenario.onFragment(fragment -> {
diff --git a/tests/robotests/src/com/android/settings/accessibility/ScreenFlashNotificationPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/ScreenFlashNotificationPreferenceControllerTest.java
index 95a9438..d7c1a0f 100644
--- a/tests/robotests/src/com/android/settings/accessibility/ScreenFlashNotificationPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/ScreenFlashNotificationPreferenceControllerTest.java
@@ -57,8 +57,6 @@
import org.robolectric.annotation.Implements;
import org.robolectric.annotation.Resetter;
-import java.util.function.Consumer;
-
@RunWith(RobolectricTestRunner.class)
@Config(shadows = {
ScreenFlashNotificationPreferenceControllerTest
@@ -83,7 +81,6 @@
private FragmentManager mFragmentManager;
@Mock
private ScreenFlashNotificationColorDialogFragment mDialogFragment;
-
private ScreenFlashNotificationPreferenceController mController;
private ContentResolver mContentResolver;
@@ -92,6 +89,7 @@
MockitoAnnotations.initMocks(this);
FragmentActivity fragmentActivity = Robolectric.setupActivity(FragmentActivity.class);
Context context = fragmentActivity.getApplicationContext();
+
ShadowScreenFlashNotificationColorDialogFragment.setInstance(mDialogFragment);
ShadowFlashNotificationsUtils.setColorDescriptionText(COLOR_DESCRIPTION_TEXT);
@@ -99,8 +97,9 @@
mController = new ScreenFlashNotificationPreferenceController(context, PREFERENCE_KEY);
when(mPreferenceScreen.findPreference(PREFERENCE_KEY)).thenReturn(mPreference);
when(mPreference.getKey()).thenReturn(PREFERENCE_KEY);
- mController.setParentFragment(mParentFragment);
when(mParentFragment.getParentFragmentManager()).thenReturn(mFragmentManager);
+
+ mController.setParentFragment(mParentFragment);
}
@After
@@ -181,6 +180,7 @@
@Test
public void handlePreferenceTreeClick() {
mController.handlePreferenceTreeClick(mPreference);
+
verify(mDialogFragment).show(any(FragmentManager.class), anyString());
}
@@ -194,7 +194,7 @@
@Implementation
protected static ScreenFlashNotificationColorDialogFragment getInstance(
- int initialColor, Consumer<Integer> colorConsumer) {
+ int initialColor) {
return sInstance;
}
diff --git a/tests/robotests/src/com/android/settings/accessibility/shortcuts/FloatingButtonShortcutOptionControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/shortcuts/FloatingButtonShortcutOptionControllerTest.java
index 20f5d5d..0952b09 100644
--- a/tests/robotests/src/com/android/settings/accessibility/shortcuts/FloatingButtonShortcutOptionControllerTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/shortcuts/FloatingButtonShortcutOptionControllerTest.java
@@ -16,37 +16,46 @@
package com.android.settings.accessibility.shortcuts;
-import static android.provider.Settings.Secure.ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU;
-import static android.provider.Settings.Secure.ACCESSIBILITY_BUTTON_MODE_GESTURE;
-
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.spy;
+
import android.content.ComponentName;
import android.content.Context;
-import android.provider.Settings;
+import android.platform.test.annotations.EnableFlags;
+import android.platform.test.flag.junit.SetFlagsRule;
+import android.provider.Flags;
import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceScreen;
import androidx.test.core.app.ApplicationProvider;
import com.android.settings.R;
+import com.android.settings.testutils.AccessibilityTestUtils;
+import com.android.settings.testutils.shadow.SettingsShadowResources;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
import java.util.Set;
/**
* Tests for {@link FloatingButtonShortcutOptionController}
*/
+@Config(shadows = SettingsShadowResources.class)
@RunWith(RobolectricTestRunner.class)
public class FloatingButtonShortcutOptionControllerTest {
+ @Rule
+ public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+
private static final String PREF_KEY = "prefKey";
private static final String TARGET =
new ComponentName("FakePackage", "FakeClass").flattenToString();
- private final Context mContext = ApplicationProvider.getApplicationContext();
+ private final Context mContext = spy(ApplicationProvider.getApplicationContext());
private FloatingButtonShortcutOptionController mController;
private ShortcutOptionPreference mShortcutOptionPreference;
@@ -61,7 +70,6 @@
mShortcutOptionPreference.setKey(PREF_KEY);
mPreferenceScreen = new PreferenceManager(mContext).createPreferenceScreen(mContext);
mPreferenceScreen.addPreference(mShortcutOptionPreference);
- setFloatingButtonEnabled(true);
}
@Test
@@ -95,23 +103,26 @@
@Test
public void isShortcutAvailable_floatingMenuEnabled_returnTrue() {
- setFloatingButtonEnabled(true);
+ AccessibilityTestUtils.setSoftwareShortcutMode(
+ mContext, /* gestureNavEnabled= */ false, /* floatingButtonEnabled= */ true);
assertThat(mController.isShortcutAvailable()).isTrue();
}
@Test
public void isShortcutAvailable_floatingMenuDisabled_returnFalse() {
- setFloatingButtonEnabled(false);
+ AccessibilityTestUtils.setSoftwareShortcutMode(
+ mContext, /* gestureNavEnabled= */ false, /* floatingButtonEnabled= */ false);
assertThat(mController.isShortcutAvailable()).isFalse();
}
- private void setFloatingButtonEnabled(boolean enable) {
- int mode = enable
- ? ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU : ACCESSIBILITY_BUTTON_MODE_GESTURE;
+ @Test
+ @EnableFlags(Flags.FLAG_A11Y_STANDALONE_GESTURE_ENABLED)
+ public void isShortcutAvailable_gestureNavigationMode_returnsTrue() {
+ AccessibilityTestUtils.setSoftwareShortcutMode(
+ mContext, /* gestureNavEnabled= */ true, /* floatingButtonEnabled= */ false);
- Settings.Secure.putInt(mContext.getContentResolver(),
- Settings.Secure.ACCESSIBILITY_BUTTON_MODE, mode);
+ assertThat(mController.isShortcutAvailable()).isTrue();
}
}
diff --git a/tests/robotests/src/com/android/settings/accessibility/shortcuts/GestureShortcutOptionControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/shortcuts/GestureShortcutOptionControllerTest.java
index 0149cc3..1d46cae 100644
--- a/tests/robotests/src/com/android/settings/accessibility/shortcuts/GestureShortcutOptionControllerTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/shortcuts/GestureShortcutOptionControllerTest.java
@@ -16,6 +16,8 @@
package com.android.settings.accessibility.shortcuts;
+import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.GESTURE;
+import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.SOFTWARE;
import static com.android.settings.testutils.AccessibilityTestUtils.setupMockAccessibilityManager;
import static com.google.common.truth.Truth.assertThat;
@@ -25,6 +27,10 @@
import android.content.ComponentName;
import android.content.Context;
+import android.platform.test.annotations.DisableFlags;
+import android.platform.test.annotations.EnableFlags;
+import android.platform.test.flag.junit.SetFlagsRule;
+import android.provider.Flags;
import android.view.accessibility.AccessibilityManager;
import androidx.preference.PreferenceManager;
@@ -37,6 +43,7 @@
import com.android.settingslib.utils.StringUtil;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
@@ -50,6 +57,8 @@
@Config(shadows = SettingsShadowResources.class)
@RunWith(RobolectricTestRunner.class)
public class GestureShortcutOptionControllerTest {
+ @Rule
+ public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
private static final String PREF_KEY = "prefKey";
private static final String TARGET =
new ComponentName("FakePackage", "FakeClass").flattenToString();
@@ -137,6 +146,18 @@
}
@Test
+ @EnableFlags(Flags.FLAG_A11Y_STANDALONE_GESTURE_ENABLED)
+ public void getSummary_standaloneGestureFlagOn_verifyNoCustomizeA11yButtonTest() {
+ enableTouchExploration(true);
+ String expected = StringUtil.getIcuPluralsString(
+ mContext,
+ /* count= */ 3,
+ R.string.accessibility_shortcut_edit_dialog_summary_gesture);
+
+ assertThat(mController.getSummary().toString()).isEqualTo(expected);
+ }
+
+ @Test
public void isShortcutAvailable_inSuw_returnFalse() {
mController.setInSetupWizard(true);
@@ -144,6 +165,7 @@
}
@Test
+ @DisableFlags(Flags.FLAG_A11Y_STANDALONE_GESTURE_ENABLED)
public void isShortcutAvailable_notInSuwUseGestureNavSystemUseFab_returnFalse() {
mController.setInSetupWizard(false);
AccessibilityTestUtils.setSoftwareShortcutMode(
@@ -179,6 +201,28 @@
assertThat(mController.isShortcutAvailable()).isFalse();
}
+ @EnableFlags(Flags.FLAG_A11Y_STANDALONE_GESTURE_ENABLED)
+ @Test
+ public void isShortcutAvailable_floatingMenuEnabled_gestureNavEnabled_returnsTrue() {
+ mController.setInSetupWizard(false);
+ AccessibilityTestUtils.setSoftwareShortcutMode(
+ mContext, /* gestureNavEnabled= */ true, /* floatingButtonEnabled= */ true);
+
+ assertThat(mController.isShortcutAvailable()).isTrue();
+ }
+
+ @EnableFlags(Flags.FLAG_A11Y_STANDALONE_GESTURE_ENABLED)
+ @Test
+ public void getShortcutType_gesture() {
+ assertThat(mController.getShortcutType()).isEqualTo(GESTURE);
+ }
+
+ @DisableFlags(Flags.FLAG_A11Y_STANDALONE_GESTURE_ENABLED)
+ @Test
+ public void getShortcutType_software() {
+ assertThat(mController.getShortcutType()).isEqualTo(SOFTWARE);
+ }
+
private void enableTouchExploration(boolean enable) {
AccessibilityManager am = setupMockAccessibilityManager(mContext);
when(am.isTouchExplorationEnabled()).thenReturn(enable);
diff --git a/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsFragmentTest.java b/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsFragmentTest.java
index b3e1c5d..ca76c1e 100644
--- a/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsFragmentTest.java
@@ -54,6 +54,7 @@
import android.os.CancellationSignal;
import android.os.Looper;
import android.os.UserHandle;
+import android.os.Vibrator;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
import android.provider.Settings;
@@ -128,6 +129,9 @@
mAuthenticationCallbackArgumentCaptor = ArgumentCaptor.forClass(
FingerprintManager.AuthenticationCallback.class);
+ @Mock
+ private Vibrator mVibrator;
+
private FingerprintAuthenticateSidecar mFingerprintAuthenticateSidecar;
private FingerprintRemoveSidecar mFingerprintRemoveSidecar;
@@ -141,6 +145,7 @@
doReturn(mContext).when(mFragment).getContext();
doReturn(mBiometricManager).when(mContext).getSystemService(BiometricManager.class);
doReturn(true).when(mFingerprintManager).isHardwareDetected();
+ doReturn(mVibrator).when(mContext).getSystemService(Vibrator.class);
when(mBiometricManager.canAuthenticate(
BiometricManager.Authenticators.MANDATORY_BIOMETRICS))
.thenReturn(BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE);
@@ -288,6 +293,28 @@
}
@Test
+ @Ignore("b/353726774")
+ public void fingerprintVibratesOnAuthSuccess() {
+ setUpFragment(false);
+
+ doNothing().when(mFingerprintManager).authenticate(any(),
+ mCancellationSignalArgumentCaptor.capture(),
+ mAuthenticationCallbackArgumentCaptor.capture(), any(), anyInt());
+
+ mFingerprintAuthenticateSidecar.startAuthentication(1);
+
+ assertThat(mAuthenticationCallbackArgumentCaptor.getValue()).isNotNull();
+ assertThat(mCancellationSignalArgumentCaptor.getValue()).isNotNull();
+
+ mAuthenticationCallbackArgumentCaptor.getValue()
+ .onAuthenticationSucceeded(new FingerprintManager.AuthenticationResult(null,
+ new Fingerprint("finger 1", 1, 1), 0 /* userId */, false));
+
+ shadowOf(Looper.getMainLooper()).idle();
+ verify(mVibrator).vibrate(FingerprintSettings.SUCCESS_VIBRATION_EFFECT);
+ }
+
+ @Test
public void testNotIndexable_whenDisabled() {
doReturn(mPackageManager).when(mContext).getPackageManager();
doReturn(false)
diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDevicePreferenceTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDevicePreferenceTest.java
index 03113421..ba90ccf 100644
--- a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDevicePreferenceTest.java
+++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDevicePreferenceTest.java
@@ -18,10 +18,10 @@
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -32,22 +32,31 @@
import android.graphics.drawable.Drawable;
import android.os.UserManager;
import android.util.Pair;
-import android.view.ContextThemeWrapper;
+
+import androidx.test.core.app.ApplicationProvider;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.shadow.ShadowAlertDialogCompat;
+import com.android.settings.testutils.shadow.ShadowBluetoothUtils;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
+import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
+import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import org.robolectric.util.ReflectionHelpers;
@@ -57,18 +66,21 @@
import java.util.List;
@RunWith(RobolectricTestRunner.class)
-@Config(shadows = {ShadowAlertDialogCompat.class})
+@Config(shadows = {ShadowAlertDialogCompat.class,
+ com.android.settings.testutils.shadow.ShadowBluetoothUtils.class})
public class BluetoothDevicePreferenceTest {
private static final boolean SHOW_DEVICES_WITHOUT_NAMES = true;
- private static final String MAC_ADDRESS = "04:52:C7:0B:D8:3C";
- private static final String MAC_ADDRESS_2 = "05:52:C7:0B:D8:3C";
- private static final String MAC_ADDRESS_3 = "06:52:C7:0B:D8:3C";
- private static final String MAC_ADDRESS_4 = "07:52:C7:0B:D8:3C";
+ private static final String TEST_MAC_ADDRESS = "04:52:C7:0B:D8:3C";
+ private static final String TEST_MAC_ADDRESS_1 = "05:52:C7:0B:D8:3C";
+ private static final String TEST_MAC_ADDRESS_2 = "06:52:C7:0B:D8:3C";
+ private static final String TEST_MAC_ADDRESS_3 = "07:52:C7:0B:D8:3C";
private static final Comparator<BluetoothDevicePreference> COMPARATOR =
Comparator.naturalOrder();
private static final String FAKE_DESCRIPTION = "fake_description";
+ private static final int TEST_DEVICE_GROUP_ID = 1;
- private Context mContext;
+ @Rule
+ public final MockitoRule mockito = MockitoJUnit.rule();
@Mock
private CachedBluetoothDevice mCachedBluetoothDevice;
@Mock
@@ -89,35 +101,37 @@
private Drawable mDrawable;
@Mock
private BluetoothAdapter mBluetoothAdapter;
+ @Mock
+ private LocalBluetoothManager mLocalBluetoothManager;
+ @Mock
+ private CachedBluetoothDeviceManager mDeviceManager;
+ private Context mContext = ApplicationProvider.getApplicationContext();
private FakeFeatureFactory mFakeFeatureFactory;
private MetricsFeatureProvider mMetricsFeatureProvider;
+
private BluetoothDevicePreference mPreference;
private List<BluetoothDevicePreference> mPreferenceList = new ArrayList<>();
@Before
public void setUp() {
- MockitoAnnotations.initMocks(this);
- Context context = spy(RuntimeEnvironment.application.getApplicationContext());
- mContext = new ContextThemeWrapper(context, R.style.Theme_Settings);
+ mContext.setTheme(R.style.Theme_Settings);
mFakeFeatureFactory = FakeFeatureFactory.setupForTest();
mMetricsFeatureProvider = mFakeFeatureFactory.getMetricsFeatureProvider();
- when(mCachedBluetoothDevice.getAddress()).thenReturn(MAC_ADDRESS);
- when(mCachedBluetoothDevice.getDrawableWithDescription())
- .thenReturn(new Pair<>(mDrawable, FAKE_DESCRIPTION));
- when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice);
- when(mCachedDevice1.getAddress()).thenReturn(MAC_ADDRESS_2);
- when(mCachedDevice1.getDrawableWithDescription())
- .thenReturn(new Pair<>(mDrawable, FAKE_DESCRIPTION));
- when(mCachedDevice1.getDevice()).thenReturn(mBluetoothDevice1);
- when(mCachedDevice2.getAddress()).thenReturn(MAC_ADDRESS_3);
- when(mCachedDevice2.getDrawableWithDescription())
- .thenReturn(new Pair<>(mDrawable, FAKE_DESCRIPTION));
- when(mCachedDevice2.getDevice()).thenReturn(mBluetoothDevice2);
- when(mCachedDevice3.getAddress()).thenReturn(MAC_ADDRESS_4);
- when(mCachedDevice3.getDrawableWithDescription())
- .thenReturn(new Pair<>(mDrawable, FAKE_DESCRIPTION));
- when(mCachedDevice3.getDevice()).thenReturn(mBluetoothDevice3);
+ ShadowBluetoothUtils.sLocalBluetoothManager = mLocalBluetoothManager;
+ mLocalBluetoothManager = Utils.getLocalBtManager(mContext);
+ when(mLocalBluetoothManager.getCachedDeviceManager()).thenReturn(mDeviceManager);
+ prepareCachedBluetoothDevice(mCachedBluetoothDevice, TEST_MAC_ADDRESS,
+ new Pair<>(mDrawable, FAKE_DESCRIPTION), TEST_DEVICE_GROUP_ID, mBluetoothDevice);
+ prepareCachedBluetoothDevice(mCachedDevice1, TEST_MAC_ADDRESS_1,
+ new Pair<>(mDrawable, FAKE_DESCRIPTION), TEST_DEVICE_GROUP_ID, mBluetoothDevice1);
+ prepareCachedBluetoothDevice(mCachedDevice2, TEST_MAC_ADDRESS_2,
+ new Pair<>(mDrawable, FAKE_DESCRIPTION), TEST_DEVICE_GROUP_ID, mBluetoothDevice2);
+ prepareCachedBluetoothDevice(mCachedDevice3, TEST_MAC_ADDRESS_3,
+ new Pair<>(mDrawable, FAKE_DESCRIPTION), TEST_DEVICE_GROUP_ID, mBluetoothDevice3);
+ when(mDeviceManager.getCachedDevicesCopy()).thenReturn(
+ ImmutableList.of(mCachedBluetoothDevice));
+
mPreference = new BluetoothDevicePreference(mContext, mCachedBluetoothDevice,
SHOW_DEVICES_WITHOUT_NAMES, BluetoothDevicePreference.SortType.TYPE_DEFAULT);
mPreference.mBluetoothAdapter = mBluetoothAdapter;
@@ -301,7 +315,8 @@
// callback is not removed.
mPreference.onAttached();
- verify(mCachedBluetoothDevice, times(1)).registerCallback(any());
+ verify(mCachedBluetoothDevice, times(1)).registerCallback(eq(mContext.getMainExecutor()),
+ any());
verify(mBluetoothAdapter, times(1)).addOnMetadataChangedListener(any(), any(), any());
}
@@ -313,7 +328,99 @@
mPreference.onAttached();
verify(mCachedBluetoothDevice, times(1)).unregisterCallback(any());
- verify(mCachedBluetoothDevice, times(2)).registerCallback(any());
+ verify(mCachedBluetoothDevice, times(2)).registerCallback(eq(mContext.getMainExecutor()),
+ any());
verify(mBluetoothAdapter, times(2)).addOnMetadataChangedListener(any(), any(), any());
}
+
+ @Test
+ public void onDeviceAttributesChanged_updatePreference() {
+ when(mCachedBluetoothDevice.getName()).thenReturn("Name");
+ mPreference.onAttached();
+ final String updatedName = "updatedName";
+ when(mCachedBluetoothDevice.getName()).thenReturn(updatedName);
+
+ getCachedBluetoothDeviceCallback().onDeviceAttributesChanged();
+
+ assertThat(mPreference.getTitle().toString()).isEqualTo(updatedName);
+ }
+
+ @Test
+ public void onAttached_memberDevicesAdded_registerAllCallback() {
+ when(mCachedBluetoothDevice.getMemberDevice()).thenReturn(
+ ImmutableSet.of(mCachedDevice1, mCachedDevice2, mCachedDevice3));
+ when(mDeviceManager.getCachedDevicesCopy()).thenReturn(
+ ImmutableList.of(mCachedBluetoothDevice, mCachedDevice1, mCachedDevice2,
+ mCachedDevice3));
+ mPreference = new BluetoothDevicePreference(mContext, mCachedBluetoothDevice,
+ SHOW_DEVICES_WITHOUT_NAMES, BluetoothDevicePreference.SortType.TYPE_DEFAULT);
+
+ mPreference.onAttached();
+
+ verify(mCachedBluetoothDevice).registerCallback(eq(mContext.getMainExecutor()), any());
+ verify(mCachedDevice1).registerCallback(eq(mContext.getMainExecutor()), any());
+ verify(mCachedDevice2).registerCallback(eq(mContext.getMainExecutor()), any());
+ verify(mCachedDevice3).registerCallback(eq(mContext.getMainExecutor()), any());
+ }
+
+ @Test
+ public void onDetached_memberDevicesAdded_unregisterAllCallback() {
+ when(mCachedBluetoothDevice.getMemberDevice()).thenReturn(
+ ImmutableSet.of(mCachedDevice1, mCachedDevice2, mCachedDevice3));
+ when(mDeviceManager.getCachedDevicesCopy()).thenReturn(
+ ImmutableList.of(mCachedBluetoothDevice, mCachedDevice1, mCachedDevice2,
+ mCachedDevice3));
+ mPreference = new BluetoothDevicePreference(mContext, mCachedBluetoothDevice,
+ SHOW_DEVICES_WITHOUT_NAMES, BluetoothDevicePreference.SortType.TYPE_DEFAULT);
+
+ mPreference.onAttached();
+ mPreference.onDetached();
+
+ verify(mCachedBluetoothDevice).unregisterCallback(any());
+ verify(mCachedDevice1).unregisterCallback(any());
+ verify(mCachedDevice2).unregisterCallback(any());
+ verify(mCachedDevice3).unregisterCallback(any());
+ }
+
+ @Test
+ public void onDeviceAttributesChanged_memberDevicesChanged_registerOnlyExistDeviceCallback() {
+ when(mCachedBluetoothDevice.getMemberDevice()).thenReturn(
+ ImmutableSet.of(mCachedDevice1, mCachedDevice2, mCachedDevice3));
+ when(mDeviceManager.getCachedDevicesCopy()).thenReturn(
+ ImmutableList.of(mCachedBluetoothDevice, mCachedDevice1, mCachedDevice2,
+ mCachedDevice3));
+ mPreference = new BluetoothDevicePreference(mContext, mCachedBluetoothDevice,
+ SHOW_DEVICES_WITHOUT_NAMES, BluetoothDevicePreference.SortType.TYPE_DEFAULT);
+ mPreference.onAttached();
+ when(mCachedBluetoothDevice.getMemberDevice()).thenReturn(
+ ImmutableSet.of(mCachedDevice1, mCachedDevice2));
+ when(mDeviceManager.getCachedDevicesCopy()).thenReturn(
+ ImmutableList.of(mCachedBluetoothDevice, mCachedDevice1, mCachedDevice2));
+
+ getCachedBluetoothDeviceCallback().onDeviceAttributesChanged();
+
+ verify(mCachedBluetoothDevice, times(2)).registerCallback(eq(mContext.getMainExecutor()),
+ any());
+ verify(mCachedDevice1, times(2)).registerCallback(eq(mContext.getMainExecutor()), any());
+ verify(mCachedDevice2, times(2)).registerCallback(eq(mContext.getMainExecutor()), any());
+ verify(mCachedDevice3, times(1)).registerCallback(eq(mContext.getMainExecutor()), any());
+ }
+
+ private void prepareCachedBluetoothDevice(CachedBluetoothDevice cachedDevice, String address,
+ Pair<Drawable, String> drawableWithDescription, int groupId,
+ BluetoothDevice bluetoothDevice) {
+ when(cachedDevice.getAddress()).thenReturn(address);
+ when(cachedDevice.getDrawableWithDescription()).thenReturn(drawableWithDescription);
+ when(cachedDevice.getGroupId()).thenReturn(groupId);
+ when(cachedDevice.getDevice()).thenReturn(bluetoothDevice);
+ }
+
+ private CachedBluetoothDevice.Callback getCachedBluetoothDeviceCallback() {
+ ArgumentCaptor<CachedBluetoothDevice.Callback> callbackCaptor = ArgumentCaptor.forClass(
+ CachedBluetoothDevice.Callback.class);
+ verify(mCachedBluetoothDevice).registerCallback(eq(mContext.getMainExecutor()),
+ callbackCaptor.capture());
+
+ return callbackCaptor.getValue();
+ }
}
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogFragmentTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogFragmentTest.java
index 20c225c..7227f37 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogFragmentTest.java
@@ -93,7 +93,6 @@
new Pair[] {TEST_EVENT_DATA};
private Fragment mParent;
- private AudioSharingDialogFragment mFragment;
private FakeFeatureFactory mFeatureFactory;
@Before
@@ -107,7 +106,6 @@
shadowBluetoothAdapter.setIsLeAudioBroadcastAssistantSupported(
BluetoothStatusCodes.FEATURE_SUPPORTED);
mFeatureFactory = FakeFeatureFactory.setupForTest();
- mFragment = new AudioSharingDialogFragment();
mParent = new Fragment();
FragmentController.setupFragment(
mParent, FragmentActivity.class, /* containerViewId= */ 0, /* bundle= */ null);
@@ -120,7 +118,8 @@
@Test
public void getMetricsCategory_correctValue() {
- assertThat(mFragment.getMetricsCategory())
+ AudioSharingDialogFragment fragment = new AudioSharingDialogFragment();
+ assertThat(fragment.getMetricsCategory())
.isEqualTo(SettingsEnums.DIALOG_AUDIO_SHARING_ADD_DEVICE);
}
@@ -145,7 +144,7 @@
}
@Test
- public void onCreateDialog_flagOn_noConnectedDevice() {
+ public void onCreateDialog_flagOn_noExtraConnectedDevice() {
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
AudioSharingDialogFragment.show(
mParent, new ArrayList<>(), EMPTY_EVENT_LISTENER, TEST_EVENT_DATA_LIST);
@@ -157,42 +156,67 @@
assertThat(description).isNotNull();
ImageView image = dialog.findViewById(R.id.description_image);
assertThat(image).isNotNull();
- Button shareBtn = dialog.findViewById(R.id.positive_btn);
- assertThat(shareBtn).isNotNull();
- Button cancelBtn = dialog.findViewById(R.id.negative_btn);
- assertThat(cancelBtn).isNotNull();
+ Button positiveBtn = dialog.findViewById(R.id.positive_btn);
+ assertThat(positiveBtn).isNotNull();
+ Button negativeBtn = dialog.findViewById(R.id.negative_btn);
+ assertThat(negativeBtn).isNotNull();
assertThat(dialog.isShowing()).isTrue();
assertThat(description.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(description.getText().toString())
.isEqualTo(mParent.getString(R.string.audio_sharing_dialog_connect_device_content));
assertThat(image.getVisibility()).isEqualTo(View.VISIBLE);
- assertThat(shareBtn.getVisibility()).isEqualTo(View.GONE);
- assertThat(cancelBtn.getVisibility()).isEqualTo(View.GONE);
+ assertThat(positiveBtn.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(positiveBtn.getText().toString())
+ .isEqualTo(mParent.getString(R.string.audio_sharing_pair_button_label));
+ assertThat(negativeBtn.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(negativeBtn.getText().toString())
+ .isEqualTo(mParent.getString(R.string.audio_sharing_qrcode_button_label));
}
@Test
- public void onCreateDialog_noConnectedDevice_dialogDismiss() {
+ public void onCreateDialog_noExtraConnectedDevice_pairNewDevice() {
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
AudioSharingDialogFragment.show(
mParent, new ArrayList<>(), EMPTY_EVENT_LISTENER, TEST_EVENT_DATA_LIST);
shadowMainLooper().idle();
AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
assertThat(dialog).isNotNull();
- View btnView = dialog.findViewById(android.R.id.button2);
- assertThat(btnView).isNotNull();
- btnView.performClick();
+ Button pairBtn = dialog.findViewById(R.id.positive_btn);
+ assertThat(pairBtn).isNotNull();
+ pairBtn.performClick();
shadowMainLooper().idle();
+ verify(mFeatureFactory.metricsFeatureProvider)
+ .action(
+ any(Context.class),
+ eq(SettingsEnums.ACTION_AUDIO_SHARING_DIALOG_POSITIVE_BTN_CLICKED),
+ eq(TEST_EVENT_DATA));
assertThat(dialog.isShowing()).isFalse();
+ }
+
+ @Test
+ public void onCreateDialog_noExtraConnectedDevice_showQRCode() {
+ mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
+ AudioSharingDialogFragment.show(
+ mParent, new ArrayList<>(), EMPTY_EVENT_LISTENER, TEST_EVENT_DATA_LIST);
+ shadowMainLooper().idle();
+ AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
+ assertThat(dialog).isNotNull();
+ Button qrCodeBtn = dialog.findViewById(R.id.negative_btn);
+ assertThat(qrCodeBtn).isNotNull();
+ qrCodeBtn.performClick();
+ shadowMainLooper().idle();
+
verify(mFeatureFactory.metricsFeatureProvider)
.action(
any(Context.class),
eq(SettingsEnums.ACTION_AUDIO_SHARING_DIALOG_NEGATIVE_BTN_CLICKED),
eq(TEST_EVENT_DATA));
+ assertThat(dialog.isShowing()).isFalse();
}
@Test
- public void onCreateDialog_flagOn_singleConnectedDevice() {
+ public void onCreateDialog_flagOn_singleExtraConnectedDevice() {
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
ArrayList<AudioSharingDeviceItem> list = new ArrayList<>();
list.add(TEST_DEVICE_ITEM1);
@@ -207,10 +231,10 @@
assertThat(description).isNotNull();
ImageView image = dialog.findViewById(R.id.description_image);
assertThat(image).isNotNull();
- Button shareBtn = dialog.findViewById(R.id.positive_btn);
- assertThat(shareBtn).isNotNull();
- Button cancelBtn = dialog.findViewById(R.id.negative_btn);
- assertThat(cancelBtn).isNotNull();
+ Button positiveBtn = dialog.findViewById(R.id.positive_btn);
+ assertThat(positiveBtn).isNotNull();
+ Button negativeBtn = dialog.findViewById(R.id.negative_btn);
+ assertThat(negativeBtn).isNotNull();
assertThat(dialog.isShowing()).isTrue();
assertThat(title.getText().toString())
.isEqualTo(
@@ -220,12 +244,16 @@
assertThat(description.getText().toString())
.isEqualTo(mParent.getString(R.string.audio_sharing_dialog_share_content));
assertThat(image.getVisibility()).isEqualTo(View.GONE);
- assertThat(shareBtn.getVisibility()).isEqualTo(View.VISIBLE);
- assertThat(cancelBtn.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(positiveBtn.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(positiveBtn.getText().toString())
+ .isEqualTo(mParent.getString(R.string.audio_sharing_share_button_label));
+ assertThat(negativeBtn.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(negativeBtn.getText().toString())
+ .isEqualTo(mParent.getString(R.string.audio_sharing_no_thanks_button_label));
}
@Test
- public void onCreateDialog_singleConnectedDevice_dialogDismiss() {
+ public void onCreateDialog_singleExtraConnectedDevice_dialogDismiss() {
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
ArrayList<AudioSharingDeviceItem> list = new ArrayList<>();
list.add(TEST_DEVICE_ITEM1);
@@ -248,7 +276,7 @@
}
@Test
- public void onCreateDialog_singleConnectedDevice_shareClicked() {
+ public void onCreateDialog_singleExtraConnectedDevice_shareClicked() {
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
ArrayList<AudioSharingDeviceItem> list = new ArrayList<>();
list.add(TEST_DEVICE_ITEM1);
@@ -285,7 +313,7 @@
}
@Test
- public void onCreateDialog_flagOn_multipleConnectedDevice() {
+ public void onCreateDialog_flagOn_multipleExtraConnectedDevice() {
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
ArrayList<AudioSharingDeviceItem> list = new ArrayList<>();
list.add(TEST_DEVICE_ITEM1);
@@ -313,12 +341,14 @@
assertThat(image.getVisibility()).isEqualTo(View.GONE);
assertThat(shareBtn.getVisibility()).isEqualTo(View.GONE);
assertThat(cancelBtn.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(cancelBtn.getText().toString())
+ .isEqualTo(mParent.getString(com.android.settings.R.string.cancel));
assertThat(recyclerView.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(recyclerView.getAdapter().getItemCount()).isEqualTo(3);
}
@Test
- public void onCreateDialog_multipleConnectedDevice_dialogDismiss() {
+ public void onCreateDialog_multipleExtraConnectedDevice_dialogDismiss() {
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
ArrayList<AudioSharingDeviceItem> list = new ArrayList<>();
list.add(TEST_DEVICE_ITEM1);
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingReceiverTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingReceiverTest.java
index deed229..db6eb8c 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingReceiverTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingReceiverTest.java
@@ -25,7 +25,7 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoInteractions;
import static org.mockito.Mockito.when;
@@ -164,8 +164,7 @@
AudioSharingReceiver audioSharingReceiver = getAudioSharingReceiver(intent);
audioSharingReceiver.onReceive(mContext, intent);
- verify(mNm, times(1))
- .notify(eq(R.drawable.ic_bt_le_audio_sharing), any(Notification.class));
+ verify(mNm).notify(eq(R.drawable.ic_bt_le_audio_sharing), any(Notification.class));
verify(mFeatureFactory.metricsFeatureProvider)
.action(mContext, SettingsEnums.ACTION_SHOW_AUDIO_SHARING_NOTIFICATION);
}
@@ -181,7 +180,7 @@
AudioSharingReceiver audioSharingReceiver = getAudioSharingReceiver(intent);
audioSharingReceiver.onReceive(mContext, intent);
- verify(mNm, times(1)).cancel(R.drawable.ic_bt_le_audio_sharing);
+ verify(mNm).cancel(R.drawable.ic_bt_le_audio_sharing);
verify(mFeatureFactory.metricsFeatureProvider)
.action(mContext, SettingsEnums.ACTION_CANCEL_AUDIO_SHARING_NOTIFICATION);
}
@@ -199,8 +198,10 @@
}
@Test
- public void broadcastReceiver_receiveAudioSharingStopIntent_stopBroadcast() {
+ public void
+ broadcastReceiver_receiveAudioSharingStopIntent_notInBroadcast_cancelNotification() {
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
+ when(mBroadcast.isEnabled(null)).thenReturn(false);
int broadcastId = 1;
when(mBroadcast.getLatestBroadcastId()).thenReturn(broadcastId);
@@ -209,7 +210,25 @@
AudioSharingReceiver audioSharingReceiver = getAudioSharingReceiver(intent);
audioSharingReceiver.onReceive(mContext, intent);
- verify(mBroadcast, times(1)).stopBroadcast(broadcastId);
+ verify(mBroadcast, never()).stopBroadcast(broadcastId);
+ verify(mNm).cancel(R.drawable.ic_bt_le_audio_sharing);
+ verify(mFeatureFactory.metricsFeatureProvider)
+ .action(mContext, SettingsEnums.ACTION_CANCEL_AUDIO_SHARING_NOTIFICATION);
+ }
+
+ @Test
+ public void broadcastReceiver_receiveAudioSharingStopIntent_inBroadcast_stopBroadcast() {
+ mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
+ when(mBroadcast.isEnabled(null)).thenReturn(true);
+ int broadcastId = 1;
+ when(mBroadcast.getLatestBroadcastId()).thenReturn(broadcastId);
+
+ Intent intent = new Intent(ACTION_LE_AUDIO_SHARING_STOP);
+ intent.setPackage(mContext.getPackageName());
+ AudioSharingReceiver audioSharingReceiver = getAudioSharingReceiver(intent);
+ audioSharingReceiver.onReceive(mContext, intent);
+
+ verify(mBroadcast).stopBroadcast(broadcastId);
verify(mFeatureFactory.metricsFeatureProvider)
.action(mContext, SettingsEnums.ACTION_STOP_AUDIO_SHARING_FROM_NOTIFICATION);
}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryTipsCardPreferenceTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryTipsCardPreferenceTest.java
deleted file mode 100644
index 5f86301..0000000
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryTipsCardPreferenceTest.java
+++ /dev/null
@@ -1,293 +0,0 @@
-/*
- * Copyright (C) 2023 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.fuelgauge.batteryusage;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.app.settings.SettingsEnums;
-import android.content.Context;
-import android.content.Intent;
-import android.provider.Settings;
-import android.util.Pair;
-import android.view.View;
-
-import com.android.settings.DisplaySettings;
-import com.android.settings.R;
-import com.android.settings.SettingsActivity;
-import com.android.settings.testutils.BatteryTestUtils;
-import com.android.settings.testutils.FakeFeatureFactory;
-import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-
-import java.util.Map;
-import java.util.Optional;
-import java.util.TimeZone;
-
-@RunWith(RobolectricTestRunner.class)
-public final class BatteryTipsCardPreferenceTest {
-
- private Context mContext;
- private FakeFeatureFactory mFeatureFactory;
- private BatteryTipsCardPreference mBatteryTipsCardPreference;
- private PowerUsageAdvanced mPowerUsageAdvanced;
- private BatteryTipsController mBatteryTipsController;
- private BatteryChartPreferenceController mBatteryChartPreferenceController;
-
- @Mock private View mFakeView;
- @Mock private BatteryUsageBreakdownController mBatteryUsageBreakdownController;
- @Mock private BatteryDiffEntry mFakeEntry;
-
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
- TimeZone.setDefault(TimeZone.getTimeZone("GMT+8"));
- mContext = spy(RuntimeEnvironment.application);
- mFeatureFactory = FakeFeatureFactory.setupForTest();
- mBatteryTipsCardPreference = new BatteryTipsCardPreference(mContext, /* attrs= */ null);
- mBatteryTipsController = new BatteryTipsController(mContext);
- mBatteryChartPreferenceController =
- spy(new BatteryChartPreferenceController(mContext, null, null));
- mBatteryChartPreferenceController.mPrefContext = mContext;
- mBatteryTipsController.mCardPreference = mBatteryTipsCardPreference;
-
- mPowerUsageAdvanced = spy(new PowerUsageAdvanced());
- doReturn(mContext).when(mPowerUsageAdvanced).getContext();
- mPowerUsageAdvanced.mBatteryTipsController = mBatteryTipsController;
- mPowerUsageAdvanced.mBatteryChartPreferenceController = mBatteryChartPreferenceController;
- mPowerUsageAdvanced.mBatteryUsageBreakdownController = mBatteryUsageBreakdownController;
- mPowerUsageAdvanced.mBatteryLevelData =
- Optional.of(
- new BatteryLevelData(
- Map.of(
- 1694354400000L, 1, // 2023-09-10 22:00:00
- 1694361600000L, 2, // 2023-09-11 00:00:00
- 1694368800000L, 3))); // 2023-09-11 02:00:00
- doReturn("TestEntriesKey").when(mFakeEntry).getKey();
- }
-
- @Test
- public void constructor_returnExpectedResult() {
- assertThat(mBatteryTipsCardPreference.getLayoutResource())
- .isEqualTo(R.layout.battery_tips_card);
- }
-
- @Test
- public void onClick_mainBtnOfSettingsAnomalyLaunchPage_getAdaptiveBrightnessLauncher() {
- final ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
- PowerAnomalyEvent adaptiveBrightnessAnomaly =
- BatteryTestUtils.createAdaptiveBrightnessAnomalyEvent(/* changeSettings= */ false);
- when(mFeatureFactory.powerUsageFeatureProvider.isBatteryTipsEnabled()).thenReturn(true);
- when(mFakeView.getId()).thenReturn(R.id.main_button);
- doNothing().when(mContext).startActivity(captor.capture());
-
- mPowerUsageAdvanced.onDisplayAnomalyEventUpdated(
- adaptiveBrightnessAnomaly, adaptiveBrightnessAnomaly);
- mBatteryTipsCardPreference.onClick(mFakeView);
-
- assertThat(mBatteryTipsCardPreference.isVisible()).isFalse();
- verify(mContext).startActivity(any(Intent.class));
- final Intent intent = captor.getValue();
- assertThat(intent.getStringExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT))
- .isEqualTo(DisplaySettings.class.getName());
- assertThat(intent.getIntExtra(MetricsFeatureProvider.EXTRA_SOURCE_METRICS_CATEGORY, -1))
- .isEqualTo(SettingsEnums.DISPLAY);
- verify(mFeatureFactory.metricsFeatureProvider)
- .action(
- SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
- SettingsEnums.ACTION_BATTERY_TIPS_CARD_SHOW,
- SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
- BatteryTipsController.ANOMALY_KEY,
- PowerAnomalyKey.KEY_BRIGHTNESS.getNumber());
- verify(mFeatureFactory.metricsFeatureProvider)
- .action(
- SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
- SettingsEnums.ACTION_BATTERY_TIPS_CARD_ACCEPT,
- SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
- BatteryTipsController.ANOMALY_KEY,
- PowerAnomalyKey.KEY_BRIGHTNESS.getNumber());
- }
-
- @Test
- public void onClick_mainBtnOfSettingsAnomalyChangeSettings_settingsChanged()
- throws Settings.SettingNotFoundException {
- Settings.System.putInt(
- mContext.getContentResolver(),
- Settings.System.SCREEN_BRIGHTNESS_MODE,
- Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL);
- final ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
- PowerAnomalyEvent adaptiveBrightnessAnomaly =
- BatteryTestUtils.createAdaptiveBrightnessAnomalyEvent(/* changeSettings= */ true);
- when(mFeatureFactory.powerUsageFeatureProvider.isBatteryTipsEnabled()).thenReturn(true);
- when(mFakeView.getId()).thenReturn(R.id.main_button);
- doNothing().when(mContext).startActivity(captor.capture());
-
- mPowerUsageAdvanced.onDisplayAnomalyEventUpdated(
- adaptiveBrightnessAnomaly, adaptiveBrightnessAnomaly);
- mBatteryTipsCardPreference.onClick(mFakeView);
-
- assertThat(mBatteryTipsCardPreference.isVisible()).isFalse();
- assertThat(
- Settings.System.getInt(
- mContext.getContentResolver(),
- Settings.System.SCREEN_BRIGHTNESS_MODE))
- .isEqualTo(Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC);
- verify(mContext, never()).startActivity(any(Intent.class));
- verify(mFeatureFactory.metricsFeatureProvider)
- .action(
- SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
- SettingsEnums.ACTION_BATTERY_TIPS_CARD_SHOW,
- SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
- BatteryTipsController.ANOMALY_KEY,
- PowerAnomalyKey.KEY_BRIGHTNESS.getNumber());
- verify(mFeatureFactory.metricsFeatureProvider)
- .action(
- SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
- SettingsEnums.ACTION_BATTERY_TIPS_CARD_ACCEPT,
- SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
- BatteryTipsController.ANOMALY_KEY,
- PowerAnomalyKey.KEY_BRIGHTNESS.getNumber());
- }
-
- @Test
- public void onClick_dismissBtnOfSettingsAnomaly_cardDismissAndLogged() {
- final PowerAnomalyEvent screenTimeoutAnomaly =
- BatteryTestUtils.createScreenTimeoutAnomalyEvent();
- DatabaseUtils.removeDismissedPowerAnomalyKeys(mContext);
- when(mFeatureFactory.powerUsageFeatureProvider.isBatteryTipsEnabled()).thenReturn(true);
- when(mFakeView.getId()).thenReturn(R.id.dismiss_button);
-
- mPowerUsageAdvanced.onDisplayAnomalyEventUpdated(
- screenTimeoutAnomaly, screenTimeoutAnomaly);
- mBatteryTipsCardPreference.onClick(mFakeView);
-
- assertThat(mBatteryTipsCardPreference.isVisible()).isFalse();
- assertThat(DatabaseUtils.getDismissedPowerAnomalyKeys(mContext)).hasSize(1);
- assertThat(DatabaseUtils.getDismissedPowerAnomalyKeys(mContext))
- .contains(PowerAnomalyKey.KEY_SCREEN_TIMEOUT.name());
- verify(mFeatureFactory.metricsFeatureProvider)
- .action(
- SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
- SettingsEnums.ACTION_BATTERY_TIPS_CARD_SHOW,
- SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
- BatteryTipsController.ANOMALY_KEY,
- PowerAnomalyKey.KEY_SCREEN_TIMEOUT.getNumber());
- verify(mFeatureFactory.metricsFeatureProvider)
- .action(
- SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
- SettingsEnums.ACTION_BATTERY_TIPS_CARD_DISMISS,
- SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
- BatteryTipsController.ANOMALY_KEY,
- PowerAnomalyKey.KEY_SCREEN_TIMEOUT.getNumber());
- }
-
- @Test
- public void onClick_mainBtnOfAppsAnomaly_selectHighlightSlot() {
- final PowerAnomalyEvent appsAnomaly = BatteryTestUtils.createAppAnomalyEvent();
- when(mFeatureFactory.powerUsageFeatureProvider.isBatteryTipsEnabled()).thenReturn(true);
- when(mFakeView.getId()).thenReturn(R.id.main_button);
- doNothing().when(mBatteryChartPreferenceController).selectHighlightSlotIndex();
- when(mPowerUsageAdvanced.findRelatedBatteryDiffEntry(any())).thenReturn(mFakeEntry);
-
- mPowerUsageAdvanced.onDisplayAnomalyEventUpdated(appsAnomaly, appsAnomaly);
- assertHighlightSlotIndexPair(1, 0);
- mBatteryTipsCardPreference.onClick(mFakeView);
-
- assertThat(mBatteryTipsCardPreference.isVisible()).isFalse();
- verify(mContext, never()).startActivity(any(Intent.class));
- verify(mBatteryChartPreferenceController).onHighlightSlotIndexUpdate(eq(1), eq(0));
- verify(mBatteryChartPreferenceController).selectHighlightSlotIndex();
- verify(mFeatureFactory.metricsFeatureProvider)
- .action(
- SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
- SettingsEnums.ACTION_BATTERY_TIPS_CARD_SHOW,
- SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
- BatteryTipsController.ANOMALY_KEY,
- PowerAnomalyKey.KEY_APP_TOTAL_HIGHER_THAN_USUAL.getNumber());
- verify(mFeatureFactory.metricsFeatureProvider)
- .action(
- SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
- SettingsEnums.ACTION_BATTERY_TIPS_CARD_ACCEPT,
- SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
- BatteryTipsController.ANOMALY_KEY,
- PowerAnomalyKey.KEY_APP_TOTAL_HIGHER_THAN_USUAL.getNumber());
- }
-
- @Test
- public void onClick_dismissBtnOfAppsAnomaly_keepHighlightSlotIndex() {
- final PowerAnomalyEvent appsAnomaly = BatteryTestUtils.createAppAnomalyEvent();
- when(mFeatureFactory.powerUsageFeatureProvider.isBatteryTipsEnabled()).thenReturn(true);
- when(mFakeView.getId()).thenReturn(R.id.dismiss_button);
- when(mPowerUsageAdvanced.findRelatedBatteryDiffEntry(any())).thenReturn(mFakeEntry);
-
- mPowerUsageAdvanced.onDisplayAnomalyEventUpdated(appsAnomaly, appsAnomaly);
- assertHighlightSlotIndexPair(1, 0);
- mBatteryTipsCardPreference.onClick(mFakeView);
-
- assertThat(mBatteryTipsCardPreference.isVisible()).isFalse();
- verify(mContext, never()).startActivity(any(Intent.class));
- verify(mBatteryChartPreferenceController).onHighlightSlotIndexUpdate(eq(1), eq(0));
- verify(mBatteryChartPreferenceController, never()).selectHighlightSlotIndex();
- verify(mFeatureFactory.metricsFeatureProvider)
- .action(
- SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
- SettingsEnums.ACTION_BATTERY_TIPS_CARD_SHOW,
- SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
- BatteryTipsController.ANOMALY_KEY,
- PowerAnomalyKey.KEY_APP_TOTAL_HIGHER_THAN_USUAL.getNumber());
- verify(mFeatureFactory.metricsFeatureProvider)
- .action(
- SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
- SettingsEnums.ACTION_BATTERY_TIPS_CARD_DISMISS,
- SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
- BatteryTipsController.ANOMALY_KEY,
- PowerAnomalyKey.KEY_APP_TOTAL_HIGHER_THAN_USUAL.getNumber());
- }
-
- private void assertHighlightSlotIndexPair(
- int dailyHighlightSlotIndex, int hourlyHighlightSlotIndex) {
- assertThat(mPowerUsageAdvanced.mBatteryLevelData.isPresent()).isTrue();
- assertThat(mPowerUsageAdvanced.mHighlightEventWrapper.isPresent()).isTrue();
- Pair<Integer, Integer> slotIndexPair =
- mPowerUsageAdvanced
- .mHighlightEventWrapper
- .get()
- .getHighlightSlotPair(mPowerUsageAdvanced.mBatteryLevelData.get());
- assertThat(slotIndexPair)
- .isEqualTo(Pair.create(dailyHighlightSlotIndex, hourlyHighlightSlotIndex));
- assertThat(mPowerUsageAdvanced.mBatteryChartPreferenceController.mDailyHighlightSlotIndex)
- .isEqualTo(dailyHighlightSlotIndex);
- assertThat(mPowerUsageAdvanced.mBatteryChartPreferenceController.mHourlyHighlightSlotIndex)
- .isEqualTo(hourlyHighlightSlotIndex);
- }
-}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryTipsControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryTipsControllerTest.java
index 954437f..6c29036b 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryTipsControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryTipsControllerTest.java
@@ -16,8 +16,13 @@
package com.android.settings.fuelgauge.batteryusage;
+
+import static com.google.common.truth.Truth.assertThat;
+
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -29,11 +34,11 @@
import com.android.settings.R;
import com.android.settings.testutils.BatteryTestUtils;
import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settings.widget.TipCardPreference;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
@@ -47,134 +52,156 @@
private Context mContext;
private FakeFeatureFactory mFeatureFactory;
private BatteryTipsController mBatteryTipsController;
-
- @Mock private BatteryTipsCardPreference mBatteryTipsCardPreference;
+ private TipCardPreference mCardPreference;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
Locale.setDefault(new Locale("en_US"));
- org.robolectric.shadows.ShadowSettings.set24HourTimeFormat(false);
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
+
mContext = spy(RuntimeEnvironment.application);
final Resources resources = spy(mContext.getResources());
resources.getConfiguration().setLocales(new LocaleList(new Locale("en_US")));
doReturn(resources).when(mContext).getResources();
mFeatureFactory = FakeFeatureFactory.setupForTest();
- mBatteryTipsController = new BatteryTipsController(mContext);
- mBatteryTipsController.mCardPreference = mBatteryTipsCardPreference;
+ mBatteryTipsController = spy(new BatteryTipsController(mContext));
+ mCardPreference = new TipCardPreference(mContext);
+ mBatteryTipsController.mCardPreference = mCardPreference;
}
@Test
public void handleBatteryTipsCardUpdated_null_hidePreference() {
mBatteryTipsController.handleBatteryTipsCardUpdated(/* powerAnomalyEvents= */ null, false);
- verify(mBatteryTipsCardPreference).setVisible(false);
+ assertThat(mCardPreference.isVisible()).isFalse();
}
@Test
public void handleBatteryTipsCardUpdated_adaptiveBrightnessAnomaly_showAnomaly() {
- PowerAnomalyEvent event = BatteryTestUtils.createAdaptiveBrightnessAnomalyEvent();
+ AnomalyEventWrapper anomalyEventWrapper =
+ spy(
+ new AnomalyEventWrapper(
+ mContext,
+ BatteryTestUtils.createAdaptiveBrightnessAnomalyEvent(true)));
when(mFeatureFactory.powerUsageFeatureProvider.isBatteryTipsEnabled()).thenReturn(true);
- mBatteryTipsController.handleBatteryTipsCardUpdated(
- new AnomalyEventWrapper(mContext, event), false);
+ mBatteryTipsController.handleBatteryTipsCardUpdated(anomalyEventWrapper, false);
- // Check pre-defined string
- verify(mBatteryTipsCardPreference)
- .setTitle("Turn on adaptive brightness to extend battery life");
- verify(mBatteryTipsCardPreference).setIconResourceId(R.drawable.ic_battery_tips_lightbulb);
- verify(mBatteryTipsCardPreference).setButtonColorResourceId(R.color.color_accent_selector);
- verify(mBatteryTipsCardPreference).setMainButtonLabel("View Settings");
- verify(mBatteryTipsCardPreference).setDismissButtonLabel("Got it");
- // Check proto info
- verify(mBatteryTipsCardPreference).setVisible(true);
- verify(mFeatureFactory.metricsFeatureProvider)
- .action(
- SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
- SettingsEnums.ACTION_BATTERY_TIPS_CARD_SHOW,
- SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
- BatteryTipsController.ANOMALY_KEY,
- PowerAnomalyKey.KEY_BRIGHTNESS.getNumber());
+ assertThat(mCardPreference.getTitle())
+ .isEqualTo("Turn on adaptive brightness to extend battery life");
+ assertThat(mCardPreference.getPrimaryButtonText()).isEqualTo("Got it");
+ assertThat(mCardPreference.getSecondaryButtonText()).isEqualTo("View Settings");
+ assertThat(mCardPreference.getIconResId()).isEqualTo(R.drawable.ic_battery_tips_lightbulb);
+ assertThat(mCardPreference.getTintColorResId()).isEqualTo(R.color.color_accent_selector);
+ assertThat(mCardPreference.getPrimaryButtonVisibility()).isTrue();
+ assertThat(mCardPreference.getSecondaryButtonVisibility()).isTrue();
+ assertCardButtonActionAndMetrics(anomalyEventWrapper);
}
@Test
public void handleBatteryTipsCardUpdated_screenTimeoutAnomaly_showAnomaly() {
- PowerAnomalyEvent event = BatteryTestUtils.createScreenTimeoutAnomalyEvent();
+ AnomalyEventWrapper anomalyEventWrapper =
+ spy(
+ new AnomalyEventWrapper(
+ mContext, BatteryTestUtils.createScreenTimeoutAnomalyEvent(true)));
when(mFeatureFactory.powerUsageFeatureProvider.isBatteryTipsEnabled()).thenReturn(true);
- mBatteryTipsController.handleBatteryTipsCardUpdated(
- new AnomalyEventWrapper(mContext, event), false);
+ mBatteryTipsController.handleBatteryTipsCardUpdated(anomalyEventWrapper, false);
- verify(mBatteryTipsCardPreference).setTitle("Reduce screen timeout to extend battery life");
- verify(mBatteryTipsCardPreference).setIconResourceId(R.drawable.ic_battery_tips_lightbulb);
- verify(mBatteryTipsCardPreference).setButtonColorResourceId(R.color.color_accent_selector);
- verify(mBatteryTipsCardPreference).setMainButtonLabel("View Settings");
- verify(mBatteryTipsCardPreference).setDismissButtonLabel("Got it");
- verify(mBatteryTipsCardPreference).setVisible(true);
- verify(mFeatureFactory.metricsFeatureProvider)
- .action(
- SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
- SettingsEnums.ACTION_BATTERY_TIPS_CARD_SHOW,
- SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
- BatteryTipsController.ANOMALY_KEY,
- PowerAnomalyKey.KEY_SCREEN_TIMEOUT.getNumber());
+ assertThat(mCardPreference.getTitle())
+ .isEqualTo("Reduce screen timeout to extend battery life");
+ assertThat(mCardPreference.getPrimaryButtonText()).isEqualTo("Got it");
+ assertThat(mCardPreference.getSecondaryButtonText()).isEqualTo("View Settings");
+ assertThat(mCardPreference.getIconResId()).isEqualTo(R.drawable.ic_battery_tips_lightbulb);
+ assertThat(mCardPreference.getTintColorResId()).isEqualTo(R.color.color_accent_selector);
+ assertThat(mCardPreference.getPrimaryButtonVisibility()).isTrue();
+ assertThat(mCardPreference.getSecondaryButtonVisibility()).isTrue();
+ assertCardButtonActionAndMetrics(anomalyEventWrapper);
}
@Test
public void handleBatteryTipsCardUpdated_screenTimeoutAnomalyHasTitle_showAnomaly() {
- PowerAnomalyEvent event = BatteryTestUtils.createScreenTimeoutAnomalyEvent();
+ PowerAnomalyEvent anomalyEvent = BatteryTestUtils.createScreenTimeoutAnomalyEvent(true);
String testTitle = "TestTitle";
- event =
- event.toBuilder()
+ anomalyEvent =
+ anomalyEvent.toBuilder()
.setWarningBannerInfo(
- event.getWarningBannerInfo().toBuilder()
+ anomalyEvent.getWarningBannerInfo().toBuilder()
.setTitleString(testTitle)
.build())
.build();
+ AnomalyEventWrapper anomalyEventWrapper =
+ spy(new AnomalyEventWrapper(mContext, anomalyEvent));
when(mFeatureFactory.powerUsageFeatureProvider.isBatteryTipsEnabled()).thenReturn(true);
- mBatteryTipsController.handleBatteryTipsCardUpdated(
- new AnomalyEventWrapper(mContext, event), false);
+ mBatteryTipsController.handleBatteryTipsCardUpdated(anomalyEventWrapper, false);
- verify(mBatteryTipsCardPreference).setTitle(testTitle);
- verify(mBatteryTipsCardPreference).setIconResourceId(R.drawable.ic_battery_tips_lightbulb);
- verify(mBatteryTipsCardPreference).setButtonColorResourceId(R.color.color_accent_selector);
- verify(mBatteryTipsCardPreference).setMainButtonLabel("View Settings");
- verify(mBatteryTipsCardPreference).setDismissButtonLabel("Got it");
- verify(mBatteryTipsCardPreference).setVisible(true);
- verify(mFeatureFactory.metricsFeatureProvider)
- .action(
- SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
- SettingsEnums.ACTION_BATTERY_TIPS_CARD_SHOW,
- SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
- BatteryTipsController.ANOMALY_KEY,
- PowerAnomalyKey.KEY_SCREEN_TIMEOUT.getNumber());
+ assertThat(mCardPreference.getTitle()).isEqualTo(testTitle);
+ assertThat(mCardPreference.getPrimaryButtonText()).isEqualTo("Got it");
+ assertThat(mCardPreference.getSecondaryButtonText()).isEqualTo("View Settings");
+ assertThat(mCardPreference.getIconResId()).isEqualTo(R.drawable.ic_battery_tips_lightbulb);
+ assertThat(mCardPreference.getTintColorResId()).isEqualTo(R.color.color_accent_selector);
+ assertThat(mCardPreference.getPrimaryButtonVisibility()).isTrue();
+ assertThat(mCardPreference.getSecondaryButtonVisibility()).isTrue();
+ assertCardButtonActionAndMetrics(anomalyEventWrapper);
}
@Test
public void handleBatteryTipsCardUpdated_appAnomaly_showAnomaly() {
- PowerAnomalyEvent event = BatteryTestUtils.createAppAnomalyEvent();
+ AnomalyEventWrapper anomalyEventWrapper =
+ spy(new AnomalyEventWrapper(mContext, BatteryTestUtils.createAppAnomalyEvent()));
when(mFeatureFactory.powerUsageFeatureProvider.isBatteryTipsEnabled()).thenReturn(true);
- AnomalyEventWrapper eventWrapper = new AnomalyEventWrapper(mContext, event);
- eventWrapper.setRelatedBatteryDiffEntry(new BatteryDiffEntry(mContext, "", "Chrome", 0));
- mBatteryTipsController.handleBatteryTipsCardUpdated(eventWrapper, false);
+ anomalyEventWrapper.setRelatedBatteryDiffEntry(
+ new BatteryDiffEntry(mContext, "", "Chrome", 0));
+ mBatteryTipsController.setOnAnomalyConfirmListener(
+ () -> mBatteryTipsController.acceptTipsCard());
+ mBatteryTipsController.handleBatteryTipsCardUpdated(anomalyEventWrapper, true);
- verify(mBatteryTipsCardPreference).setTitle("Chrome used more battery than usual");
- verify(mBatteryTipsCardPreference)
- .setIconResourceId(R.drawable.ic_battery_tips_warning_icon);
- verify(mBatteryTipsCardPreference)
- .setButtonColorResourceId(R.color.color_battery_anomaly_app_warning_selector);
- verify(mBatteryTipsCardPreference).setMainButtonLabel("Check");
- verify(mBatteryTipsCardPreference).setDismissButtonLabel("Got it");
- verify(mBatteryTipsCardPreference).setVisible(true);
+ assertThat(mCardPreference.getTitle()).isEqualTo("Chrome used more battery than usual");
+ assertThat(mCardPreference.getPrimaryButtonText()).isEqualTo("Got it");
+ assertThat(mCardPreference.getSecondaryButtonText()).isEqualTo("Check");
+ assertThat(mCardPreference.getIconResId())
+ .isEqualTo(R.drawable.ic_battery_tips_warning_icon);
+ assertThat(mCardPreference.getTintColorResId())
+ .isEqualTo(R.color.color_battery_anomaly_app_warning_selector);
+ assertThat(mCardPreference.getPrimaryButtonVisibility()).isTrue();
+ assertThat(mCardPreference.getSecondaryButtonVisibility()).isTrue();
+ assertThat(mCardPreference.isVisible()).isTrue();
+ assertCardButtonActionAndMetrics(anomalyEventWrapper);
+ }
+
+ private void assertCardButtonActionAndMetrics(final AnomalyEventWrapper anomalyEventWrapper) {
+ when(anomalyEventWrapper.updateSystemSettingsIfAvailable()).thenReturn(true);
+
+ final int powerAnomalyKeyNumber = anomalyEventWrapper.getAnomalyKeyNumber();
+ assertCardMetrics(SettingsEnums.ACTION_BATTERY_TIPS_CARD_SHOW, powerAnomalyKeyNumber);
+ assertThat(mCardPreference.isVisible()).isTrue();
+
+ // Check accept button action
+ mCardPreference.setVisible(true);
+ mCardPreference.getSecondaryButtonAction().invoke();
+ assertCardMetrics(SettingsEnums.ACTION_BATTERY_TIPS_CARD_ACCEPT, powerAnomalyKeyNumber);
+ assertThat(mCardPreference.isVisible()).isFalse();
+ final boolean isAppAnomalyCard = powerAnomalyKeyNumber > 1;
+ verify(anomalyEventWrapper, isAppAnomalyCard ? never() : times(1))
+ .updateSystemSettingsIfAvailable();
+
+ // Check reject button action
+ mCardPreference.setVisible(true);
+ mCardPreference.getPrimaryButtonAction().invoke();
+ assertCardMetrics(SettingsEnums.ACTION_BATTERY_TIPS_CARD_DISMISS, powerAnomalyKeyNumber);
+ assertThat(mCardPreference.isVisible()).isFalse();
+ }
+
+ private void assertCardMetrics(final int action, final int powerAnomalyKeyNumber) {
verify(mFeatureFactory.metricsFeatureProvider)
.action(
SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
- SettingsEnums.ACTION_BATTERY_TIPS_CARD_SHOW,
+ action,
SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
BatteryTipsController.ANOMALY_KEY,
- PowerAnomalyKey.KEY_APP_TOTAL_HIGHER_THAN_USUAL.getNumber());
+ powerAnomalyKeyNumber);
}
}
diff --git a/tests/robotests/src/com/android/settings/notification/app/AppChannelsBypassingDndPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/app/AppChannelsBypassingDndPreferenceControllerTest.java
index b8c9b5b..e0381f2 100644
--- a/tests/robotests/src/com/android/settings/notification/app/AppChannelsBypassingDndPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/app/AppChannelsBypassingDndPreferenceControllerTest.java
@@ -50,6 +50,7 @@
import org.robolectric.shadows.ShadowPausedAsyncTask;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
@RunWith(RobolectricTestRunner.class)
@@ -185,12 +186,7 @@
NotificationManager.IMPORTANCE_DEFAULT));
ParceledListSlice<NotificationChannelGroup> groups = new ParceledListSlice<>(
- new ArrayList<NotificationChannelGroup>() {
- {
- add(group1);
- add(group2);
- }
- }
+ Arrays.asList(group1, group2)
);
when(mBackend.getGroups(eq(mAppRow.pkg), eq(mAppRow.uid))).thenReturn(groups);
diff --git a/tests/robotests/src/com/android/settings/testutils/AccessibilityTestUtils.java b/tests/robotests/src/com/android/settings/testutils/AccessibilityTestUtils.java
index 5d895d9..4d69821 100644
--- a/tests/robotests/src/com/android/settings/testutils/AccessibilityTestUtils.java
+++ b/tests/robotests/src/com/android/settings/testutils/AccessibilityTestUtils.java
@@ -20,6 +20,8 @@
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;
+import static com.google.common.truth.Truth.assertThat;
+
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -46,20 +48,15 @@
public static void setSoftwareShortcutMode(
Context context, boolean gestureNavEnabled, boolean floatingButtonEnabled) {
- int mode = floatingButtonEnabled ? ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU : -1;
+ int buttonMode = floatingButtonEnabled ? ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU : -1;
+ int navMode = gestureNavEnabled ? NAV_BAR_MODE_GESTURAL : NAV_BAR_MODE_3BUTTON;
Settings.Secure.putInt(context.getContentResolver(),
- Settings.Secure.ACCESSIBILITY_BUTTON_MODE, mode);
-
- if (gestureNavEnabled) {
- SettingsShadowResources.overrideResource(
- com.android.internal.R.integer.config_navBarInteractionMode,
- NAV_BAR_MODE_GESTURAL);
- } else {
- SettingsShadowResources.overrideResource(
- com.android.internal.R.integer.config_navBarInteractionMode,
- NAV_BAR_MODE_3BUTTON);
- }
+ Settings.Secure.ACCESSIBILITY_BUTTON_MODE, buttonMode);
+ SettingsShadowResources.overrideResource(
+ com.android.internal.R.integer.config_navBarInteractionMode, navMode);
+ assertThat(context.getResources().getInteger(
+ com.android.internal.R.integer.config_navBarInteractionMode)).isEqualTo(navMode);
}
/**
diff --git a/tests/robotests/src/com/android/settings/testutils/BatteryTestUtils.java b/tests/robotests/src/com/android/settings/testutils/BatteryTestUtils.java
index a151632..951f2f0 100644
--- a/tests/robotests/src/com/android/settings/testutils/BatteryTestUtils.java
+++ b/tests/robotests/src/com/android/settings/testutils/BatteryTestUtils.java
@@ -264,18 +264,28 @@
/** Create a power anomaly event proto of screen timeout. */
public static PowerAnomalyEvent createScreenTimeoutAnomalyEvent() {
+ return createScreenTimeoutAnomalyEvent(false);
+ }
+
+ /** Create a power anomaly event proto of screen timeout. */
+ public static PowerAnomalyEvent createScreenTimeoutAnomalyEvent(boolean changeSettings) {
+ WarningBannerInfo.Builder warningBannerInfoBuilder =
+ WarningBannerInfo.newBuilder()
+ .setMainButtonDestination(ScreenTimeoutSettings.class.getName())
+ .setMainButtonSourceMetricsCategory(SettingsEnums.SCREEN_TIMEOUT)
+ .setMainButtonSourceHighlightKey("60000");
+ if (changeSettings) {
+ warningBannerInfoBuilder
+ .setMainButtonConfigSettingsName(Settings.System.SCREEN_OFF_TIMEOUT)
+ .setMainButtonConfigSettingsValue(60000);
+ }
return PowerAnomalyEvent.newBuilder()
.setEventId("ScreenTimeoutAnomaly")
.setType(PowerAnomalyType.TYPE_SETTINGS_BANNER)
.setKey(PowerAnomalyKey.KEY_SCREEN_TIMEOUT)
.setDismissRecordKey(PowerAnomalyKey.KEY_SCREEN_TIMEOUT.name())
.setScore(1.1f)
- .setWarningBannerInfo(
- WarningBannerInfo.newBuilder()
- .setMainButtonDestination(ScreenTimeoutSettings.class.getName())
- .setMainButtonSourceMetricsCategory(SettingsEnums.SCREEN_TIMEOUT)
- .setMainButtonSourceHighlightKey("60000")
- .build())
+ .setWarningBannerInfo(warningBannerInfoBuilder.build())
.build();
}
diff --git a/tests/spa_unit/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceControllerHelperTest.kt b/tests/spa_unit/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceControllerHelperTest.kt
new file mode 100644
index 0000000..8edc90f
--- /dev/null
+++ b/tests/spa_unit/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceControllerHelperTest.kt
@@ -0,0 +1,96 @@
+/*
+ * 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.network.telephony
+
+import android.content.Context
+import android.telephony.CarrierConfigManager
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.kotlin.spy
+
+@RunWith(AndroidJUnit4::class)
+class EnabledNetworkModePreferenceControllerHelperTest {
+
+ private var context: Context = spy(ApplicationProvider.getApplicationContext()) {}
+
+ @Before
+ fun setUp() {
+ CarrierConfigRepository.resetForTest()
+ CarrierConfigRepository.setBooleanForTest(
+ SUB_ID, CarrierConfigManager.KEY_CARRIER_CONFIG_APPLIED_BOOL, true)
+ }
+
+ @Test
+ fun getNetworkModePreferenceType_hideCarrierNetworkSettings_returnNone() {
+ CarrierConfigRepository.setBooleanForTest(
+ SUB_ID, CarrierConfigManager.KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL, true)
+
+ val networkModePreferenceType = getNetworkModePreferenceType(context, SUB_ID)
+
+ assertThat(networkModePreferenceType).isEqualTo(NetworkModePreferenceType.None)
+ }
+
+ @Test
+ fun getNetworkModePreferenceType_hidePreferredNetworkType_returnNone() {
+ CarrierConfigRepository.setBooleanForTest(
+ SUB_ID, CarrierConfigManager.KEY_HIDE_PREFERRED_NETWORK_TYPE_BOOL, true)
+
+ val networkModePreferenceType = getNetworkModePreferenceType(context, SUB_ID)
+
+ assertThat(networkModePreferenceType).isEqualTo(NetworkModePreferenceType.None)
+ }
+
+ @Test
+ fun getNetworkModePreferenceType_carrierConfigNotReady_returnNone() {
+ CarrierConfigRepository.setBooleanForTest(
+ SUB_ID, CarrierConfigManager.KEY_CARRIER_CONFIG_APPLIED_BOOL, false)
+
+ val networkModePreferenceType = getNetworkModePreferenceType(context, SUB_ID)
+
+ assertThat(networkModePreferenceType).isEqualTo(NetworkModePreferenceType.None)
+ }
+
+ @Test
+ fun getNetworkModePreferenceType_isWorldPhone_returnPreferredNetworkMode() {
+ CarrierConfigRepository.setBooleanForTest(
+ SUB_ID, CarrierConfigManager.KEY_WORLD_PHONE_BOOL, true)
+
+ val networkModePreferenceType = getNetworkModePreferenceType(context, SUB_ID)
+
+ assertThat(networkModePreferenceType)
+ .isEqualTo(NetworkModePreferenceType.PreferredNetworkMode)
+ }
+
+ @Test
+ fun getNetworkModePreferenceType_notWorldPhone_returnEnabledNetworkMode() {
+ CarrierConfigRepository.setBooleanForTest(
+ SUB_ID, CarrierConfigManager.KEY_WORLD_PHONE_BOOL, false)
+
+ val networkModePreferenceType = getNetworkModePreferenceType(context, SUB_ID)
+
+ assertThat(networkModePreferenceType)
+ .isEqualTo(NetworkModePreferenceType.EnabledNetworkMode)
+ }
+
+ private companion object {
+ const val SUB_ID = 10
+ }
+}
diff --git a/tests/spa_unit/src/com/android/settings/network/telephony/MobileNetworkSettingsSearchIndexTest.kt b/tests/spa_unit/src/com/android/settings/network/telephony/MobileNetworkSettingsSearchIndexTest.kt
index 5e7e83c..bf51208 100644
--- a/tests/spa_unit/src/com/android/settings/network/telephony/MobileNetworkSettingsSearchIndexTest.kt
+++ b/tests/spa_unit/src/com/android/settings/network/telephony/MobileNetworkSettingsSearchIndexTest.kt
@@ -25,6 +25,7 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.settings.R
import com.android.settings.network.telephony.MobileNetworkSettingsSearchIndex.Companion.isMobileNetworkSettingsSearchable
+import com.android.settings.network.telephony.MobileNetworkSettingsSearchIndex.MobileNetworkSettingsSearchResult
import com.android.settings.spa.SpaSearchLanding.BundleValue
import com.android.settings.spa.SpaSearchLanding.SpaSearchLandingFragment
import com.android.settings.spa.SpaSearchLanding.SpaSearchLandingKey
@@ -62,10 +63,12 @@
private val mobileNetworkSettingsSearchIndex = MobileNetworkSettingsSearchIndex {
listOf(
object : MobileNetworkSettingsSearchIndex.MobileNetworkSettingsSearchItem {
- override val key = KEY
- override val title = TITLE
-
- override fun isAvailable(subId: Int) = subId == SUB_ID_1
+ override fun getSearchResult(subId: Int): MobileNetworkSettingsSearchResult? =
+ if (subId == SUB_ID_1) {
+ MobileNetworkSettingsSearchResult(key = KEY, title = TITLE)
+ } else {
+ null
+ }
})
}
diff --git a/tests/spa_unit/src/com/android/settings/spa/app/appinfo/AppNotificationPreferenceTest.kt b/tests/spa_unit/src/com/android/settings/spa/app/appinfo/AppNotificationPreferenceTest.kt
index 37f3a11..7a0ec8c 100644
--- a/tests/spa_unit/src/com/android/settings/spa/app/appinfo/AppNotificationPreferenceTest.kt
+++ b/tests/spa_unit/src/com/android/settings/spa/app/appinfo/AppNotificationPreferenceTest.kt
@@ -20,8 +20,8 @@
import android.content.pm.ApplicationInfo
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.platform.LocalContext
-import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.assertIsNotEnabled
+import androidx.compose.ui.test.hasText
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.onRoot
@@ -34,36 +34,35 @@
import com.android.settings.notification.app.AppNotificationSettings
import com.android.settings.spa.notification.IAppNotificationRepository
import com.android.settingslib.spa.testutils.delay
+import com.android.settingslib.spa.testutils.waitUntilExists
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.MockitoSession
-import org.mockito.Spy
import org.mockito.quality.Strictness
@RunWith(AndroidJUnit4::class)
class AppNotificationPreferenceTest {
- @get:Rule
- val composeTestRule = createComposeRule()
+ @get:Rule val composeTestRule = createComposeRule()
private lateinit var mockSession: MockitoSession
- @Spy
private val context: Context = ApplicationProvider.getApplicationContext()
- private val repository = object : IAppNotificationRepository {
- override fun getNotificationSummary(app: ApplicationInfo) = SUMMARY
- }
+ private val repository =
+ object : IAppNotificationRepository {
+ override fun getNotificationSummary(app: ApplicationInfo) = SUMMARY
+ }
@Before
fun setUp() {
- mockSession = ExtendedMockito.mockitoSession()
- .initMocks(this)
- .mockStatic(AppInfoDashboardFragment::class.java)
- .strictness(Strictness.LENIENT)
- .startMocking()
+ mockSession =
+ ExtendedMockito.mockitoSession()
+ .mockStatic(AppInfoDashboardFragment::class.java)
+ .strictness(Strictness.LENIENT)
+ .startMocking()
}
@After
@@ -75,25 +74,26 @@
fun title_displayed() {
setContent(APP)
- composeTestRule.onNodeWithText(context.getString(R.string.notifications_label))
- .assertIsDisplayed()
+ composeTestRule.waitUntilExists(hasText(context.getString(R.string.notifications_label)))
}
@Test
fun summary_displayed() {
setContent(APP)
- composeTestRule.onNodeWithText(SUMMARY).assertIsDisplayed()
+ composeTestRule.waitUntilExists(hasText(SUMMARY))
}
@Test
fun whenNotInstalled_disable() {
- setContent(ApplicationInfo().apply {
- packageName = PACKAGE_NAME
- uid = UID
- })
+ setContent(
+ ApplicationInfo().apply {
+ packageName = PACKAGE_NAME
+ uid = UID
+ })
- composeTestRule.onNodeWithText(context.getString(R.string.notifications_label))
+ composeTestRule
+ .onNodeWithText(context.getString(R.string.notifications_label))
.assertIsNotEnabled()
}
@@ -125,11 +125,12 @@
private companion object {
const val PACKAGE_NAME = "package.name"
const val UID = 123
- val APP = ApplicationInfo().apply {
- packageName = PACKAGE_NAME
- uid = UID
- flags = ApplicationInfo.FLAG_INSTALLED
- }
+ val APP =
+ ApplicationInfo().apply {
+ packageName = PACKAGE_NAME
+ uid = UID
+ flags = ApplicationInfo.FLAG_INSTALLED
+ }
const val SUMMARY = "Summary"
}
-}
\ No newline at end of file
+}
diff --git a/tests/unit/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceControllerTest.java b/tests/unit/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceControllerTest.java
index b3d095e..adc8dc0 100644
--- a/tests/unit/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceControllerTest.java
+++ b/tests/unit/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceControllerTest.java
@@ -18,9 +18,6 @@
import static androidx.lifecycle.Lifecycle.Event.ON_START;
-import static com.android.settings.core.BasePreferenceController.AVAILABLE;
-import static com.android.settings.core.BasePreferenceController.AVAILABLE_UNSEARCHABLE;
-import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE;
import static com.android.settings.network.telephony.MobileNetworkUtils.getRafFromNetworkType;
import static com.android.settings.network.telephony.TelephonyConstants.RadioAccessFamily.CDMA;
import static com.android.settings.network.telephony.TelephonyConstants.RadioAccessFamily.EVDO;
@@ -33,8 +30,6 @@
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
@@ -125,79 +120,6 @@
@UiThreadTest
@Test
- public void getAvailabilityStatus_hideCarrierNetworkSettings_returnUnavailable() {
- mPersistableBundle.putBoolean(
- CarrierConfigManager.KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL,
- true);
-
- assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
- }
-
- @UiThreadTest
- @Test
- public void getAvailabilityStatus_hidePreferredNetworkType_returnUnavailable() {
- mPersistableBundle.putBoolean(CarrierConfigManager.KEY_HIDE_PREFERRED_NETWORK_TYPE_BOOL,
- true);
-
- when(mServiceState.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
- when(mServiceState.getDataRegistrationState()).thenReturn(
- ServiceState.STATE_OUT_OF_SERVICE);
- assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
-
- when(mServiceState.getState()).thenReturn(ServiceState.STATE_IN_SERVICE);
- when(mServiceState.getDataRegistrationState()).thenReturn(ServiceState.STATE_IN_SERVICE);
-
- when(mServiceState.getRoaming()).thenReturn(false);
- assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
-
- when(mServiceState.getRoaming()).thenReturn(true);
- assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
- }
-
- @UiThreadTest
- @Test
- public void getAvailabilityStatus_carrierConfigNotReady_returnUnavailable() {
- mPersistableBundle.putBoolean(CarrierConfigManager.KEY_CARRIER_CONFIG_APPLIED_BOOL, false);
-
- assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
- }
-
- @UiThreadTest
- @Test
- public void getAvailabilityStatus_notWorldPhone_returnAvailable() {
- mPersistableBundle.putBoolean(CarrierConfigManager.KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL,
- false);
- mPersistableBundle.putBoolean(CarrierConfigManager.KEY_WORLD_PHONE_BOOL, false);
-
- assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
- }
-
- @UiThreadTest
- @Test
- public void getAvailabilityStatus_callStateIsIdle_returnAvailable() {
- mockEnabledNetworkMode(TelephonyManagerConstants.NETWORK_MODE_NR_LTE_GSM_WCDMA);
- mController.getTelephonyCallback().onCallStateChanged(TelephonyManager.CALL_STATE_IDLE);
-
- mController.updateState(mPreference);
-
- assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
- assertTrue(mPreference.isEnabled());
- }
-
- @UiThreadTest
- @Test
- public void getAvailabilityStatus_duringCalling_returnAvailable() {
- mockEnabledNetworkMode(TelephonyManagerConstants.NETWORK_MODE_NR_LTE_GSM_WCDMA);
- mController.getTelephonyCallback().onCallStateChanged(TelephonyManager.CALL_STATE_OFFHOOK);
-
- mController.updateState(mPreference);
-
- assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE_UNSEARCHABLE);
- assertFalse(mPreference.isEnabled());
- }
-
- @UiThreadTest
- @Test
public void updateState_LteWorldPhone_GlobalHasLte() {
mPersistableBundle.putBoolean(CarrierConfigManager.KEY_WORLD_MODE_ENABLED_BOOL, true);
diff --git a/tests/unit/src/com/android/settings/network/telephony/PreferredNetworkModePreferenceControllerTest.java b/tests/unit/src/com/android/settings/network/telephony/PreferredNetworkModePreferenceControllerTest.java
index 9dbfdde..f22ad3b 100644
--- a/tests/unit/src/com/android/settings/network/telephony/PreferredNetworkModePreferenceControllerTest.java
+++ b/tests/unit/src/com/android/settings/network/telephony/PreferredNetworkModePreferenceControllerTest.java
@@ -16,8 +16,6 @@
package com.android.settings.network.telephony;
-import static com.android.settings.core.BasePreferenceController.AVAILABLE;
-import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE;
import static com.android.settings.network.telephony.TelephonyConstants.RadioAccessFamily.GSM;
import static com.android.settings.network.telephony.TelephonyConstants.RadioAccessFamily.RAF_TD_SCDMA;
import static com.android.settings.network.telephony.TelephonyConstants.RadioAccessFamily.WCDMA;
@@ -32,7 +30,6 @@
import android.content.Context;
import android.os.PersistableBundle;
-import android.telephony.CarrierConfigManager;
import android.telephony.ServiceState;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
@@ -92,43 +89,6 @@
}
@Test
- public void getAvailabilityStatus_hideCarrierNetworkSettings_returnUnavailable() {
- mPersistableBundle.putBoolean(CarrierConfigManager.KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL,
- true);
-
- assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
- }
-
- @Test
- public void getAvailabilityStatus_worldPhone_returnAvailable() {
- mPersistableBundle.putBoolean(CarrierConfigManager.KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL,
- false);
- mPersistableBundle.putBoolean(CarrierConfigManager.KEY_WORLD_PHONE_BOOL, true);
-
- assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
- }
-
- @Test
- public void getAvailabilityStatus_hidePreferredNetworkType_returnUnavailable() {
- mPersistableBundle.putBoolean(CarrierConfigManager.KEY_HIDE_PREFERRED_NETWORK_TYPE_BOOL,
- true);
-
- when(mServiceState.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
- when(mServiceState.getDataRegistrationState()).thenReturn(
- ServiceState.STATE_OUT_OF_SERVICE);
- assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
-
- when(mServiceState.getState()).thenReturn(ServiceState.STATE_IN_SERVICE);
- when(mServiceState.getDataRegistrationState()).thenReturn(ServiceState.STATE_IN_SERVICE);
-
- when(mServiceState.getRoaming()).thenReturn(false);
- assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
-
- when(mServiceState.getRoaming()).thenReturn(true);
- assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
- }
-
- @Test
public void updateState_updateByNetworkMode() {
// NETWORK_MODE_TDSCDMA_GSM_WCDMA = RAF_TD_SCDMA | GSM | WCDMA
when(mTelephonyManager.getAllowedNetworkTypesForReason(
diff --git a/tests/unit/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivityTest.java b/tests/unit/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivityTest.java
index 4d723dc1..34c8602 100644
--- a/tests/unit/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivityTest.java
+++ b/tests/unit/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivityTest.java
@@ -20,15 +20,33 @@
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 @@
@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 @@
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;
+ }
}