Merge "Swtich to use DefaultAccount related API to get and set default account for handling contacts." into main
diff --git a/aconfig/catalyst/accessibility.aconfig b/aconfig/catalyst/accessibility.aconfig
index 80a9d62..7837067 100644
--- a/aconfig/catalyst/accessibility.aconfig
+++ b/aconfig/catalyst/accessibility.aconfig
@@ -2,8 +2,15 @@
container: "system"
flag {
+ name: "catalyst_accessibility_color_and_motion"
+ namespace: "android_settings"
+ description: "Migrate Color and motion screen to the Catalyst infrastructure"
+ bug: "323791114"
+}
+
+flag {
name: "catalyst_text_reading_screen"
namespace: "android_settings"
description: "Flag for Display size and text"
bug: "323791114"
-}
\ No newline at end of file
+}
diff --git a/aconfig/catalyst/battery.aconfig b/aconfig/catalyst/battery.aconfig
index ce5c5c5..cec40f3 100644
--- a/aconfig/catalyst/battery.aconfig
+++ b/aconfig/catalyst/battery.aconfig
@@ -2,8 +2,15 @@
container: "system"
flag {
+ name: "catalyst_power_usage_summary_screen"
+ namespace: "android_settings"
+ description: "Flag for Battery screen"
+ bug: "323791114"
+}
+
+flag {
name: "catalyst_battery_saver_screen"
namespace: "android_settings"
description: "Flag for Battery Saver"
bug: "323791114"
-}
+}
\ No newline at end of file
diff --git a/aconfig/catalyst/connected_devices.aconfig b/aconfig/catalyst/connected_devices.aconfig
new file mode 100644
index 0000000..7a335fa
--- /dev/null
+++ b/aconfig/catalyst/connected_devices.aconfig
@@ -0,0 +1,9 @@
+package: "com.android.settings.flags"
+container: "system"
+
+flag {
+ name: "catalyst_bluetooth_switchbar_screen"
+ namespace: "android_settings"
+ description: "Flag for Bluetooth"
+ bug: "323791114"
+}
diff --git a/aconfig/catalyst/display.aconfig b/aconfig/catalyst/display.aconfig
index f722f74..94a01e0 100644
--- a/aconfig/catalyst/display.aconfig
+++ b/aconfig/catalyst/display.aconfig
@@ -7,3 +7,10 @@
description: "Flag for Display"
bug: "323791114"
}
+
+flag {
+ name: "catalyst_screen_timeout"
+ namespace: "android_settings"
+ description: "Flag for Screen Timeout settings"
+ bug: "323791114"
+}
diff --git a/aconfig/catalyst/location.aconfig b/aconfig/catalyst/location.aconfig
new file mode 100644
index 0000000..c656bf3
--- /dev/null
+++ b/aconfig/catalyst/location.aconfig
@@ -0,0 +1,9 @@
+package: "com.android.settings.flags"
+container: "system"
+
+flag {
+ name: "catalyst_location_settings"
+ namespace: "android_settings"
+ description: "Flag for Location"
+ bug: "323791114"
+}
diff --git a/aconfig/catalyst/network_and_internet.aconfig b/aconfig/catalyst/network_and_internet.aconfig
index a3e1784..a5183f3 100644
--- a/aconfig/catalyst/network_and_internet.aconfig
+++ b/aconfig/catalyst/network_and_internet.aconfig
@@ -7,3 +7,10 @@
description: "Flag for Network & Internet"
bug: "323791114"
}
+
+flag {
+ name: "catalyst_mobile_network_list"
+ namespace: "android_settings"
+ description: "Flag for SIMs"
+ bug: "323791114"
+}
diff --git a/res/xml/power_background_usage_detail.xml b/res/xml/power_background_usage_detail.xml
index 5c7b6a5..32d80b5 100644
--- a/res/xml/power_background_usage_detail.xml
+++ b/res/xml/power_background_usage_detail.xml
@@ -25,22 +25,25 @@
android:layout="@layout/settings_entity_header"
android:selectable="false"/>
- <com.android.settingslib.widget.MainSwitchPreference
- android:key="allow_background_usage"
- android:title="@string/manager_battery_usage_allow_background_usage_title"
- settings:controller="com.android.settings.fuelgauge.AllowBackgroundPreferenceController"/>
+ <PreferenceCategory
+ android:key="battery_optimization_mode_category"
+ android:layout="@layout/settingslib_preference_category_no_title"
+ settings:controller="com.android.settings.fuelgauge.BatteryOptimizationModePreferenceController">
- <com.android.settingslib.widget.SelectorWithWidgetPreference
- android:key="optimized_preference"
- android:title="@string/manager_battery_usage_optimized_title"
- android:summary="@string/manager_battery_usage_optimized_summary"
- settings:controller="com.android.settings.fuelgauge.OptimizedPreferenceController"/>
+ <com.android.settingslib.widget.MainSwitchPreference
+ android:key="background_usage_allowability_switch"
+ android:title="@string/manager_battery_usage_allow_background_usage_title"/>
- <com.android.settingslib.widget.SelectorWithWidgetPreference
- android:key="unrestricted_preference"
- android:title="@string/manager_battery_usage_unrestricted_title"
- android:summary="@string/manager_battery_usage_unrestricted_summary"
- settings:controller="com.android.settings.fuelgauge.UnrestrictedPreferenceController"/>
+ <com.android.settingslib.widget.SelectorWithWidgetPreference
+ android:key="optimized_preference"
+ android:title="@string/manager_battery_usage_optimized_title"
+ android:summary="@string/manager_battery_usage_optimized_summary"/>
+
+ <com.android.settingslib.widget.SelectorWithWidgetPreference
+ android:key="unrestricted_preference"
+ android:title="@string/manager_battery_usage_unrestricted_title"
+ android:summary="@string/manager_battery_usage_unrestricted_summary"/>
+ </PreferenceCategory>
<com.android.settingslib.widget.FooterPreference
android:key="app_usage_footer_preference"
diff --git a/res/xml/power_usage_detail.xml b/res/xml/power_usage_detail.xml
index f3b30b6..655dbc5 100644
--- a/res/xml/power_usage_detail.xml
+++ b/res/xml/power_usage_detail.xml
@@ -48,12 +48,12 @@
<PreferenceCategory
android:title="@string/manager_battery_usage_category_title"
- android:key="manage_battery_usage_category">
+ android:key="background_usage_allowability_category"
+ settings:controller="com.android.settings.fuelgauge.BackgroundUsageAllowabilityPreferenceController">
<com.android.settingslib.PrimarySwitchPreference
- android:key="allow_background_usage"
- android:title="@string/manager_battery_usage_allow_background_usage_title"
- settings:controller="com.android.settings.fuelgauge.AllowBackgroundPreferenceController"/>
+ android:key="background_usage_allowability_switch"
+ android:title="@string/manager_battery_usage_allow_background_usage_title"/>
</PreferenceCategory>
diff --git a/src/com/android/settings/DisplaySettings.java b/src/com/android/settings/DisplaySettings.java
index a095006..10763d0 100644
--- a/src/com/android/settings/DisplaySettings.java
+++ b/src/com/android/settings/DisplaySettings.java
@@ -97,9 +97,8 @@
}
};
- @Nullable
@Override
- public String getPreferenceScreenBindingKey(@NonNull Context context) {
+ public @Nullable String getPreferenceScreenBindingKey(@NonNull Context context) {
return DisplayScreen.KEY;
}
}
diff --git a/src/com/android/settings/LegalSettings.java b/src/com/android/settings/LegalSettings.java
index e48da26..533dde3 100644
--- a/src/com/android/settings/LegalSettings.java
+++ b/src/com/android/settings/LegalSettings.java
@@ -50,9 +50,8 @@
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider(R.xml.about_legal);
- @Nullable
@Override
- public String getPreferenceScreenBindingKey(@NonNull Context context) {
+ public @Nullable String getPreferenceScreenBindingKey(@NonNull Context context) {
return LegalSettingsScreen.KEY;
}
}
diff --git a/src/com/android/settings/accessibility/ColorAndMotionFragment.java b/src/com/android/settings/accessibility/ColorAndMotionFragment.java
index 4ea2226..7a7c21d 100644
--- a/src/com/android/settings/accessibility/ColorAndMotionFragment.java
+++ b/src/com/android/settings/accessibility/ColorAndMotionFragment.java
@@ -17,12 +17,15 @@
package com.android.settings.accessibility;
import android.app.settings.SettingsEnums;
+import android.content.Context;
import android.hardware.display.ColorDisplayManager;
import android.os.Bundle;
import android.os.Handler;
import android.provider.Settings;
import android.view.accessibility.Flags;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import androidx.preference.Preference;
import androidx.preference.PreferenceCategory;
import androidx.preference.TwoStatePreference;
@@ -148,6 +151,12 @@
}
}
+ @Nullable
+ @Override
+ public String getPreferenceScreenBindingKey(@NonNull Context context) {
+ return ColorAndMotionScreen.KEY;
+ }
+
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider(R.xml.accessibility_color_and_motion);
}
diff --git a/src/com/android/settings/accessibility/ColorAndMotionScreen.kt b/src/com/android/settings/accessibility/ColorAndMotionScreen.kt
new file mode 100644
index 0000000..20a71e3
--- /dev/null
+++ b/src/com/android/settings/accessibility/ColorAndMotionScreen.kt
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.accessibility
+
+import android.content.Context
+import com.android.settings.flags.Flags
+import com.android.settings.R
+import com.android.settingslib.metadata.ProvidePreferenceScreen
+import com.android.settingslib.metadata.preferenceHierarchy
+import com.android.settingslib.preference.PreferenceScreenCreator
+
+@ProvidePreferenceScreen
+class ColorAndMotionScreen : PreferenceScreenCreator {
+ override val key: String = KEY
+ override val title: Int = R.string.accessibility_color_and_motion_title
+
+ override fun isFlagEnabled(context: Context) = Flags.catalystAccessibilityColorAndMotion()
+
+ override fun hasCompleteHierarchy(): Boolean = false
+
+ override fun fragmentClass() = ColorAndMotionFragment::class.java
+
+ override fun getPreferenceHierarchy(context: Context) = preferenceHierarchy(this) {}
+
+
+ companion object {
+ const val KEY = "accessibility_color_and_motion"
+ }
+}
\ No newline at end of file
diff --git a/src/com/android/settings/accessibility/shortcuts/EditShortcutsPreferenceFragment.java b/src/com/android/settings/accessibility/shortcuts/EditShortcutsPreferenceFragment.java
index d04b34a..f05b157 100644
--- a/src/com/android/settings/accessibility/shortcuts/EditShortcutsPreferenceFragment.java
+++ b/src/com/android/settings/accessibility/shortcuts/EditShortcutsPreferenceFragment.java
@@ -61,6 +61,7 @@
import com.android.settings.R;
import com.android.settings.SetupWizardUtils;
import com.android.settings.accessibility.AccessibilitySetupWizardUtils;
+import com.android.settings.accessibility.Flags;
import com.android.settings.accessibility.PreferredShortcuts;
import com.android.settings.core.SubSettingLauncher;
import com.android.settings.dashboard.DashboardFragment;
@@ -201,9 +202,14 @@
super.onCreatePreferences(savedInstanceState, rootKey);
Activity activity = getActivity();
+ final Preference descriptionPref = findPreference(getString(
+ R.string.accessibility_shortcut_description_pref));
if (!activity.getIntent().getAction().equals(
Settings.ACTION_ACCESSIBILITY_SHORTCUT_SETTINGS)) {
+ if (Flags.toggleFeatureFragmentCollectionInfo()) {
+ descriptionPref.setVisible(false);
+ }
return;
}
@@ -219,10 +225,11 @@
);
activity.setTitle(titles.first);
-
- String screenDescriptionPrefKey = getString(
- R.string.accessibility_shortcut_description_pref);
- findPreference(screenDescriptionPrefKey).setSummary(titles.second);
+ if (titles.second != null || !Flags.toggleFeatureFragmentCollectionInfo()) {
+ descriptionPref.setSummary(titles.second);
+ } else {
+ descriptionPref.setVisible(false);
+ }
}
@NonNull
diff --git a/src/com/android/settings/biometrics/fingerprint2/BiometricsEnvironment.kt b/src/com/android/settings/biometrics/fingerprint2/BiometricsEnvironment.kt
index 761a9c3..50ac3cd 100644
--- a/src/com/android/settings/biometrics/fingerprint2/BiometricsEnvironment.kt
+++ b/src/com/android/settings/biometrics/fingerprint2/BiometricsEnvironment.kt
@@ -133,11 +133,8 @@
fun createRenameFingerprintInteractor(): RenameFingerprintInteractor =
RenameFingerprintsInteractorImpl(fingerprintManager, context.userId, backgroundDispatcher)
- val accessibilityInteractor: AccessibilityInteractor by lazy {
- AccessibilityInteractorImpl(
- context.getSystemService(AccessibilityManager::class.java)!!,
- applicationScope,
- )
+ fun createAccessibilityInteractor(): AccessibilityInteractor {
+ return AccessibilityInteractorImpl(context.getSystemService(AccessibilityManager::class.java)!!)
}
val foldStateInteractor: FoldStateInteractor by lazy { FoldStateInteractorImpl(context) }
@@ -157,7 +154,7 @@
val enrollStageInteractor: EnrollStageInteractor by lazy { EnrollStageInteractorImpl() }
val udfpsEnrollInteractor: UdfpsEnrollInteractor by lazy {
- UdfpsEnrollInteractorImpl(context, accessibilityInteractor)
+ UdfpsEnrollInteractorImpl(context, createAccessibilityInteractor())
}
val sensorInteractor: FingerprintSensorInteractor by lazy {
diff --git a/src/com/android/settings/biometrics/fingerprint2/domain/interactor/AccessibilityInteractor.kt b/src/com/android/settings/biometrics/fingerprint2/domain/interactor/AccessibilityInteractor.kt
index e1a08e6..9f62ed0 100644
--- a/src/com/android/settings/biometrics/fingerprint2/domain/interactor/AccessibilityInteractor.kt
+++ b/src/com/android/settings/biometrics/fingerprint2/domain/interactor/AccessibilityInteractor.kt
@@ -16,6 +16,8 @@
package com.android.settings.biometrics.fingerprint2.domain.interactor
+import android.view.accessibility.AccessibilityEvent
+import android.view.accessibility.AccessibilityEvent.TYPE_ANNOUNCEMENT
import android.view.accessibility.AccessibilityManager
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.channels.awaitClose
@@ -27,26 +29,38 @@
/** Represents all of the information on accessibility state. */
interface AccessibilityInteractor {
/** A flow that contains whether or not accessibility is enabled */
- val isAccessibilityEnabled: Flow<Boolean>
+ fun isEnabledFlow(scope: CoroutineScope): Flow<Boolean>
+ val isEnabled: Boolean
+ fun announce(clazz: Class<*>, announcement: CharSequence?)
}
class AccessibilityInteractorImpl(
- accessibilityManager: AccessibilityManager,
- applicationScope: CoroutineScope,
+ private val accessibilityManager: AccessibilityManager,
) : AccessibilityInteractor {
/** A flow that contains whether or not accessibility is enabled */
- override val isAccessibilityEnabled: Flow<Boolean> =
+ override fun isEnabledFlow(scope: CoroutineScope): Flow<Boolean> =
callbackFlow {
- val listener =
- AccessibilityManager.AccessibilityStateChangeListener { enabled -> trySend(enabled) }
- accessibilityManager.addAccessibilityStateChangeListener(listener)
+ val listener =
+ AccessibilityManager.AccessibilityStateChangeListener { enabled -> trySend(enabled) }
+ accessibilityManager.addAccessibilityStateChangeListener(listener)
- // This clause will be called when no one is listening to the flow
- awaitClose { accessibilityManager.removeAccessibilityStateChangeListener(listener) }
- }
+ // This clause will be called when no one is listening to the flow
+ awaitClose { accessibilityManager.removeAccessibilityStateChangeListener(listener) }
+ }
.stateIn(
- applicationScope, // This is going to tied to the activity scope
+ scope,
SharingStarted.WhileSubscribed(), // When no longer subscribed, we removeTheListener
false,
)
+
+ override val isEnabled: Boolean
+ get() = accessibilityManager.isEnabled
+
+ override fun announce(clazz: Class<*>, announcement: CharSequence?) {
+ val event = AccessibilityEvent(TYPE_ANNOUNCEMENT)
+ event.className = clazz.javaClass.name
+ event.packageName = clazz.packageName
+ event.text.add(announcement)
+ accessibilityManager.sendAccessibilityEvent(event)
+ }
}
diff --git a/src/com/android/settings/biometrics/fingerprint2/domain/interactor/UdfpsEnrollInteractor.kt b/src/com/android/settings/biometrics/fingerprint2/domain/interactor/UdfpsEnrollInteractor.kt
index 006060a..62c51ae 100644
--- a/src/com/android/settings/biometrics/fingerprint2/domain/interactor/UdfpsEnrollInteractor.kt
+++ b/src/com/android/settings/biometrics/fingerprint2/domain/interactor/UdfpsEnrollInteractor.kt
@@ -19,6 +19,7 @@
import android.content.Context
import android.graphics.PointF
import android.util.TypedValue
+import kotlinx.coroutines.MainScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.combine
@@ -87,7 +88,7 @@
override val guidedEnrollmentOffset: Flow<PointF> =
combine(
_guidedEnrollment,
- accessibilityInteractor.isAccessibilityEnabled,
+ accessibilityInteractor.isEnabledFlow(MainScope()),
isGuidedEnrollment,
) { point, accessibilityEnabled, guidedEnrollmentEnabled ->
if (accessibilityEnabled || !guidedEnrollmentEnabled) {
diff --git a/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/modules/enrolling/udfps/ui/viewmodel/UdfpsViewModel.kt b/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/modules/enrolling/udfps/ui/viewmodel/UdfpsViewModel.kt
index 658c6c7..df46aa4 100644
--- a/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/modules/enrolling/udfps/ui/viewmodel/UdfpsViewModel.kt
+++ b/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/modules/enrolling/udfps/ui/viewmodel/UdfpsViewModel.kt
@@ -179,7 +179,7 @@
/** Indicates if accessibility is enabled */
val accessibilityEnabled =
- accessibilityInteractor.isAccessibilityEnabled.shareIn(
+ accessibilityInteractor.isEnabledFlow(viewModelScope).shareIn(
this.viewModelScope,
SharingStarted.Eagerly,
replay = 1,
@@ -425,7 +425,7 @@
biometricEnvironment.enrollStageInteractor,
biometricEnvironment.orientationInteractor,
biometricEnvironment.udfpsEnrollInteractor,
- biometricEnvironment.accessibilityInteractor,
+ biometricEnvironment.createAccessibilityInteractor(),
biometricEnvironment.sensorInteractor,
biometricEnvironment.touchEventInteractor,
biometricEnvironment.createSensorPropertiesInteractor(),
diff --git a/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/viewmodel/FingerprintEnrollFindSensorViewModel.kt b/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/viewmodel/FingerprintEnrollFindSensorViewModel.kt
index 9b2cdde..b27cfdd 100644
--- a/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/viewmodel/FingerprintEnrollFindSensorViewModel.kt
+++ b/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/viewmodel/FingerprintEnrollFindSensorViewModel.kt
@@ -84,7 +84,7 @@
/** Represents the stream of showing udfps lottie and whether accessibility is enabled. */
val udfpsLottieInfo: Flow<Boolean> =
- _showUdfpsLottie.combine(accessibilityInteractor.isAccessibilityEnabled) {
+ _showUdfpsLottie.combine(accessibilityInteractor.isEnabledFlow(viewModelScope)) {
_,
isAccessibilityEnabled ->
isAccessibilityEnabled
@@ -213,7 +213,7 @@
provider[FingerprintGatekeeperViewModel::class],
provider[BackgroundViewModel::class],
provider[FingerprintFlowViewModel::class],
- biometricEnvironment.accessibilityInteractor,
+ biometricEnvironment.createAccessibilityInteractor(),
biometricEnvironment.foldStateInteractor,
biometricEnvironment.orientationInteractor,
biometricEnvironment.createSensorPropertiesInteractor(),
diff --git a/src/com/android/settings/connecteddevice/BluetoothDashboardFragment.java b/src/com/android/settings/connecteddevice/BluetoothDashboardFragment.java
index 66f2f1b..90ef5b9 100644
--- a/src/com/android/settings/connecteddevice/BluetoothDashboardFragment.java
+++ b/src/com/android/settings/connecteddevice/BluetoothDashboardFragment.java
@@ -21,6 +21,8 @@
import android.text.TextUtils;
import android.util.Log;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import com.android.settings.R;
@@ -120,4 +122,9 @@
*/
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider(R.xml.bluetooth_screen);
+
+ @Override
+ public @Nullable String getPreferenceScreenBindingKey(@NonNull Context context) {
+ return BluetoothDashboardScreen.KEY;
+ }
}
diff --git a/src/com/android/settings/connecteddevice/BluetoothDashboardScreen.kt b/src/com/android/settings/connecteddevice/BluetoothDashboardScreen.kt
new file mode 100644
index 0000000..66fd8b1
--- /dev/null
+++ b/src/com/android/settings/connecteddevice/BluetoothDashboardScreen.kt
@@ -0,0 +1,47 @@
+/*
+ * 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.connecteddevice
+
+import android.content.Context
+import com.android.settings.R
+import com.android.settings.flags.Flags
+import com.android.settingslib.metadata.ProvidePreferenceScreen
+import com.android.settingslib.metadata.preferenceHierarchy
+import com.android.settingslib.preference.PreferenceScreenCreator
+
+@ProvidePreferenceScreen
+class BluetoothDashboardScreen : PreferenceScreenCreator {
+ override val key: String
+ get() = KEY
+
+ override val title: Int
+ get() = R.string.bluetooth_settings_title
+
+ override val icon: Int
+ get() = R.drawable.ic_settings_bluetooth
+
+ override fun isFlagEnabled(context: Context) = Flags.catalystBluetoothSwitchbarScreen()
+
+ override fun hasCompleteHierarchy() = false
+
+ override fun fragmentClass() = BluetoothDashboardFragment::class.java
+
+ override fun getPreferenceHierarchy(context: Context) = preferenceHierarchy(this) {}
+
+ companion object {
+ const val KEY = "bluetooth_switchbar_screen"
+ }
+}
diff --git a/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java b/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java
index e922f70..28d7d58 100644
--- a/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java
+++ b/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java
@@ -26,13 +26,10 @@
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.UserHandle;
-import android.text.TextUtils;
import android.util.Log;
import android.view.View;
-import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
-import androidx.preference.Preference;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
@@ -48,7 +45,6 @@
import com.android.settings.fuelgauge.batteryusage.BatteryEntry;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.widget.EntityHeaderController;
-import com.android.settingslib.PrimarySwitchPreference;
import com.android.settingslib.applications.AppUtils;
import com.android.settingslib.applications.ApplicationsState;
import com.android.settingslib.core.AbstractPreferenceController;
@@ -67,9 +63,7 @@
* 2. Battery related controls for app(i.e uninstall, force stop)
*/
public class AdvancedPowerUsageDetail extends DashboardFragment
- implements ButtonActionDialogFragment.AppButtonsDialogListener,
- Preference.OnPreferenceClickListener,
- Preference.OnPreferenceChangeListener {
+ implements ButtonActionDialogFragment.AppButtonsDialogListener {
public static final String TAG = "AdvancedPowerDetail";
public static final String EXTRA_UID = "extra_uid";
public static final String EXTRA_PACKAGE_NAME = "extra_package_name";
@@ -86,7 +80,8 @@
public static final String EXTRA_POWER_USAGE_AMOUNT = "extra_power_usage_amount";
private static final String KEY_PREF_HEADER = "header_view";
- private static final String KEY_ALLOW_BACKGROUND_USAGE = "allow_background_usage";
+ private static final String KEY_BACKGROUND_USAGE_ALLOWABILITY_CATEGORY =
+ "background_usage_allowability_category";
private static final int REQUEST_UNINSTALL = 0;
private static final int REQUEST_REMOVE_DEVICE_ADMIN = 1;
@@ -96,11 +91,9 @@
private AppButtonsPreferenceController mAppButtonsPreferenceController;
private PowerUsageTimeController mPowerUsageTimeController;
- @VisibleForTesting LayoutPreference mHeaderPreference;
@VisibleForTesting ApplicationsState mState;
@VisibleForTesting ApplicationsState.AppEntry mAppEntry;
@VisibleForTesting BatteryOptimizeUtils mBatteryOptimizeUtils;
- @VisibleForTesting PrimarySwitchPreference mAllowBackgroundUsagePreference;
@VisibleForTesting @BatteryOptimizeUtils.OptimizationMode
int mOptimizationMode = BatteryOptimizeUtils.MODE_UNKNOWN;
@@ -242,17 +235,11 @@
public void onAttach(Activity activity) {
super.onAttach(activity);
+ final Bundle bundle = getArguments();
+ final int uid = bundle.getInt(EXTRA_UID, 0);
+ final String packageName = bundle.getString(EXTRA_PACKAGE_NAME);
+ mBatteryOptimizeUtils = new BatteryOptimizeUtils(getContext(), uid, packageName);
mState = ApplicationsState.getInstance(getActivity().getApplication());
- }
-
- @Override
- public void onCreate(Bundle icicle) {
- super.onCreate(icicle);
-
- final String packageName = getArguments().getString(EXTRA_PACKAGE_NAME);
- onCreateBackgroundUsageState(packageName);
- mHeaderPreference = findPreference(KEY_PREF_HEADER);
-
if (packageName != null) {
mAppEntry = mState.getEntry(packageName, UserHandle.myUserId());
}
@@ -264,7 +251,6 @@
initHeader();
mOptimizationMode = mBatteryOptimizeUtils.getAppOptimizationMode();
- initFooter();
mLogStringBuilder = new StringBuilder("onResume mode = ").append(mOptimizationMode);
}
@@ -299,7 +285,8 @@
@VisibleForTesting
void initHeader() {
- final View appSnippet = mHeaderPreference.findViewById(R.id.entity_header);
+ final LayoutPreference headerPreference = findPreference(KEY_PREF_HEADER);
+ final View appSnippet = headerPreference.findViewById(R.id.entity_header);
final Activity context = getActivity();
final Bundle bundle = getArguments();
EntityHeaderController controller =
@@ -340,31 +327,6 @@
controller.done(true /* rebindActions */);
}
- @VisibleForTesting
- void initFooter() {
- final String stateString;
- final String detailInfoString;
- final Context context = getContext();
-
- if (mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()) {
- // Present optimized only string when the package name is invalid.
- stateString = context.getString(R.string.manager_battery_usage_optimized_only);
- detailInfoString =
- context.getString(R.string.manager_battery_usage_footer_limited, stateString);
- } else if (mBatteryOptimizeUtils.isSystemOrDefaultApp()) {
- // Present unrestricted only string when the package is system or default active app.
- stateString = context.getString(R.string.manager_battery_usage_unrestricted_only);
- detailInfoString =
- context.getString(R.string.manager_battery_usage_footer_limited, stateString);
- } else {
- // Present default string to normal app.
- detailInfoString =
- context.getString(
- R.string.manager_battery_usage_allow_background_usage_summary);
- }
- mAllowBackgroundUsagePreference.setSummary(detailInfoString);
- }
-
@Override
public int getMetricsCategory() {
return SettingsEnums.FUELGAUGE_POWER_USAGE_DETAIL;
@@ -384,7 +346,6 @@
protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
final List<AbstractPreferenceController> controllers = new ArrayList<>();
final Bundle bundle = getArguments();
- final int uid = bundle.getInt(EXTRA_UID, 0);
final String packageName = bundle.getString(EXTRA_PACKAGE_NAME);
mAppButtonsPreferenceController =
@@ -401,7 +362,12 @@
controllers.add(mPowerUsageTimeController);
}
controllers.add(mAppButtonsPreferenceController);
- controllers.add(new AllowBackgroundPreferenceController(context, uid, packageName));
+ controllers.add(
+ new BackgroundUsageAllowabilityPreferenceController(
+ context,
+ /* dashboardFragment= */ this,
+ KEY_BACKGROUND_USAGE_ALLOWABILITY_CATEGORY,
+ mBatteryOptimizeUtils));
return controllers;
}
@@ -421,34 +387,6 @@
}
}
- @Override
- public boolean onPreferenceClick(Preference preference) {
- if (!(preference instanceof PrimarySwitchPreference)
- || !TextUtils.equals(preference.getKey(), KEY_ALLOW_BACKGROUND_USAGE)) {
- return false;
- }
- PowerBackgroundUsageDetail.startPowerBackgroundUsageDetailPage(
- getContext(), getArguments());
- return true;
- }
-
- @Override
- public boolean onPreferenceChange(@NonNull Preference preference, Object newValue) {
- if (!(preference instanceof PrimarySwitchPreference)
- || !TextUtils.equals(preference.getKey(), KEY_ALLOW_BACKGROUND_USAGE)) {
- return false;
- }
- if (newValue instanceof Boolean) {
- final boolean isAllowBackgroundUsage = (boolean) newValue;
- mBatteryOptimizeUtils.setAppUsageState(
- isAllowBackgroundUsage
- ? BatteryOptimizeUtils.MODE_OPTIMIZED
- : BatteryOptimizeUtils.MODE_RESTRICTED,
- Action.APPLY);
- }
- return true;
- }
-
private void logMetricCategory(int currentOptimizeMode) {
if (currentOptimizeMode == mOptimizationMode) {
return;
@@ -482,16 +420,4 @@
getArguments().getInt(EXTRA_POWER_USAGE_AMOUNT));
});
}
-
- private void onCreateBackgroundUsageState(String packageName) {
- mAllowBackgroundUsagePreference = findPreference(KEY_ALLOW_BACKGROUND_USAGE);
- if (mAllowBackgroundUsagePreference != null) {
- mAllowBackgroundUsagePreference.setOnPreferenceClickListener(this);
- mAllowBackgroundUsagePreference.setOnPreferenceChangeListener(this);
- }
-
- mBatteryOptimizeUtils =
- new BatteryOptimizeUtils(
- getContext(), getArguments().getInt(EXTRA_UID), packageName);
- }
}
diff --git a/src/com/android/settings/fuelgauge/AllowBackgroundPreferenceController.java b/src/com/android/settings/fuelgauge/AllowBackgroundPreferenceController.java
deleted file mode 100644
index 52cec795..0000000
--- a/src/com/android/settings/fuelgauge/AllowBackgroundPreferenceController.java
+++ /dev/null
@@ -1,85 +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;
-
-import android.content.Context;
-
-import androidx.annotation.VisibleForTesting;
-import androidx.preference.Preference;
-
-import com.android.settings.core.PreferenceControllerMixin;
-import com.android.settingslib.PrimarySwitchPreference;
-import com.android.settingslib.core.AbstractPreferenceController;
-import com.android.settingslib.widget.MainSwitchPreference;
-
-/** Controller to update the app background usage state */
-public class AllowBackgroundPreferenceController extends AbstractPreferenceController
- implements PreferenceControllerMixin {
-
- private static final String TAG = "AllowBackgroundPreferenceController";
-
- @VisibleForTesting static final String KEY_ALLOW_BACKGROUND_USAGE = "allow_background_usage";
-
- @VisibleForTesting BatteryOptimizeUtils mBatteryOptimizeUtils;
-
- public AllowBackgroundPreferenceController(Context context, int uid, String packageName) {
- super(context);
- mBatteryOptimizeUtils = new BatteryOptimizeUtils(context, uid, packageName);
- }
-
- private void setChecked(Preference preference, boolean checked) {
- if (preference instanceof PrimarySwitchPreference) {
- ((PrimarySwitchPreference) preference).setChecked(checked);
- } else if (preference instanceof MainSwitchPreference) {
- ((MainSwitchPreference) preference).setChecked(checked);
- }
- }
-
- private void setEnabled(Preference preference, boolean enabled) {
- if (preference instanceof PrimarySwitchPreference) {
- ((PrimarySwitchPreference) preference).setEnabled(enabled);
- ((PrimarySwitchPreference) preference).setSwitchEnabled(enabled);
- } else if (preference instanceof MainSwitchPreference) {
- ((MainSwitchPreference) preference).setEnabled(enabled);
- }
- }
-
- @Override
- public void updateState(Preference preference) {
- setEnabled(preference, mBatteryOptimizeUtils.isOptimizeModeMutable());
-
- final boolean isAllowBackground =
- mBatteryOptimizeUtils.getAppOptimizationMode()
- != BatteryOptimizeUtils.MODE_RESTRICTED;
- setChecked(preference, isAllowBackground);
- }
-
- @Override
- public boolean isAvailable() {
- return true;
- }
-
- @Override
- public String getPreferenceKey() {
- return KEY_ALLOW_BACKGROUND_USAGE;
- }
-
- @Override
- public boolean handlePreferenceTreeClick(Preference preference) {
- return getPreferenceKey().equals(preference.getKey());
- }
-}
diff --git a/src/com/android/settings/fuelgauge/BackgroundUsageAllowabilityPreferenceController.java b/src/com/android/settings/fuelgauge/BackgroundUsageAllowabilityPreferenceController.java
new file mode 100644
index 0000000..bce439b
--- /dev/null
+++ b/src/com/android/settings/fuelgauge/BackgroundUsageAllowabilityPreferenceController.java
@@ -0,0 +1,140 @@
+/*
+ * 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.fuelgauge;
+
+import android.content.Context;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
+import com.android.settings.R;
+import com.android.settings.core.BasePreferenceController;
+import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settings.dashboard.DashboardFragment;
+import com.android.settingslib.PrimarySwitchPreference;
+
+/** Controller to update the manage battery usage preference in App Battery Usage page */
+public class BackgroundUsageAllowabilityPreferenceController extends BasePreferenceController
+ implements PreferenceControllerMixin {
+
+ @VisibleForTesting
+ static final String KEY_BACKGROUND_USAGE_ALLOWABILITY_SWITCH =
+ "background_usage_allowability_switch";
+
+ private final BatteryOptimizeUtils mBatteryOptimizeUtils;
+ private final DashboardFragment mDashboardFragment;
+ @Nullable @VisibleForTesting PrimarySwitchPreference mBackgroundUsageAllowabilityPreference;
+
+ public BackgroundUsageAllowabilityPreferenceController(
+ @NonNull Context context,
+ @NonNull DashboardFragment dashboardFragment,
+ @NonNull String preferenceKey,
+ @NonNull BatteryOptimizeUtils batteryOptimizeUtils) {
+ super(context, preferenceKey);
+ mDashboardFragment = dashboardFragment;
+ mBatteryOptimizeUtils = batteryOptimizeUtils;
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ return AVAILABLE;
+ }
+
+ @Override
+ public void updateState(@NonNull Preference preference) {
+ updatePreferences(mBatteryOptimizeUtils.getAppOptimizationMode());
+ }
+
+ @Override
+ public void displayPreference(@NonNull PreferenceScreen screen) {
+ super.displayPreference(screen);
+ mBackgroundUsageAllowabilityPreference =
+ screen.findPreference(KEY_BACKGROUND_USAGE_ALLOWABILITY_SWITCH);
+ initPreferences();
+ }
+
+ @VisibleForTesting
+ void initPreferences() {
+ if (mBackgroundUsageAllowabilityPreference == null) {
+ return;
+ }
+ final String stateString;
+ final String detailInfoString;
+ boolean isPreferenceEnabled = true;
+ if (mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()) {
+ // Present "Optimized" only string if the package name is invalid.
+ stateString = mContext.getString(R.string.manager_battery_usage_optimized_only);
+ detailInfoString =
+ mContext.getString(R.string.manager_battery_usage_footer_limited, stateString);
+ isPreferenceEnabled = false;
+ } else if (mBatteryOptimizeUtils.isSystemOrDefaultApp()) {
+ // Present "Unrestricted" only string if the package is system important apps.
+ stateString = mContext.getString(R.string.manager_battery_usage_unrestricted_only);
+ detailInfoString =
+ mContext.getString(R.string.manager_battery_usage_footer_limited, stateString);
+ isPreferenceEnabled = false;
+ } else {
+ // Present default string to normal app.
+ detailInfoString =
+ mContext.getString(
+ R.string.manager_battery_usage_allow_background_usage_summary);
+ }
+ mBackgroundUsageAllowabilityPreference.setEnabled(isPreferenceEnabled);
+ mBackgroundUsageAllowabilityPreference.setSwitchEnabled(isPreferenceEnabled);
+ mBackgroundUsageAllowabilityPreference.setSummary(detailInfoString);
+ if (isPreferenceEnabled) {
+ mBackgroundUsageAllowabilityPreference.setOnPreferenceClickListener(
+ preference -> {
+ PowerBackgroundUsageDetail.startPowerBackgroundUsageDetailPage(
+ mContext, mDashboardFragment.getArguments());
+ return true;
+ });
+ mBackgroundUsageAllowabilityPreference.setOnPreferenceChangeListener(
+ (preference, isAllowBackground) -> {
+ handleBatteryOptimizeModeUpdated(
+ (boolean) isAllowBackground
+ ? BatteryOptimizeUtils.MODE_OPTIMIZED
+ : BatteryOptimizeUtils.MODE_RESTRICTED);
+ return true;
+ });
+ }
+ }
+
+ @VisibleForTesting
+ void handleBatteryOptimizeModeUpdated(int newBatteryOptimizeMode) {
+ if (mBatteryOptimizeUtils.getAppOptimizationMode() == newBatteryOptimizeMode) {
+ Log.w(TAG, "ignore same mode for: " + mBatteryOptimizeUtils.getPackageName());
+ return;
+ }
+ mBatteryOptimizeUtils.setAppUsageState(
+ newBatteryOptimizeMode, BatteryOptimizeHistoricalLogEntry.Action.APPLY);
+ updatePreferences(newBatteryOptimizeMode);
+ }
+
+ @VisibleForTesting
+ void updatePreferences(int optimizationMode) {
+ if (mBackgroundUsageAllowabilityPreference == null) {
+ return;
+ }
+ mBackgroundUsageAllowabilityPreference.setChecked(
+ optimizationMode != BatteryOptimizeUtils.MODE_RESTRICTED);
+ }
+}
diff --git a/src/com/android/settings/fuelgauge/BatteryOptimizationModePreferenceController.java b/src/com/android/settings/fuelgauge/BatteryOptimizationModePreferenceController.java
new file mode 100644
index 0000000..0a4cbac
--- /dev/null
+++ b/src/com/android/settings/fuelgauge/BatteryOptimizationModePreferenceController.java
@@ -0,0 +1,136 @@
+/*
+ * 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.fuelgauge;
+
+import android.content.Context;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
+import com.android.settings.core.BasePreferenceController;
+import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settingslib.widget.MainSwitchPreference;
+import com.android.settingslib.widget.SelectorWithWidgetPreference;
+
+/** Controller to update the app background usage mode state in Allow background usage page */
+public class BatteryOptimizationModePreferenceController extends BasePreferenceController
+ implements PreferenceControllerMixin {
+
+ @VisibleForTesting
+ static final String KEY_BACKGROUND_USAGE_ALLOWABILITY_SWITCH =
+ "background_usage_allowability_switch";
+
+ @VisibleForTesting static final String KEY_OPTIMIZED_PREF = "optimized_preference";
+ @VisibleForTesting static final String KEY_UNRESTRICTED_PREF = "unrestricted_preference";
+
+ private final BatteryOptimizeUtils mBatteryOptimizeUtils;
+ @Nullable @VisibleForTesting MainSwitchPreference mBackgroundUsageAllowabilityPreference;
+ @Nullable @VisibleForTesting SelectorWithWidgetPreference mOptimizedPreference;
+ @Nullable @VisibleForTesting SelectorWithWidgetPreference mUnrestrictedPreference;
+
+ public BatteryOptimizationModePreferenceController(
+ @NonNull Context context,
+ @NonNull String preferenceKey,
+ @NonNull BatteryOptimizeUtils batteryOptimizeUtils) {
+ super(context, preferenceKey);
+ mBatteryOptimizeUtils = batteryOptimizeUtils;
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ return AVAILABLE;
+ }
+
+ @Override
+ public void updateState(@NonNull Preference preference) {
+ updatePreferences(mBatteryOptimizeUtils.getAppOptimizationMode());
+ }
+
+ @Override
+ public void displayPreference(@NonNull PreferenceScreen screen) {
+ super.displayPreference(screen);
+ mBackgroundUsageAllowabilityPreference =
+ screen.findPreference(KEY_BACKGROUND_USAGE_ALLOWABILITY_SWITCH);
+ mOptimizedPreference = screen.findPreference(KEY_OPTIMIZED_PREF);
+ mUnrestrictedPreference = screen.findPreference(KEY_UNRESTRICTED_PREF);
+ initPreferences();
+ }
+
+ @VisibleForTesting
+ void initPreferences() {
+ if (mBackgroundUsageAllowabilityPreference == null
+ || mOptimizedPreference == null
+ || mUnrestrictedPreference == null) {
+ return;
+ }
+ final boolean isEnabled = mBatteryOptimizeUtils.isOptimizeModeMutable();
+ mBackgroundUsageAllowabilityPreference.setEnabled(isEnabled);
+ mOptimizedPreference.setEnabled(isEnabled);
+ mUnrestrictedPreference.setEnabled(isEnabled);
+ if (isEnabled) {
+ mBackgroundUsageAllowabilityPreference.setOnPreferenceChangeListener(
+ (preference, isAllowBackground) -> {
+ handleBatteryOptimizeModeUpdated(
+ (boolean) isAllowBackground
+ ? BatteryOptimizeUtils.MODE_OPTIMIZED
+ : BatteryOptimizeUtils.MODE_RESTRICTED);
+ return true;
+ });
+ mOptimizedPreference.setOnPreferenceClickListener(
+ preference -> {
+ handleBatteryOptimizeModeUpdated(BatteryOptimizeUtils.MODE_OPTIMIZED);
+ return true;
+ });
+ mUnrestrictedPreference.setOnPreferenceClickListener(
+ preference -> {
+ handleBatteryOptimizeModeUpdated(BatteryOptimizeUtils.MODE_UNRESTRICTED);
+ return true;
+ });
+ }
+ }
+
+ @VisibleForTesting
+ void updatePreferences(int optimizationMode) {
+ if (mBackgroundUsageAllowabilityPreference == null
+ || mOptimizedPreference == null
+ || mUnrestrictedPreference == null) {
+ return;
+ }
+ final boolean isAllowBackground = optimizationMode != BatteryOptimizeUtils.MODE_RESTRICTED;
+ mBackgroundUsageAllowabilityPreference.setChecked(isAllowBackground);
+ mOptimizedPreference.setEnabled(isAllowBackground);
+ mUnrestrictedPreference.setEnabled(isAllowBackground);
+ mOptimizedPreference.setChecked(optimizationMode == BatteryOptimizeUtils.MODE_OPTIMIZED);
+ mUnrestrictedPreference.setChecked(
+ optimizationMode == BatteryOptimizeUtils.MODE_UNRESTRICTED);
+ }
+
+ @VisibleForTesting
+ void handleBatteryOptimizeModeUpdated(int newBatteryOptimizeMode) {
+ if (mBatteryOptimizeUtils.getAppOptimizationMode() == newBatteryOptimizeMode) {
+ Log.w(TAG, "ignore same mode for: " + mBatteryOptimizeUtils.getPackageName());
+ return;
+ }
+ mBatteryOptimizeUtils.setAppUsageState(
+ newBatteryOptimizeMode, BatteryOptimizeHistoricalLogEntry.Action.APPLY);
+ updatePreferences(newBatteryOptimizeMode);
+ }
+}
diff --git a/src/com/android/settings/fuelgauge/OptimizedPreferenceController.java b/src/com/android/settings/fuelgauge/OptimizedPreferenceController.java
deleted file mode 100644
index a26ab7a..0000000
--- a/src/com/android/settings/fuelgauge/OptimizedPreferenceController.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2021 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;
-
-import android.content.Context;
-
-import androidx.annotation.VisibleForTesting;
-import androidx.preference.Preference;
-
-import com.android.settings.core.PreferenceControllerMixin;
-import com.android.settingslib.core.AbstractPreferenceController;
-import com.android.settingslib.widget.SelectorWithWidgetPreference;
-
-public class OptimizedPreferenceController extends AbstractPreferenceController
- implements PreferenceControllerMixin {
-
- private static final String TAG = "OPTIMIZED_PREF";
-
- @VisibleForTesting static final String KEY_OPTIMIZED_PREF = "optimized_preference";
- @VisibleForTesting BatteryOptimizeUtils mBatteryOptimizeUtils;
-
- public OptimizedPreferenceController(Context context, int uid, String packageName) {
- super(context);
- mBatteryOptimizeUtils = new BatteryOptimizeUtils(context, uid, packageName);
- }
-
- @Override
- public boolean isAvailable() {
- return true;
- }
-
- @Override
- public void updateState(Preference preference) {
- preference.setEnabled(mBatteryOptimizeUtils.isSelectorPreferenceEnabled());
-
- final boolean isOptimized =
- mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()
- || mBatteryOptimizeUtils.getAppOptimizationMode()
- == BatteryOptimizeUtils.MODE_OPTIMIZED;
- ((SelectorWithWidgetPreference) preference).setChecked(isOptimized);
- }
-
- @Override
- public String getPreferenceKey() {
- return KEY_OPTIMIZED_PREF;
- }
-
- @Override
- public boolean handlePreferenceTreeClick(Preference preference) {
- return getPreferenceKey().equals(preference.getKey());
- }
-}
diff --git a/src/com/android/settings/fuelgauge/PowerBackgroundUsageDetail.java b/src/com/android/settings/fuelgauge/PowerBackgroundUsageDetail.java
index e59cc4ad..dadf2e8 100644
--- a/src/com/android/settings/fuelgauge/PowerBackgroundUsageDetail.java
+++ b/src/com/android/settings/fuelgauge/PowerBackgroundUsageDetail.java
@@ -24,11 +24,8 @@
import android.content.Intent;
import android.os.Bundle;
import android.os.UserHandle;
-import android.text.TextUtils;
import android.util.Log;
import android.view.View;
-import android.widget.CompoundButton;
-import android.widget.CompoundButton.OnCheckedChangeListener;
import androidx.annotation.VisibleForTesting;
@@ -44,8 +41,6 @@
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.widget.FooterPreference;
import com.android.settingslib.widget.LayoutPreference;
-import com.android.settingslib.widget.MainSwitchPreference;
-import com.android.settingslib.widget.SelectorWithWidgetPreference;
import java.util.ArrayList;
import java.util.List;
@@ -53,8 +48,7 @@
import java.util.concurrent.Executors;
/** Allow background usage fragment for each app */
-public class PowerBackgroundUsageDetail extends DashboardFragment
- implements SelectorWithWidgetPreference.OnClickListener, OnCheckedChangeListener {
+public class PowerBackgroundUsageDetail extends DashboardFragment {
private static final String TAG = "PowerBackgroundUsageDetail";
public static final String EXTRA_UID = "extra_uid";
@@ -63,21 +57,15 @@
public static final String EXTRA_POWER_USAGE_AMOUNT = "extra_power_usage_amount";
public static final String EXTRA_ICON_ID = "extra_icon_id";
private static final String KEY_PREF_HEADER = "header_view";
- private static final String KEY_PREF_UNRESTRICTED = "unrestricted_preference";
- private static final String KEY_PREF_OPTIMIZED = "optimized_preference";
- private static final String KEY_ALLOW_BACKGROUND_USAGE = "allow_background_usage";
private static final String KEY_FOOTER_PREFERENCE = "app_usage_footer_preference";
+ private static final String KEY_BATTERY_OPTIMIZATION_MODE_CATEGORY =
+ "battery_optimization_mode_category";
private final ExecutorService mExecutor = Executors.newSingleThreadExecutor();
- @VisibleForTesting LayoutPreference mHeaderPreference;
@VisibleForTesting ApplicationsState mState;
@VisibleForTesting ApplicationsState.AppEntry mAppEntry;
@VisibleForTesting BatteryOptimizeUtils mBatteryOptimizeUtils;
- @VisibleForTesting SelectorWithWidgetPreference mOptimizePreference;
- @VisibleForTesting SelectorWithWidgetPreference mUnrestrictedPreference;
- @VisibleForTesting MainSwitchPreference mMainSwitchPreference;
- @VisibleForTesting FooterPreference mFooterPreference;
@VisibleForTesting StringBuilder mLogStringBuilder;
@VisibleForTesting @BatteryOptimizeUtils.OptimizationMode
@@ -87,17 +75,11 @@
public void onAttach(Activity activity) {
super.onAttach(activity);
+ final Bundle bundle = getArguments();
+ final int uid = bundle.getInt(EXTRA_UID, 0);
+ final String packageName = bundle.getString(EXTRA_PACKAGE_NAME);
+ mBatteryOptimizeUtils = new BatteryOptimizeUtils(getContext(), uid, packageName);
mState = ApplicationsState.getInstance(getActivity().getApplication());
- }
-
- @Override
- public void onCreate(Bundle icicle) {
- super.onCreate(icicle);
-
- final String packageName = getArguments().getString(EXTRA_PACKAGE_NAME);
- onCreateBackgroundUsageState(packageName);
- mHeaderPreference = findPreference(KEY_PREF_HEADER);
-
if (packageName != null) {
mAppEntry = mState.getEntry(packageName, UserHandle.myUserId());
}
@@ -107,8 +89,8 @@
public void onResume() {
super.onResume();
initHeader();
- mOptimizationMode = mBatteryOptimizeUtils.getAppOptimizationMode();
initFooter();
+ mOptimizationMode = mBatteryOptimizeUtils.getAppOptimizationMode();
mLogStringBuilder = new StringBuilder("onResume mode = ").append(mOptimizationMode);
}
@@ -137,34 +119,16 @@
}
@Override
- public void onRadioButtonClicked(SelectorWithWidgetPreference selected) {
- final String selectedKey = selected == null ? null : selected.getKey();
- updateSelectorPreferenceState(mUnrestrictedPreference, selectedKey);
- updateSelectorPreferenceState(mOptimizePreference, selectedKey);
- mBatteryOptimizeUtils.setAppUsageState(getSelectedPreference(), Action.APPLY);
- }
-
- @Override
- public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
- mMainSwitchPreference.setChecked(isChecked);
- updateSelectorPreference(isChecked);
- }
-
- @Override
public int getMetricsCategory() {
return SettingsEnums.FUELGAUGE_POWER_USAGE_MANAGE_BACKGROUND;
}
@Override
protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
- final List<AbstractPreferenceController> controllers = new ArrayList<>();
- final Bundle bundle = getArguments();
- final int uid = bundle.getInt(EXTRA_UID, 0);
- final String packageName = bundle.getString(EXTRA_PACKAGE_NAME);
-
- controllers.add(new AllowBackgroundPreferenceController(context, uid, packageName));
- controllers.add(new OptimizedPreferenceController(context, uid, packageName));
- controllers.add(new UnrestrictedPreferenceController(context, uid, packageName));
+ final List<AbstractPreferenceController> controllers = new ArrayList<>(1);
+ controllers.add(
+ new BatteryOptimizationModePreferenceController(
+ context, KEY_BATTERY_OPTIMIZATION_MODE_CATEGORY, mBatteryOptimizeUtils));
return controllers;
}
@@ -179,26 +143,6 @@
return TAG;
}
- @VisibleForTesting
- void updateSelectorPreference(boolean isEnabled) {
- mOptimizePreference.setEnabled(isEnabled);
- mUnrestrictedPreference.setEnabled(isEnabled);
- onRadioButtonClicked(isEnabled ? mOptimizePreference : null);
- }
-
- @VisibleForTesting
- int getSelectedPreference() {
- if (!mMainSwitchPreference.isChecked()) {
- return BatteryOptimizeUtils.MODE_RESTRICTED;
- } else if (mUnrestrictedPreference.isChecked()) {
- return BatteryOptimizeUtils.MODE_UNRESTRICTED;
- } else if (mOptimizePreference.isChecked()) {
- return BatteryOptimizeUtils.MODE_OPTIMIZED;
- } else {
- return BatteryOptimizeUtils.MODE_UNKNOWN;
- }
- }
-
static void startPowerBackgroundUsageDetailPage(Context context, Bundle args) {
new SubSettingLauncher(context)
.setDestination(PowerBackgroundUsageDetail.class.getName())
@@ -209,7 +153,11 @@
@VisibleForTesting
void initHeader() {
- final View appSnippet = mHeaderPreference.findViewById(R.id.entity_header);
+ final LayoutPreference headerPreference = findPreference(KEY_PREF_HEADER);
+ if (headerPreference == null) {
+ return;
+ }
+ final View appSnippet = headerPreference.findViewById(R.id.entity_header);
final Activity context = getActivity();
final Bundle bundle = getArguments();
EntityHeaderController controller =
@@ -239,58 +187,25 @@
@VisibleForTesting
void initFooter() {
- final String stateString;
- final String footerString;
- final Context context = getContext();
-
- if (mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()) {
- // Present optimized only string when the package name is invalid.
- stateString = context.getString(R.string.manager_battery_usage_optimized_only);
- footerString =
- context.getString(R.string.manager_battery_usage_footer_limited, stateString);
- } else if (mBatteryOptimizeUtils.isSystemOrDefaultApp()) {
- // Present unrestricted only string when the package is system or default active app.
- stateString = context.getString(R.string.manager_battery_usage_unrestricted_only);
- footerString =
- context.getString(R.string.manager_battery_usage_footer_limited, stateString);
- } else {
- // Present default string to normal app.
- footerString = context.getString(R.string.manager_battery_usage_footer);
+ final FooterPreference footerPreference = findPreference(KEY_FOOTER_PREFERENCE);
+ if (footerPreference == null) {
+ return;
}
- mFooterPreference.setTitle(footerString);
+ final Context context = getContext();
+ footerPreference.setTitle(context.getString(R.string.manager_battery_usage_footer));
final Intent helpIntent =
HelpUtils.getHelpIntent(
context,
context.getString(R.string.help_url_app_usage_settings),
/* backupContext= */ "");
if (helpIntent != null) {
- mFooterPreference.setLearnMoreAction(
+ footerPreference.setLearnMoreAction(
v -> startActivityForResult(helpIntent, /* requestCode= */ 0));
- mFooterPreference.setLearnMoreText(
+ footerPreference.setLearnMoreText(
context.getString(R.string.manager_battery_usage_link_a11y));
}
}
- private void onCreateBackgroundUsageState(String packageName) {
- mOptimizePreference = findPreference(KEY_PREF_OPTIMIZED);
- mUnrestrictedPreference = findPreference(KEY_PREF_UNRESTRICTED);
- mMainSwitchPreference = findPreference(KEY_ALLOW_BACKGROUND_USAGE);
- mFooterPreference = findPreference(KEY_FOOTER_PREFERENCE);
-
- mOptimizePreference.setOnClickListener(this);
- mUnrestrictedPreference.setOnClickListener(this);
- mMainSwitchPreference.addOnSwitchChangeListener(this);
-
- mBatteryOptimizeUtils =
- new BatteryOptimizeUtils(
- getContext(), getArguments().getInt(EXTRA_UID), packageName);
- }
-
- private void updateSelectorPreferenceState(
- SelectorWithWidgetPreference preference, String selectedKey) {
- preference.setChecked(TextUtils.equals(selectedKey, preference.getKey()));
- }
-
private void logMetricCategory(int currentOptimizeMode) {
if (currentOptimizeMode == mOptimizationMode) {
return;
diff --git a/src/com/android/settings/fuelgauge/UnrestrictedPreferenceController.java b/src/com/android/settings/fuelgauge/UnrestrictedPreferenceController.java
deleted file mode 100644
index 652941b..0000000
--- a/src/com/android/settings/fuelgauge/UnrestrictedPreferenceController.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2021 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;
-
-import android.content.Context;
-
-import androidx.annotation.VisibleForTesting;
-import androidx.preference.Preference;
-
-import com.android.settings.core.PreferenceControllerMixin;
-import com.android.settingslib.core.AbstractPreferenceController;
-import com.android.settingslib.widget.SelectorWithWidgetPreference;
-
-public class UnrestrictedPreferenceController extends AbstractPreferenceController
- implements PreferenceControllerMixin {
-
- private static final String TAG = "UNRESTRICTED_PREF";
-
- @VisibleForTesting static final String KEY_UNRESTRICTED_PREF = "unrestricted_preference";
-
- @VisibleForTesting BatteryOptimizeUtils mBatteryOptimizeUtils;
-
- public UnrestrictedPreferenceController(Context context, int uid, String packageName) {
- super(context);
- mBatteryOptimizeUtils = new BatteryOptimizeUtils(context, uid, packageName);
- }
-
- @Override
- public void updateState(Preference preference) {
- preference.setEnabled(mBatteryOptimizeUtils.isSelectorPreferenceEnabled());
-
- final boolean isUnrestricted =
- mBatteryOptimizeUtils.getAppOptimizationMode()
- == BatteryOptimizeUtils.MODE_UNRESTRICTED;
- ((SelectorWithWidgetPreference) preference).setChecked(isUnrestricted);
- }
-
- @Override
- public boolean isAvailable() {
- return true;
- }
-
- @Override
- public String getPreferenceKey() {
- return KEY_UNRESTRICTED_PREF;
- }
-
- @Override
- public boolean handlePreferenceTreeClick(Preference preference) {
- return getPreferenceKey().equals(preference.getKey());
- }
-}
diff --git a/src/com/android/settings/fuelgauge/batterysaver/BatterySaverSettings.java b/src/com/android/settings/fuelgauge/batterysaver/BatterySaverSettings.java
index 8373d03..df6c1d9 100644
--- a/src/com/android/settings/fuelgauge/batterysaver/BatterySaverSettings.java
+++ b/src/com/android/settings/fuelgauge/batterysaver/BatterySaverSettings.java
@@ -97,9 +97,8 @@
}
}
- @Nullable
@Override
- public String getPreferenceScreenBindingKey(@NonNull Context context) {
+ public @Nullable String getPreferenceScreenBindingKey(@NonNull Context context) {
return BatterySaverScreen.KEY;
}
}
diff --git a/src/com/android/settings/fuelgauge/batteryusage/PowerUsageSummary.java b/src/com/android/settings/fuelgauge/batteryusage/PowerUsageSummary.java
index 4c700d2..b5581d0 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/PowerUsageSummary.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/PowerUsageSummary.java
@@ -27,6 +27,8 @@
import android.os.Handler;
import android.provider.Settings.Global;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import androidx.loader.app.LoaderManager;
import androidx.loader.content.Loader;
@@ -270,4 +272,9 @@
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider(R.xml.power_usage_summary);
+
+ @Override
+ public @Nullable String getPreferenceScreenBindingKey(@NonNull Context context) {
+ return PowerUsageSummaryScreen.KEY;
+ }
}
diff --git a/src/com/android/settings/fuelgauge/batteryusage/PowerUsageSummaryScreen.kt b/src/com/android/settings/fuelgauge/batteryusage/PowerUsageSummaryScreen.kt
new file mode 100644
index 0000000..229e308
--- /dev/null
+++ b/src/com/android/settings/fuelgauge/batteryusage/PowerUsageSummaryScreen.kt
@@ -0,0 +1,62 @@
+/*
+ * 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.fuelgauge.batteryusage
+
+import android.content.Context
+import com.android.settings.R
+import com.android.settings.flags.Flags
+import com.android.settingslib.metadata.PreferenceAvailabilityProvider
+import com.android.settingslib.metadata.PreferenceIconProvider
+import com.android.settingslib.metadata.ProvidePreferenceScreen
+import com.android.settingslib.metadata.preferenceHierarchy
+import com.android.settingslib.preference.PreferenceScreenCreator
+
+@ProvidePreferenceScreen
+class PowerUsageSummaryScreen : PreferenceScreenCreator,
+ PreferenceAvailabilityProvider,
+ PreferenceIconProvider {
+ override val key: String
+ get() = KEY
+
+ override val title: Int
+ get() = R.string.power_usage_summary_title
+
+ override val keywords: Int
+ get() = R.string.keywords_battery
+
+ override fun isFlagEnabled(context: Context) = Flags.catalystPowerUsageSummaryScreen()
+
+ override fun hasCompleteHierarchy() = false
+
+ override fun fragmentClass() = PowerUsageSummary::class.java
+
+ override fun isAvailable(context: Context) =
+ context.resources.getBoolean(R.bool.config_show_top_level_battery)
+
+ override fun getIcon(context: Context): Int =
+ if (Flags.homepageRevamp()) {
+ R.drawable.ic_settings_battery_filled
+ } else {
+ R.drawable.ic_settings_battery_white
+ }
+
+
+ override fun getPreferenceHierarchy(context: Context) = preferenceHierarchy(this) {}
+
+ companion object {
+ const val KEY = "power_usage_summary_screen"
+ }
+}
\ No newline at end of file
diff --git a/src/com/android/settings/gestures/SystemNavigationGestureSettings.java b/src/com/android/settings/gestures/SystemNavigationGestureSettings.java
index cfaee00..9b4da46 100644
--- a/src/com/android/settings/gestures/SystemNavigationGestureSettings.java
+++ b/src/com/android/settings/gestures/SystemNavigationGestureSettings.java
@@ -243,7 +243,9 @@
protected boolean setDefaultKey(String key) {
setCurrentSystemNavigationMode(mOverlayManager, key);
setIllustrationVideo(mVideoPreference, key);
- setGestureNavigationTutorialDialog(key);
+ if (!android.provider.Flags.a11yStandaloneGestureEnabled()) {
+ setGestureNavigationTutorialDialog(key);
+ }
setIllustrationClickListener(mVideoPreference, key);
return true;
}
diff --git a/src/com/android/settings/location/LocationScreen.kt b/src/com/android/settings/location/LocationScreen.kt
new file mode 100644
index 0000000..d45b762
--- /dev/null
+++ b/src/com/android/settings/location/LocationScreen.kt
@@ -0,0 +1,65 @@
+/*
+ * 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.location
+
+import android.content.Context
+import android.location.LocationManager
+import com.android.settings.R
+import com.android.settings.flags.Flags
+import com.android.settingslib.metadata.PreferenceIconProvider
+import com.android.settingslib.metadata.PreferenceSummaryProvider
+import com.android.settingslib.metadata.ProvidePreferenceScreen
+import com.android.settingslib.metadata.preferenceHierarchy
+import com.android.settingslib.preference.PreferenceScreenCreator
+
+@ProvidePreferenceScreen
+class LocationScreen : PreferenceScreenCreator, PreferenceSummaryProvider, PreferenceIconProvider {
+ override val key: String
+ get() = KEY
+
+ override val title: Int
+ get() = R.string.location_settings_title
+
+ override val keywords: Int
+ get() = R.string.keywords_location
+
+ override fun getSummary(context: Context): CharSequence? {
+ var locationManager = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager
+ return if (locationManager.isLocationEnabled) {
+ context.getString(R.string.location_settings_loading_app_permission_stats)
+ } else {
+ context.getString(R.string.location_settings_summary_location_off)
+ }
+ }
+
+ override fun getIcon(context: Context) =
+ when {
+ Flags.homepageRevamp() -> R.drawable.ic_settings_location_filled
+ else -> R.drawable.ic_settings_location
+ }
+
+ override fun isFlagEnabled(context: Context) = Flags.catalystLocationSettings()
+
+ override fun hasCompleteHierarchy() = false
+
+ override fun fragmentClass() = LocationSettings::class.java
+
+ override fun getPreferenceHierarchy(context: Context) = preferenceHierarchy(this) {}
+
+ companion object {
+ const val KEY = "location_settings"
+ }
+}
diff --git a/src/com/android/settings/location/LocationSettings.java b/src/com/android/settings/location/LocationSettings.java
index 87e8817..6a1d3d2 100644
--- a/src/com/android/settings/location/LocationSettings.java
+++ b/src/com/android/settings/location/LocationSettings.java
@@ -29,6 +29,8 @@
import android.provider.Settings;
import android.util.Log;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import androidx.preference.Preference;
import androidx.preference.PreferenceGroup;
@@ -185,4 +187,9 @@
R.string.location_settings_tooltip_text_for_chrome));
}
}
+
+ @Override
+ public @Nullable String getPreferenceScreenBindingKey(@NonNull Context context) {
+ return LocationScreen.KEY;
+ }
}
diff --git a/src/com/android/settings/network/MobileNetworkListFragment.kt b/src/com/android/settings/network/MobileNetworkListFragment.kt
index 3118088..a0da636 100644
--- a/src/com/android/settings/network/MobileNetworkListFragment.kt
+++ b/src/com/android/settings/network/MobileNetworkListFragment.kt
@@ -92,4 +92,6 @@
simRepositoryFactory(context).canEnterMobileNetworkPage()
}
}
+
+ override fun getPreferenceScreenBindingKey(context: Context) = MobileNetworkListScreen.KEY
}
diff --git a/src/com/android/settings/network/MobileNetworkListScreen.kt b/src/com/android/settings/network/MobileNetworkListScreen.kt
new file mode 100644
index 0000000..93d8ee6
--- /dev/null
+++ b/src/com/android/settings/network/MobileNetworkListScreen.kt
@@ -0,0 +1,50 @@
+/*
+ * 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
+
+import android.content.Context
+import com.android.settings.R
+import com.android.settings.flags.Flags
+import com.android.settingslib.metadata.ProvidePreferenceScreen
+import com.android.settingslib.metadata.preferenceHierarchy
+import com.android.settingslib.preference.PreferenceScreenCreator
+
+@ProvidePreferenceScreen
+class MobileNetworkListScreen : PreferenceScreenCreator {
+ override val key: String
+ get() = KEY
+
+ override val title: Int
+ get() = R.string.provider_network_settings_title
+
+ override val icon: Int
+ get() = R.drawable.ic_sim_card
+
+ override val keywords: Int
+ get() = R.string.keywords_more_mobile_networks
+
+ override fun isFlagEnabled(context: Context) = Flags.catalystMobileNetworkList()
+
+ override fun hasCompleteHierarchy() = false
+
+ override fun fragmentClass() = MobileNetworkListFragment::class.java
+
+ override fun getPreferenceHierarchy(context: Context) = preferenceHierarchy(this) {}
+
+ companion object {
+ const val KEY = "mobile_network_list"
+ }
+}
diff --git a/src/com/android/settings/network/NetworkDashboardFragment.java b/src/com/android/settings/network/NetworkDashboardFragment.java
index 3ba3dc6..2585d04 100644
--- a/src/com/android/settings/network/NetworkDashboardFragment.java
+++ b/src/com/android/settings/network/NetworkDashboardFragment.java
@@ -117,9 +117,8 @@
}
};
- @Nullable
@Override
- public String getPreferenceScreenBindingKey(@NonNull Context context) {
+ public @Nullable String getPreferenceScreenBindingKey(@NonNull Context context) {
return NetworkDashboardScreen.KEY;
}
}
diff --git a/src/com/android/settings/network/NetworkProviderSettings.java b/src/com/android/settings/network/NetworkProviderSettings.java
index 69183ff..b268461 100644
--- a/src/com/android/settings/network/NetworkProviderSettings.java
+++ b/src/com/android/settings/network/NetworkProviderSettings.java
@@ -64,8 +64,8 @@
import com.android.settings.AirplaneModeEnabler;
import com.android.settings.R;
-import com.android.settings.RestrictedSettingsFragment;
import com.android.settings.core.SubSettingLauncher;
+import com.android.settings.dashboard.RestrictedDashboardFragment;
import com.android.settings.datausage.DataUsagePreference;
import com.android.settings.datausage.DataUsageUtils;
import com.android.settings.location.WifiScanningFragment;
@@ -104,7 +104,7 @@
* UI for Mobile network and Wi-Fi network settings.
*/
@SearchIndexable
-public class NetworkProviderSettings extends RestrictedSettingsFragment
+public class NetworkProviderSettings extends RestrictedDashboardFragment
implements Indexable, WifiPickerTracker.WifiPickerTrackerCallback,
WifiDialog2.WifiDialog2Listener, DialogInterface.OnDismissListener,
AirplaneModeEnabler.OnAirplaneModeChangedListener, InternetUpdater.InternetChangeListener {
@@ -356,9 +356,17 @@
mIsGuest = userManager.isGuestUser();
}
- private void addPreferences() {
- addPreferencesFromResource(R.xml.network_provider_settings);
+ @Override
+ protected String getLogTag() {
+ return TAG;
+ }
+ @Override
+ protected int getPreferenceScreenResId() {
+ return R.xml.network_provider_settings;
+ }
+
+ private void addPreferences() {
mAirplaneModeMsgPreference = findPreference(PREF_KEY_AIRPLANE_MODE_MSG);
updateAirplaneModeMsgPreference(mAirplaneModeEnabler.isAirplaneModeOn() /* visible */);
mConnectedWifiEntryPreferenceCategory = findPreference(PREF_KEY_CONNECTED_ACCESS_POINTS);
diff --git a/src/com/android/settings/network/apn/ApnEditor.java b/src/com/android/settings/network/apn/ApnEditor.java
index dc9741d..533fd29 100644
--- a/src/com/android/settings/network/apn/ApnEditor.java
+++ b/src/com/android/settings/network/apn/ApnEditor.java
@@ -16,153 +16,33 @@
package com.android.settings.network.apn;
-import android.app.Dialog;
+import static com.android.settings.network.apn.ApnEditPageProviderKt.EDIT_URL;
+import static com.android.settings.network.apn.ApnEditPageProviderKt.INSERT_URL;
+
import android.app.settings.SettingsEnums;
-import android.content.ContentValues;
-import android.content.Context;
import android.content.Intent;
-import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.PersistableBundle;
import android.os.UserManager;
import android.provider.Telephony;
import android.telephony.CarrierConfigManager;
-import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
-import android.telephony.TelephonyManager;
-import android.text.TextUtils;
import android.util.Log;
-import android.view.KeyEvent;
-import android.view.Menu;
-import android.view.MenuInflater;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.View.OnKeyListener;
-import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
-import androidx.appcompat.app.AlertDialog;
-import androidx.preference.EditTextPreference;
-import androidx.preference.ListPreference;
-import androidx.preference.MultiSelectListPreference;
-import androidx.preference.Preference;
-import androidx.preference.Preference.OnPreferenceChangeListener;
-import androidx.preference.TwoStatePreference;
import com.android.internal.util.ArrayUtils;
-import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
-import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
-import com.android.settings.network.ProxySubscriptionManager;
-import com.android.settingslib.utils.ThreadUtils;
+import com.android.settings.spa.SpaActivity;
import java.util.Arrays;
-import java.util.HashSet;
import java.util.List;
-import java.util.Objects;
-import java.util.Set;
/** Use to edit apn settings. */
-public class ApnEditor extends SettingsPreferenceFragment
- implements OnPreferenceChangeListener, OnKeyListener {
+public class ApnEditor extends SettingsPreferenceFragment {
private static final String TAG = ApnEditor.class.getSimpleName();
- private static final boolean VDBG = false; // STOPSHIP if true
-
- private static final String KEY_AUTH_TYPE = "auth_type";
- private static final String KEY_APN_TYPE = "apn_type";
- private static final String KEY_PROTOCOL = "apn_protocol";
- private static final String KEY_ROAMING_PROTOCOL = "apn_roaming_protocol";
- private static final String KEY_CARRIER_ENABLED = "carrier_enabled";
- private static final String KEY_BEARER_MULTI = "bearer_multi";
- private static final String KEY_MVNO_TYPE = "mvno_type";
- private static final String KEY_PASSWORD = "apn_password";
-
- @VisibleForTesting
- static final int MENU_DELETE = Menu.FIRST;
- private static final int MENU_SAVE = Menu.FIRST + 1;
- private static final int MENU_CANCEL = Menu.FIRST + 2;
-
- @VisibleForTesting
- static String sNotSet;
- @VisibleForTesting
- EditTextPreference mName;
- @VisibleForTesting
- EditTextPreference mApn;
- @VisibleForTesting
- EditTextPreference mProxy;
- @VisibleForTesting
- EditTextPreference mPort;
- @VisibleForTesting
- EditTextPreference mUser;
- @VisibleForTesting
- EditTextPreference mServer;
- @VisibleForTesting
- EditTextPreference mPassword;
- @VisibleForTesting
- EditTextPreference mMmsc;
- @VisibleForTesting
- EditTextPreference mMcc;
- @VisibleForTesting
- EditTextPreference mMnc;
- @VisibleForTesting
- EditTextPreference mMmsProxy;
- @VisibleForTesting
- EditTextPreference mMmsPort;
- @VisibleForTesting
- ListPreference mAuthType;
- @VisibleForTesting
- EditTextPreference mApnType;
- @VisibleForTesting
- ListPreference mProtocol;
- @VisibleForTesting
- ListPreference mRoamingProtocol;
- @VisibleForTesting
- TwoStatePreference mCarrierEnabled;
- @VisibleForTesting
- MultiSelectListPreference mBearerMulti;
- @VisibleForTesting
- ListPreference mMvnoType;
- @VisibleForTesting
- EditTextPreference mMvnoMatchData;
-
- @VisibleForTesting
- ApnData mApnData;
-
- private String mCurMnc;
- private String mCurMcc;
-
- private boolean mNewApn;
- private int mSubId;
- @VisibleForTesting
- ProxySubscriptionManager mProxySubscriptionMgr;
- private int mBearerInitialVal = 0;
- private String mMvnoTypeStr;
- private String mMvnoMatchDataStr;
- @VisibleForTesting
- String[] mReadOnlyApnTypes;
- @VisibleForTesting
- String[] mDefaultApnTypes;
- @VisibleForTesting
- String mDefaultApnProtocol;
- @VisibleForTesting
- String mDefaultApnRoamingProtocol;
- private String[] mReadOnlyApnFields;
- private boolean mReadOnlyApn;
- /**
- * The APN deletion feature within menu is aligned with the APN adding feature.
- * Having only one of them could lead to a UX which not that make sense from user's
- * perspective.
- *
- * mIsAddApnAllowed stores the configuration value reading from
- * CarrierConfigManager.KEY_ALLOW_ADDING_APNS_BOOL to support the presentation
- * control of the menu options. When false, delete option would be invisible to
- * the end user.
- */
- private boolean mIsAddApnAllowed;
- private Uri mCarrierUri;
- private boolean mIsCarrierIdApn;
/**
* APN types for data connections. These are usage categories for an APN
@@ -225,150 +105,41 @@
APN_TYPE_OEM_PRIVATE,
};
- /**
- * Standard projection for the interesting columns of a normal note.
- */
- private static final String[] sProjection = new String[] {
- Telephony.Carriers._ID, // 0
- Telephony.Carriers.NAME, // 1
- Telephony.Carriers.APN, // 2
- Telephony.Carriers.PROXY, // 3
- Telephony.Carriers.PORT, // 4
- Telephony.Carriers.USER, // 5
- Telephony.Carriers.SERVER, // 6
- Telephony.Carriers.PASSWORD, // 7
- Telephony.Carriers.MMSC, // 8
- Telephony.Carriers.MCC, // 9
- Telephony.Carriers.MNC, // 10
- Telephony.Carriers.NUMERIC, // 11
- Telephony.Carriers.MMSPROXY, // 12
- Telephony.Carriers.MMSPORT, // 13
- Telephony.Carriers.AUTH_TYPE, // 14
- Telephony.Carriers.TYPE, // 15
- Telephony.Carriers.PROTOCOL, // 16
- Telephony.Carriers.CARRIER_ENABLED, // 17
- Telephony.Carriers.BEARER, // 18
- Telephony.Carriers.BEARER_BITMASK, // 19
- Telephony.Carriers.ROAMING_PROTOCOL, // 20
- Telephony.Carriers.MVNO_TYPE, // 21
- Telephony.Carriers.MVNO_MATCH_DATA, // 22
- Telephony.Carriers.EDITED_STATUS, // 23
- Telephony.Carriers.USER_EDITABLE, // 24
- Telephony.Carriers.CARRIER_ID // 25
- };
-
- private static final int ID_INDEX = 0;
- @VisibleForTesting
- static final int NAME_INDEX = 1;
- @VisibleForTesting
- static final int APN_INDEX = 2;
- private static final int PROXY_INDEX = 3;
- private static final int PORT_INDEX = 4;
- private static final int USER_INDEX = 5;
- private static final int SERVER_INDEX = 6;
- private static final int PASSWORD_INDEX = 7;
- private static final int MMSC_INDEX = 8;
- @VisibleForTesting
- static final int MCC_INDEX = 9;
- @VisibleForTesting
- static final int MNC_INDEX = 10;
- private static final int MMSPROXY_INDEX = 12;
- private static final int MMSPORT_INDEX = 13;
- private static final int AUTH_TYPE_INDEX = 14;
- @VisibleForTesting
- static final int TYPE_INDEX = 15;
- @VisibleForTesting
- static final int PROTOCOL_INDEX = 16;
- @VisibleForTesting
- static final int CARRIER_ENABLED_INDEX = 17;
- private static final int BEARER_INDEX = 18;
- private static final int BEARER_BITMASK_INDEX = 19;
- @VisibleForTesting
- static final int ROAMING_PROTOCOL_INDEX = 20;
- private static final int MVNO_TYPE_INDEX = 21;
- private static final int MVNO_MATCH_DATA_INDEX = 22;
- private static final int EDITED_INDEX = 23;
- private static final int USER_EDITABLE_INDEX = 24;
- private static final int CARRIER_ID_INDEX = 25;
-
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
+ maybeRedirectToNewPage();
+ finish();
+ }
+
+ private void maybeRedirectToNewPage() {
if (isUserRestricted()) {
Log.e(TAG, "This setting isn't available due to user restriction.");
- finish();
return;
}
- setLifecycleForAllControllers();
-
final Intent intent = getIntent();
final String action = intent.getAction();
- if (TextUtils.isEmpty(action)) {
- finish();
- return;
- }
- mSubId = intent.getIntExtra(ApnSettings.SUB_ID,
- SubscriptionManager.INVALID_SUBSCRIPTION_ID);
- initApnEditorUi();
- getCarrierCustomizedConfig(getContext());
+ int subId =
+ intent.getIntExtra(ApnSettings.SUB_ID, SubscriptionManager.INVALID_SUBSCRIPTION_ID);
- Uri uri = null;
- if (action.equals(Intent.ACTION_EDIT)) {
- uri = intent.getData();
+ Uri uri = intent.getData();
+ if (Intent.ACTION_EDIT.equals(action)) {
if (!uri.isPathPrefixMatch(Telephony.Carriers.CONTENT_URI)) {
Log.e(TAG, "Edit request not for carrier table. Uri: " + uri);
- finish();
- return;
+ } else {
+ String route = ApnEditPageProvider.INSTANCE.getRoute(EDIT_URL, uri, subId);
+ SpaActivity.startSpaActivity(requireContext(), route);
}
- } else if (action.equals(Intent.ACTION_INSERT)) {
- mCarrierUri = intent.getData();
- if (!mCarrierUri.isPathPrefixMatch(Telephony.Carriers.CONTENT_URI)) {
- Log.e(TAG, "Insert request not for carrier table. Uri: " + mCarrierUri);
- finish();
- return;
+ } else if (Intent.ACTION_INSERT.equals(action)) {
+ if (!uri.isPathPrefixMatch(Telephony.Carriers.CONTENT_URI)) {
+ Log.e(TAG, "Insert request not for carrier table. Uri: " + uri);
+ } else {
+ String route = ApnEditPageProvider.INSTANCE.getRoute(
+ INSERT_URL, Telephony.Carriers.CONTENT_URI, subId);
+ SpaActivity.startSpaActivity(getContext(), route);
}
- mNewApn = true;
- mMvnoTypeStr = intent.getStringExtra(ApnSettings.MVNO_TYPE);
- mMvnoMatchDataStr = intent.getStringExtra(ApnSettings.MVNO_MATCH_DATA);
- } else {
- finish();
- return;
- }
-
- // Creates an ApnData to store the apn data temporary, so that we don't need the cursor to
- // get the apn data. The uri is null if the action is ACTION_INSERT, that mean there is no
- // record in the database, so create a empty ApnData to represent a empty row of database.
- if (uri != null) {
- mApnData = getApnDataFromUri(uri);
- } else {
- mApnData = new ApnData(sProjection.length);
- }
- final int carrierId = mApnData.getInteger(CARRIER_ID_INDEX,
- TelephonyManager.UNKNOWN_CARRIER_ID);
- mIsCarrierIdApn = (carrierId > TelephonyManager.UNKNOWN_CARRIER_ID);
-
- final boolean isUserEdited = mApnData.getInteger(EDITED_INDEX,
- Telephony.Carriers.USER_EDITED) == Telephony.Carriers.USER_EDITED;
-
- Log.d(TAG, "onCreate: EDITED " + isUserEdited);
- // if it's not a USER_EDITED apn, check if it's read-only
- if (!isUserEdited && (mApnData.getInteger(USER_EDITABLE_INDEX, 1) == 0
- || apnTypesMatch(mReadOnlyApnTypes, mApnData.getString(TYPE_INDEX)))) {
- Log.d(TAG, "onCreate: apnTypesMatch; read-only APN");
- mReadOnlyApn = true;
- disableAllFields();
- } else if (!ArrayUtils.isEmpty(mReadOnlyApnFields)) {
- disableFields(mReadOnlyApnFields);
- }
- // Make sure that a user cannot break carrier id APN matching
- if (mIsCarrierIdApn) {
- disableFieldsForCarrieridApn();
- }
-
- for (int i = 0; i < getPreferenceScreen().getPreferenceCount(); i++) {
- getPreferenceScreen().getPreference(i).setOnPreferenceChangeListener(this);
}
}
@@ -385,44 +156,6 @@
}
/**
- * Enable ProxySubscriptionMgr with Lifecycle support for all controllers
- * live within this fragment
- */
- private void setLifecycleForAllControllers() {
- if (mProxySubscriptionMgr == null) {
- mProxySubscriptionMgr = ProxySubscriptionManager.getInstance(getContext());
- }
- mProxySubscriptionMgr.setLifecycle(getLifecycle());
- }
-
- @Override
- public void onViewStateRestored(@Nullable Bundle savedInstanceState) {
- super.onViewStateRestored(savedInstanceState);
- fillUI(savedInstanceState == null);
- setCarrierCustomizedConfigToUi();
- }
-
- @VisibleForTesting
- static String formatInteger(String value) {
- try {
- final int intValue = Integer.parseInt(value);
- return String.format(getCorrectDigitsFormat(value), intValue);
- } catch (NumberFormatException e) {
- return value;
- }
- }
-
- /**
- * Get the digits format so we preserve leading 0's.
- * MCCs are 3 digits and MNCs are either 2 or 3.
- */
- static String getCorrectDigitsFormat(String value) {
- if (value.length() == 2) return "%02d";
- else return "%03d";
- }
-
-
- /**
* Check if passed in array of APN types indicates all APN types
* @param apnTypes array of APN types. "*" indicates all types.
* @return true if all apn types are included in the array, false otherwise
@@ -447,1046 +180,12 @@
return true;
}
- /**
- * Check if APN types overlap.
- * @param apnTypesArray1 array of APNs. Empty array indicates no APN type; "*" indicates all
- * types
- * @param apnTypes2 comma separated string of APN types. Empty string represents all types.
- * @return if any apn type matches return true, otherwise return false
- */
- private boolean apnTypesMatch(String[] apnTypesArray1, String apnTypes2) {
- if (ArrayUtils.isEmpty(apnTypesArray1)) {
- return false;
- }
-
- final String[] apnTypesArray1LowerCase = new String[apnTypesArray1.length];
- for (int i = 0; i < apnTypesArray1.length; i++) {
- apnTypesArray1LowerCase[i] = apnTypesArray1[i].toLowerCase();
- }
-
- if (hasAllApns(apnTypesArray1LowerCase) || TextUtils.isEmpty(apnTypes2)) {
- return true;
- }
-
- final List apnTypesList1 = Arrays.asList(apnTypesArray1LowerCase);
- final String[] apnTypesArray2 = apnTypes2.split(",");
-
- for (String apn : apnTypesArray2) {
- if (apnTypesList1.contains(apn.trim().toLowerCase())) {
- Log.d(TAG, "apnTypesMatch: true because match found for " + apn.trim());
- return true;
- }
- }
-
- Log.d(TAG, "apnTypesMatch: false");
- return false;
- }
-
- /**
- * Function to get Preference obj corresponding to an apnField
- * @param apnField apn field name for which pref is needed
- * @return Preference obj corresponding to passed in apnField
- */
- private Preference getPreferenceFromFieldName(String apnField) {
- switch (apnField) {
- case Telephony.Carriers.NAME:
- return mName;
- case Telephony.Carriers.APN:
- return mApn;
- case Telephony.Carriers.PROXY:
- return mProxy;
- case Telephony.Carriers.PORT:
- return mPort;
- case Telephony.Carriers.USER:
- return mUser;
- case Telephony.Carriers.SERVER:
- return mServer;
- case Telephony.Carriers.PASSWORD:
- return mPassword;
- case Telephony.Carriers.MMSPROXY:
- return mMmsProxy;
- case Telephony.Carriers.MMSPORT:
- return mMmsPort;
- case Telephony.Carriers.MMSC:
- return mMmsc;
- case Telephony.Carriers.MCC:
- return mMcc;
- case Telephony.Carriers.MNC:
- return mMnc;
- case Telephony.Carriers.TYPE:
- return mApnType;
- case Telephony.Carriers.AUTH_TYPE:
- return mAuthType;
- case Telephony.Carriers.PROTOCOL:
- return mProtocol;
- case Telephony.Carriers.ROAMING_PROTOCOL:
- return mRoamingProtocol;
- case Telephony.Carriers.CARRIER_ENABLED:
- return mCarrierEnabled;
- case Telephony.Carriers.BEARER:
- case Telephony.Carriers.BEARER_BITMASK:
- return mBearerMulti;
- case Telephony.Carriers.MVNO_TYPE:
- return mMvnoType;
- case Telephony.Carriers.MVNO_MATCH_DATA:
- return mMvnoMatchData;
- }
- return null;
- }
-
- /**
- * Disables given fields so that user cannot modify them
- *
- * @param apnFields fields to be disabled
- */
- private void disableFields(String[] apnFields) {
- for (String apnField : apnFields) {
- final Preference preference = getPreferenceFromFieldName(apnField);
- if (preference != null) {
- preference.setEnabled(false);
- }
- }
- }
-
- /**
- * Disables all fields so that user cannot modify the APN
- */
- private void disableAllFields() {
- mName.setEnabled(false);
- mApn.setEnabled(false);
- mProxy.setEnabled(false);
- mPort.setEnabled(false);
- mUser.setEnabled(false);
- mServer.setEnabled(false);
- mPassword.setEnabled(false);
- mMmsProxy.setEnabled(false);
- mMmsPort.setEnabled(false);
- mMmsc.setEnabled(false);
- mMcc.setEnabled(false);
- mMnc.setEnabled(false);
- mApnType.setEnabled(false);
- mAuthType.setEnabled(false);
- mProtocol.setEnabled(false);
- mRoamingProtocol.setEnabled(false);
- mCarrierEnabled.setEnabled(false);
- mBearerMulti.setEnabled(false);
- mMvnoType.setEnabled(false);
- mMvnoMatchData.setEnabled(false);
- }
-
- /**
- * Disables fields for a carrier id APN to avoid breaking the match criteria
- */
- private void disableFieldsForCarrieridApn() {
- mMcc.setEnabled(false);
- mMnc.setEnabled(false);
- mMvnoType.setEnabled(false);
- mMvnoMatchData.setEnabled(false);
- }
-
@Override
public int getMetricsCategory() {
return SettingsEnums.APN_EDITOR;
}
@VisibleForTesting
- void fillUI(boolean firstTime) {
- if (firstTime) {
- // Fill in all the values from the db in both text editor and summary
- mName.setText(mApnData.getString(NAME_INDEX));
- mApn.setText(mApnData.getString(APN_INDEX));
- mProxy.setText(mApnData.getString(PROXY_INDEX));
- mPort.setText(mApnData.getString(PORT_INDEX));
- mUser.setText(mApnData.getString(USER_INDEX));
- mServer.setText(mApnData.getString(SERVER_INDEX));
- mPassword.setText(mApnData.getString(PASSWORD_INDEX));
- mMmsProxy.setText(mApnData.getString(MMSPROXY_INDEX));
- mMmsPort.setText(mApnData.getString(MMSPORT_INDEX));
- mMmsc.setText(mApnData.getString(MMSC_INDEX));
- mMcc.setText(mApnData.getString(MCC_INDEX));
- mMnc.setText(mApnData.getString(MNC_INDEX));
- mApnType.setText(mApnData.getString(TYPE_INDEX));
- if (mNewApn) {
- final SubscriptionInfo subInfo =
- mProxySubscriptionMgr.getAccessibleSubscriptionInfo(mSubId);
-
- // Country code
- final String mcc = (subInfo == null) ? null : subInfo.getMccString();
- // Network code
- final String mnc = (subInfo == null) ? null : subInfo.getMncString();
-
- if (!TextUtils.isEmpty(mcc)) {
- // Auto populate MNC and MCC for new entries, based on what SIM reports
- mMcc.setText(mcc);
- mMnc.setText(mnc);
- mCurMnc = mnc;
- mCurMcc = mcc;
- }
- }
- final int authVal = mApnData.getInteger(AUTH_TYPE_INDEX, -1);
- if (authVal != -1) {
- mAuthType.setValueIndex(authVal);
- } else {
- mAuthType.setValue(null);
- }
-
- mProtocol.setValue(mApnData.getString(PROTOCOL_INDEX));
- mRoamingProtocol.setValue(mApnData.getString(ROAMING_PROTOCOL_INDEX));
- mCarrierEnabled.setChecked(mApnData.getInteger(CARRIER_ENABLED_INDEX, 1) == 1);
- mBearerInitialVal = mApnData.getInteger(BEARER_INDEX, 0);
-
- final HashSet<String> bearers = new HashSet<String>();
- int bearerBitmask = mApnData.getInteger(BEARER_BITMASK_INDEX, 0);
- if (bearerBitmask == 0) {
- if (mBearerInitialVal == 0) {
- bearers.add("" + 0);
- }
- } else {
- int i = 1;
- while (bearerBitmask != 0) {
- if ((bearerBitmask & 1) == 1) {
- bearers.add("" + i);
- }
- bearerBitmask >>= 1;
- i++;
- }
- }
-
- if (mBearerInitialVal != 0 && !bearers.contains("" + mBearerInitialVal)) {
- // add mBearerInitialVal to bearers
- bearers.add("" + mBearerInitialVal);
- }
- mBearerMulti.setValues(bearers);
-
- mMvnoType.setValue(mApnData.getString(MVNO_TYPE_INDEX));
- mMvnoMatchData.setEnabled(false);
- mMvnoMatchData.setText(mApnData.getString(MVNO_MATCH_DATA_INDEX));
- if (mNewApn && mMvnoTypeStr != null && mMvnoMatchDataStr != null) {
- mMvnoType.setValue(mMvnoTypeStr);
- mMvnoMatchData.setText(mMvnoMatchDataStr);
- }
- }
-
- mName.setSummary(checkNull(mName.getText()));
- mApn.setSummary(checkNull(mApn.getText()));
- mProxy.setSummary(checkNull(mProxy.getText()));
- mPort.setSummary(checkNull(mPort.getText()));
- mUser.setSummary(checkNull(mUser.getText()));
- mServer.setSummary(checkNull(mServer.getText()));
- mPassword.setSummary(starify(mPassword.getText()));
- mMmsProxy.setSummary(checkNull(mMmsProxy.getText()));
- mMmsPort.setSummary(checkNull(mMmsPort.getText()));
- mMmsc.setSummary(checkNull(mMmsc.getText()));
- mMcc.setSummary(formatInteger(checkNull(mMcc.getText())));
- mMnc.setSummary(formatInteger(checkNull(mMnc.getText())));
- mApnType.setSummary(checkNull(mApnType.getText()));
-
- final String authVal = mAuthType.getValue();
- if (authVal != null) {
- final int authValIndex = Integer.parseInt(authVal);
- mAuthType.setValueIndex(authValIndex);
-
- final String[] values = getResources().getStringArray(R.array.apn_auth_entries);
- mAuthType.setSummary(values[authValIndex]);
- } else {
- mAuthType.setSummary(sNotSet);
- }
-
- mProtocol.setSummary(checkNull(protocolDescription(mProtocol.getValue(), mProtocol)));
- mRoamingProtocol.setSummary(
- checkNull(protocolDescription(mRoamingProtocol.getValue(), mRoamingProtocol)));
- mBearerMulti.setSummary(
- checkNull(bearerMultiDescription(mBearerMulti.getValues())));
- mMvnoType.setSummary(
- checkNull(mvnoDescription(mMvnoType.getValue())));
- mMvnoMatchData.setSummary(checkNullforMvnoValue(mMvnoMatchData.getText()));
- // allow user to edit carrier_enabled for some APN
- final boolean ceEditable = getResources().getBoolean(
- R.bool.config_allow_edit_carrier_enabled);
- if (ceEditable) {
- mCarrierEnabled.setEnabled(true);
- } else {
- mCarrierEnabled.setEnabled(false);
- }
- }
-
- /**
- * Returns the UI choice (e.g., "IPv4/IPv6") corresponding to the given
- * raw value of the protocol preference (e.g., "IPV4V6"). If unknown,
- * return null.
- */
- private String protocolDescription(String raw, ListPreference protocol) {
- String uRaw = checkNull(raw).toUpperCase();
- uRaw = uRaw.equals("IPV4") ? "IP" : uRaw;
- final int protocolIndex = protocol.findIndexOfValue(uRaw);
- if (protocolIndex == -1) {
- return null;
- } else {
- final String[] values = getResources().getStringArray(R.array.apn_protocol_entries);
- try {
- return values[protocolIndex];
- } catch (ArrayIndexOutOfBoundsException e) {
- return null;
- }
- }
- }
-
- private String bearerMultiDescription(Set<String> raw) {
- final String[] values = getResources().getStringArray(R.array.bearer_entries);
- final StringBuilder retVal = new StringBuilder();
- boolean first = true;
- for (String bearer : raw) {
- int bearerIndex = mBearerMulti.findIndexOfValue(bearer);
- try {
- if (first) {
- retVal.append(values[bearerIndex]);
- first = false;
- } else {
- retVal.append(", " + values[bearerIndex]);
- }
- } catch (ArrayIndexOutOfBoundsException e) {
- // ignore
- }
- }
- final String val = retVal.toString();
- if (!TextUtils.isEmpty(val)) {
- return val;
- }
- return null;
- }
-
- private String mvnoDescription(String newValue) {
- final int mvnoIndex = mMvnoType.findIndexOfValue(newValue);
- final String oldValue = mMvnoType.getValue();
-
- if (mvnoIndex == -1) {
- return null;
- } else {
- final String[] values = getResources().getStringArray(R.array.mvno_type_entries);
- final boolean mvnoMatchDataUneditable =
- mReadOnlyApn || (mReadOnlyApnFields != null
- && Arrays.asList(mReadOnlyApnFields)
- .contains(Telephony.Carriers.MVNO_MATCH_DATA));
- mMvnoMatchData.setEnabled(!mvnoMatchDataUneditable && mvnoIndex != 0);
- if (newValue != null && !newValue.equals(oldValue)) {
- if (values[mvnoIndex].equals("SPN")) {
- TelephonyManager telephonyManager = (TelephonyManager)
- getContext().getSystemService(TelephonyManager.class);
- final TelephonyManager telephonyManagerForSubId =
- telephonyManager.createForSubscriptionId(mSubId);
- if (telephonyManagerForSubId != null) {
- telephonyManager = telephonyManagerForSubId;
- }
- mMvnoMatchData.setText(telephonyManager.getSimOperatorName());
- } else if (values[mvnoIndex].equals("IMSI")) {
- final SubscriptionInfo subInfo =
- mProxySubscriptionMgr.getAccessibleSubscriptionInfo(mSubId);
- final String mcc = (subInfo == null) ? "" :
- Objects.toString(subInfo.getMccString(), "");
- final String mnc = (subInfo == null) ? "" :
- Objects.toString(subInfo.getMncString(), "");
- mMvnoMatchData.setText(mcc + mnc + "x");
- } else if (values[mvnoIndex].equals("GID")) {
- TelephonyManager telephonyManager = (TelephonyManager)
- getContext().getSystemService(TelephonyManager.class);
- final TelephonyManager telephonyManagerForSubId =
- telephonyManager.createForSubscriptionId(mSubId);
- if (telephonyManagerForSubId != null) {
- telephonyManager = telephonyManagerForSubId;
- }
- mMvnoMatchData.setText(telephonyManager.getGroupIdLevel1());
- } else {
- // mvno type 'none' case. At this time, mvnoIndex should be 0.
- mMvnoMatchData.setText("");
- }
- }
-
- try {
- return values[mvnoIndex];
- } catch (ArrayIndexOutOfBoundsException e) {
- return null;
- }
- }
- }
- /**
- * Callback when preference status changed.
- */
- public boolean onPreferenceChange(Preference preference, Object newValue) {
- String key = preference.getKey();
- if (KEY_AUTH_TYPE.equals(key)) {
- try {
- final int index = Integer.parseInt((String) newValue);
- mAuthType.setValueIndex(index);
-
- final String[] values = getResources().getStringArray(R.array.apn_auth_entries);
- mAuthType.setSummary(values[index]);
- } catch (NumberFormatException e) {
- return false;
- }
- } else if (KEY_APN_TYPE.equals(key)) {
- String data = (TextUtils.isEmpty((String) newValue)
- && !ArrayUtils.isEmpty(mDefaultApnTypes))
- ? getEditableApnType(mDefaultApnTypes) : (String) newValue;
- if (!TextUtils.isEmpty(data)) {
- mApnType.setSummary(data);
- }
- } else if (KEY_PROTOCOL.equals(key)) {
- final String protocol = protocolDescription((String) newValue, mProtocol);
- if (protocol == null) {
- return false;
- }
- mProtocol.setSummary(protocol);
- mProtocol.setValue((String) newValue);
- } else if (KEY_ROAMING_PROTOCOL.equals(key)) {
- final String protocol = protocolDescription((String) newValue, mRoamingProtocol);
- if (protocol == null) {
- return false;
- }
- mRoamingProtocol.setSummary(protocol);
- mRoamingProtocol.setValue((String) newValue);
- } else if (KEY_BEARER_MULTI.equals(key)) {
- final String bearer = bearerMultiDescription((Set<String>) newValue);
- if (bearer == null) {
- return false;
- }
- mBearerMulti.setValues((Set<String>) newValue);
- mBearerMulti.setSummary(bearer);
- } else if (KEY_MVNO_TYPE.equals(key)) {
- final String mvno = mvnoDescription((String) newValue);
- if (mvno == null) {
- return false;
- }
- mMvnoType.setValue((String) newValue);
- mMvnoType.setSummary(mvno);
- mMvnoMatchData.setSummary(checkNullforMvnoValue(mMvnoMatchData.getText()));
- } else if (KEY_PASSWORD.equals(key)) {
- mPassword.setSummary(starify(newValue != null ? String.valueOf(newValue) : ""));
- } else if (KEY_CARRIER_ENABLED.equals(key)) {
- // do nothing
- } else {
- preference.setSummary(checkNull(newValue != null ? String.valueOf(newValue) : null));
- }
- return true;
- }
-
- @Override
- public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
- super.onCreateOptionsMenu(menu, inflater);
- // If it's a new APN, then cancel will delete the new entry in onPause
- // If APN add is not allowed, delete might lead to issue regarding recovery
- if (!mNewApn && !mReadOnlyApn && mIsAddApnAllowed) {
- menu.add(0, MENU_DELETE, 0, R.string.menu_delete)
- .setIcon(R.drawable.ic_delete);
- }
- if (!mReadOnlyApn) {
- menu.add(0, MENU_SAVE, 0, R.string.menu_save)
- .setIcon(android.R.drawable.ic_menu_save);
- }
- menu.add(0, MENU_CANCEL, 0, R.string.menu_cancel)
- .setIcon(android.R.drawable.ic_menu_close_clear_cancel);
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case MENU_DELETE:
- deleteApn();
- finish();
- return true;
- case MENU_SAVE:
- if (validateAndSaveApnData()) {
- finish();
- }
- return true;
- case MENU_CANCEL:
- finish();
- return true;
- default:
- return super.onOptionsItemSelected(item);
- }
- }
-
- @Override
- public void onViewCreated(View view, Bundle savedInstanceState) {
- super.onViewCreated(view, savedInstanceState);
- view.setOnKeyListener(this);
- view.setFocusableInTouchMode(true);
- view.requestFocus();
- }
-
- /**
- * Try to save the apn data when pressed the back button. An error message will be displayed if
- * the apn data is invalid.
- *
- * TODO(b/77339593): Try to keep the same behavior between back button and up navigate button.
- * We will save the valid apn data to the database when pressed the back button, but discard all
- * user changed when pressed the up navigate button.
- */
- @Override
- public boolean onKey(View v, int keyCode, KeyEvent event) {
- if (event.getAction() != KeyEvent.ACTION_DOWN) return false;
- switch (keyCode) {
- case KeyEvent.KEYCODE_BACK: {
- if (validateAndSaveApnData()) {
- finish();
- }
- return true;
- }
- }
- return false;
- }
-
- /**
- * Add key, value to {@code cv} and compare the value against the value at index in
- * {@link #mApnData}.
- *
- * <p>
- * The key, value will not add to {@code cv} if value is null.
- *
- * @return true if values are different. {@code assumeDiff} indicates if values can be assumed
- * different in which case no comparison is needed.
- */
- boolean setStringValueAndCheckIfDiff(
- ContentValues cv, String key, String value, boolean assumeDiff, int index) {
- final String valueFromLocalCache = mApnData.getString(index);
- if (VDBG) {
- Log.d(TAG, "setStringValueAndCheckIfDiff: assumeDiff: " + assumeDiff
- + " key: " + key
- + " value: '" + value
- + "' valueFromDb: '" + valueFromLocalCache + "'");
- }
- final boolean isDiff = assumeDiff
- || !((TextUtils.isEmpty(value) && TextUtils.isEmpty(valueFromLocalCache))
- || (value != null && value.equals(valueFromLocalCache)));
-
- if (isDiff && value != null) {
- cv.put(key, value);
- }
- return isDiff;
- }
-
- /**
- * Add key, value to {@code cv} and compare the value against the value at index in
- * {@link #mApnData}.
- *
- * @return true if values are different. {@code assumeDiff} indicates if values can be assumed
- * different in which case no comparison is needed.
- */
- boolean setIntValueAndCheckIfDiff(
- ContentValues cv, String key, int value, boolean assumeDiff, int index) {
- final Integer valueFromLocalCache = mApnData.getInteger(index);
- if (VDBG) {
- Log.d(TAG, "setIntValueAndCheckIfDiff: assumeDiff: " + assumeDiff
- + " key: " + key
- + " value: '" + value
- + "' valueFromDb: '" + valueFromLocalCache + "'");
- }
-
- final boolean isDiff = assumeDiff || value != valueFromLocalCache;
- if (isDiff) {
- cv.put(key, value);
- }
- return isDiff;
- }
-
- /**
- * Validates the apn data and save it to the database if it's valid.
- *
- * <p>
- * A dialog with error message will be displayed if the APN data is invalid.
- *
- * @return true if there is no error
- */
- @VisibleForTesting
- boolean validateAndSaveApnData() {
- // Nothing to do if it's a read only APN
- if (mReadOnlyApn) {
- return true;
- }
-
- final String name = checkNotSet(mName.getText());
- final String apn = checkNotSet(mApn.getText());
- final String mcc = checkNotSet(mMcc.getText());
- final String mnc = checkNotSet(mMnc.getText());
-
- final String errorMsg = validateApnData();
- if (errorMsg != null) {
- showError();
- return false;
- }
-
- final ContentValues values = new ContentValues();
- // call update() if it's a new APN. If not, check if any field differs from the db value;
- // if any diff is found update() should be called
- boolean callUpdate = mNewApn;
- callUpdate = setStringValueAndCheckIfDiff(values,
- Telephony.Carriers.NAME,
- name,
- callUpdate,
- NAME_INDEX);
-
- callUpdate = setStringValueAndCheckIfDiff(values,
- Telephony.Carriers.APN,
- apn,
- callUpdate,
- APN_INDEX);
-
- callUpdate = setStringValueAndCheckIfDiff(values,
- Telephony.Carriers.PROXY,
- checkNotSet(mProxy.getText()),
- callUpdate,
- PROXY_INDEX);
-
- callUpdate = setStringValueAndCheckIfDiff(values,
- Telephony.Carriers.PORT,
- checkNotSet(mPort.getText()),
- callUpdate,
- PORT_INDEX);
-
- callUpdate = setStringValueAndCheckIfDiff(values,
- Telephony.Carriers.MMSPROXY,
- checkNotSet(mMmsProxy.getText()),
- callUpdate,
- MMSPROXY_INDEX);
-
- callUpdate = setStringValueAndCheckIfDiff(values,
- Telephony.Carriers.MMSPORT,
- checkNotSet(mMmsPort.getText()),
- callUpdate,
- MMSPORT_INDEX);
-
- callUpdate = setStringValueAndCheckIfDiff(values,
- Telephony.Carriers.USER,
- checkNotSet(mUser.getText()),
- callUpdate,
- USER_INDEX);
-
- callUpdate = setStringValueAndCheckIfDiff(values,
- Telephony.Carriers.SERVER,
- checkNotSet(mServer.getText()),
- callUpdate,
- SERVER_INDEX);
-
- callUpdate = setStringValueAndCheckIfDiff(values,
- Telephony.Carriers.PASSWORD,
- checkNotSet(mPassword.getText()),
- callUpdate,
- PASSWORD_INDEX);
-
- callUpdate = setStringValueAndCheckIfDiff(values,
- Telephony.Carriers.MMSC,
- checkNotSet(mMmsc.getText()),
- callUpdate,
- MMSC_INDEX);
-
- final String authVal = mAuthType.getValue();
- if (authVal != null) {
- callUpdate = setIntValueAndCheckIfDiff(values,
- Telephony.Carriers.AUTH_TYPE,
- Integer.parseInt(authVal),
- callUpdate,
- AUTH_TYPE_INDEX);
- }
-
- callUpdate = setStringValueAndCheckIfDiff(values,
- Telephony.Carriers.PROTOCOL,
- checkNotSet(mProtocol.getValue()),
- callUpdate,
- PROTOCOL_INDEX);
-
- callUpdate = setStringValueAndCheckIfDiff(values,
- Telephony.Carriers.ROAMING_PROTOCOL,
- checkNotSet(mRoamingProtocol.getValue()),
- callUpdate,
- ROAMING_PROTOCOL_INDEX);
-
- callUpdate = setStringValueAndCheckIfDiff(values,
- Telephony.Carriers.TYPE,
- checkNotSet(getUserEnteredApnType()),
- callUpdate,
- TYPE_INDEX);
-
- callUpdate = setStringValueAndCheckIfDiff(values,
- Telephony.Carriers.MCC,
- mcc,
- callUpdate,
- MCC_INDEX);
-
- callUpdate = setStringValueAndCheckIfDiff(values,
- Telephony.Carriers.MNC,
- mnc,
- callUpdate,
- MNC_INDEX);
-
- values.put(Telephony.Carriers.NUMERIC, mcc + mnc);
-
- if (mCurMnc != null && mCurMcc != null) {
- if (mCurMnc.equals(mnc) && mCurMcc.equals(mcc)) {
- values.put(Telephony.Carriers.CURRENT, 1);
- }
- }
-
- final Set<String> bearerSet = mBearerMulti.getValues();
- int bearerBitmask = 0;
- for (String bearer : bearerSet) {
- if (Integer.parseInt(bearer) == 0) {
- bearerBitmask = 0;
- break;
- } else {
- bearerBitmask |= getBitmaskForTech(Integer.parseInt(bearer));
- }
- }
- callUpdate = setIntValueAndCheckIfDiff(values,
- Telephony.Carriers.BEARER_BITMASK,
- bearerBitmask,
- callUpdate,
- BEARER_BITMASK_INDEX);
-
- int bearerVal;
- if (bearerBitmask == 0 || mBearerInitialVal == 0) {
- bearerVal = 0;
- } else if (bitmaskHasTech(bearerBitmask, mBearerInitialVal)) {
- bearerVal = mBearerInitialVal;
- } else {
- // bearer field was being used but bitmask has changed now and does not include the
- // initial bearer value -- setting bearer to 0 but maybe better behavior is to choose a
- // random tech from the new bitmask??
- bearerVal = 0;
- }
- callUpdate = setIntValueAndCheckIfDiff(values,
- Telephony.Carriers.BEARER,
- bearerVal,
- callUpdate,
- BEARER_INDEX);
-
- callUpdate = setStringValueAndCheckIfDiff(values,
- Telephony.Carriers.MVNO_TYPE,
- checkNotSet(mMvnoType.getValue()),
- callUpdate,
- MVNO_TYPE_INDEX);
-
- callUpdate = setStringValueAndCheckIfDiff(values,
- Telephony.Carriers.MVNO_MATCH_DATA,
- checkNotSet(mMvnoMatchData.getText()),
- callUpdate,
- MVNO_MATCH_DATA_INDEX);
-
- callUpdate = setIntValueAndCheckIfDiff(values,
- Telephony.Carriers.CARRIER_ENABLED,
- mCarrierEnabled.isChecked() ? 1 : 0,
- callUpdate,
- CARRIER_ENABLED_INDEX);
-
- values.put(Telephony.Carriers.EDITED_STATUS, Telephony.Carriers.USER_EDITED);
-
- if (callUpdate) {
- final Uri uri = mApnData.getUri() == null ? mCarrierUri : mApnData.getUri();
- updateApnDataToDatabase(uri, values);
- } else {
- if (VDBG) Log.d(TAG, "validateAndSaveApnData: not calling update()");
- }
-
- return true;
- }
-
- private void updateApnDataToDatabase(Uri uri, ContentValues values) {
- ThreadUtils.postOnBackgroundThread(() -> {
- if (uri.equals(mCarrierUri)) {
- // Add a new apn to the database
- final Uri newUri = getContentResolver().insert(mCarrierUri, values);
- if (newUri == null) {
- Log.e(TAG, "Can't add a new apn to database " + mCarrierUri);
- }
- } else {
- // Update the existing apn
- getContentResolver().update(
- uri, values, null /* where */, null /* selection Args */);
- }
- });
- }
-
- /**
- * Validates whether the apn data is valid.
- *
- * @return An error message if the apn data is invalid, otherwise return null.
- */
- @VisibleForTesting
- String validateApnData() {
- String errorMsg = null;
-
- final String name = checkNotSet(mName.getText());
- final String apn = checkNotSet(mApn.getText());
- final String mcc = checkNotSet(mMcc.getText());
- final String mnc = checkNotSet(mMnc.getText());
- boolean doNotCheckMccMnc = mIsCarrierIdApn && TextUtils.isEmpty(mcc)
- && TextUtils.isEmpty(mnc);
- if (TextUtils.isEmpty(name)) {
- errorMsg = getResources().getString(R.string.error_name_empty);
- } else if (TextUtils.isEmpty(apn)) {
- errorMsg = getResources().getString(R.string.error_apn_empty);
- } else if (doNotCheckMccMnc) {
- Log.d(TAG, "validateApnData: carrier id APN does not have mcc/mnc defined");
- // no op, skip mcc mnc null check
- } else if (mcc == null || mcc.length() != 3) {
- errorMsg = getResources().getString(R.string.error_mcc_not3);
- } else if ((mnc == null || (mnc.length() & 0xFFFE) != 2)) {
- errorMsg = getResources().getString(R.string.error_mnc_not23);
- }
-
- if (errorMsg == null) {
- // if carrier does not allow editing certain apn types, make sure type does not include
- // those
- if (!ArrayUtils.isEmpty(mReadOnlyApnTypes)
- && apnTypesMatch(mReadOnlyApnTypes, getUserEnteredApnType())) {
- final StringBuilder stringBuilder = new StringBuilder();
- for (String type : mReadOnlyApnTypes) {
- stringBuilder.append(type).append(", ");
- Log.d(TAG, "validateApnData: appending type: " + type);
- }
- // remove last ", "
- if (stringBuilder.length() >= 2) {
- stringBuilder.delete(stringBuilder.length() - 2, stringBuilder.length());
- }
- errorMsg = String.format(getResources().getString(R.string.error_adding_apn_type),
- stringBuilder);
- }
- }
-
- return errorMsg;
- }
-
- @VisibleForTesting
- void showError() {
- ErrorDialog.showError(this);
- }
-
- private void deleteApn() {
- if (mApnData.getUri() != null) {
- getContentResolver().delete(mApnData.getUri(), null, null);
- mApnData = new ApnData(sProjection.length);
- }
- }
-
- private String starify(String value) {
- if (value == null || value.length() == 0) {
- return sNotSet;
- } else {
- final char[] password = new char[value.length()];
- for (int i = 0; i < password.length; i++) {
- password[i] = '*';
- }
- return new String(password);
- }
- }
-
- /**
- * Returns {@link #sNotSet} if the given string {@code value} is null or empty. The string
- * {@link #sNotSet} typically used as the default display when an entry in the preference is
- * null or empty.
- */
- private String checkNull(String value) {
- return TextUtils.isEmpty(value) ? sNotSet : value;
- }
-
- /**
- * To make traslation be diversity, use another string id for MVNO value.
- */
- private String checkNullforMvnoValue(String value) {
- String notSetForMvnoValue = getResources().getString(R.string.apn_not_set_for_mvno);
- return TextUtils.isEmpty(value) ? notSetForMvnoValue : value;
- }
-
- /**
- * Returns null if the given string {@code value} equals to {@link #sNotSet}. This method
- * should be used when convert a string value from preference to database.
- */
- private String checkNotSet(String value) {
- return sNotSet.equals(value) ? null : value;
- }
-
- @VisibleForTesting
- String getUserEnteredApnType() {
- // if user has not specified a type, map it to "ALL APN TYPES THAT ARE NOT READ-ONLY"
- // but if user enter empty type, map it just for default
- String userEnteredApnType = mApnType.getText();
- if (userEnteredApnType != null) userEnteredApnType = userEnteredApnType.trim();
- if ((TextUtils.isEmpty(userEnteredApnType)
- || APN_TYPE_ALL.equals(userEnteredApnType))) {
- userEnteredApnType = getEditableApnType(APN_TYPES);
- }
- Log.d(TAG, "getUserEnteredApnType: changed apn type to editable apn types: "
- + userEnteredApnType);
- return userEnteredApnType;
- }
-
- private String getEditableApnType(String[] apnTypeList) {
- final StringBuilder editableApnTypes = new StringBuilder();
- final List<String> readOnlyApnTypes = Arrays.asList(mReadOnlyApnTypes);
- boolean first = true;
- for (String apnType : apnTypeList) {
- // add APN type if it is not read-only and is not wild-cardable
- if (!readOnlyApnTypes.contains(apnType)
- && !apnType.equals(APN_TYPE_IA)
- && !apnType.equals(APN_TYPE_EMERGENCY)
- && !apnType.equals(APN_TYPE_MCX)
- && !apnType.equals(APN_TYPE_IMS)) {
- if (first) {
- first = false;
- } else {
- editableApnTypes.append(",");
- }
- editableApnTypes.append(apnType);
- }
- }
- return editableApnTypes.toString();
- }
-
- private void initApnEditorUi() {
- addPreferencesFromResource(R.xml.apn_editor);
-
- sNotSet = getResources().getString(R.string.apn_not_set);
- mName = (EditTextPreference) findPreference("apn_name");
- mApn = (EditTextPreference) findPreference("apn_apn");
- mProxy = (EditTextPreference) findPreference("apn_http_proxy");
- mPort = (EditTextPreference) findPreference("apn_http_port");
- mUser = (EditTextPreference) findPreference("apn_user");
- mServer = (EditTextPreference) findPreference("apn_server");
- mPassword = (EditTextPreference) findPreference(KEY_PASSWORD);
- mMmsProxy = (EditTextPreference) findPreference("apn_mms_proxy");
- mMmsPort = (EditTextPreference) findPreference("apn_mms_port");
- mMmsc = (EditTextPreference) findPreference("apn_mmsc");
- mMcc = (EditTextPreference) findPreference("apn_mcc");
- mMnc = (EditTextPreference) findPreference("apn_mnc");
- mApnType = (EditTextPreference) findPreference("apn_type");
- mAuthType = (ListPreference) findPreference(KEY_AUTH_TYPE);
- mProtocol = (ListPreference) findPreference(KEY_PROTOCOL);
- mRoamingProtocol = (ListPreference) findPreference(KEY_ROAMING_PROTOCOL);
- mCarrierEnabled = (TwoStatePreference) findPreference(KEY_CARRIER_ENABLED);
- mBearerMulti = (MultiSelectListPreference) findPreference(KEY_BEARER_MULTI);
- mMvnoType = (ListPreference) findPreference(KEY_MVNO_TYPE);
- mMvnoMatchData = (EditTextPreference) findPreference("mvno_match_data");
- }
-
- @VisibleForTesting
- protected void getCarrierCustomizedConfig(Context context) {
- mReadOnlyApn = false;
- mReadOnlyApnTypes = null;
- mReadOnlyApnFields = null;
- mIsAddApnAllowed = true;
-
- final CarrierConfigManager configManager = (CarrierConfigManager)
- context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
- if (configManager != null) {
- final PersistableBundle b = configManager.getConfigForSubId(mSubId);
- if (b != null) {
- mReadOnlyApnTypes = getReadOnlyApnTypes(b);
- if (!ArrayUtils.isEmpty(mReadOnlyApnTypes)) {
- Log.d(TAG,
- "onCreate: read only APN type: " + Arrays.toString(mReadOnlyApnTypes));
- }
- mReadOnlyApnFields = b.getStringArray(
- CarrierConfigManager.KEY_READ_ONLY_APN_FIELDS_STRING_ARRAY);
-
- mDefaultApnTypes = b.getStringArray(
- CarrierConfigManager.KEY_APN_SETTINGS_DEFAULT_APN_TYPES_STRING_ARRAY);
-
- if (!ArrayUtils.isEmpty(mDefaultApnTypes)) {
- Log.d(TAG, "onCreate: default apn types: " + Arrays.toString(mDefaultApnTypes));
- }
-
- mDefaultApnProtocol = b.getString(
- CarrierConfigManager.Apn.KEY_SETTINGS_DEFAULT_PROTOCOL_STRING);
- if (!TextUtils.isEmpty(mDefaultApnProtocol)) {
- Log.d(TAG, "onCreate: default apn protocol: " + mDefaultApnProtocol);
- }
-
- mDefaultApnRoamingProtocol = b.getString(
- CarrierConfigManager.Apn.KEY_SETTINGS_DEFAULT_ROAMING_PROTOCOL_STRING);
- if (!TextUtils.isEmpty(mDefaultApnRoamingProtocol)) {
- Log.d(TAG, "onCreate: default apn roaming protocol: "
- + mDefaultApnRoamingProtocol);
- }
-
- mIsAddApnAllowed = b.getBoolean(CarrierConfigManager.KEY_ALLOW_ADDING_APNS_BOOL);
- if (!mIsAddApnAllowed) {
- Log.d(TAG, "onCreate: not allow to add new APN");
- }
- }
- }
- }
-
- private void setCarrierCustomizedConfigToUi() {
- if (TextUtils.isEmpty(mApnType.getText()) && !ArrayUtils.isEmpty(mDefaultApnTypes)) {
- String value = getEditableApnType(mDefaultApnTypes);
- mApnType.setText(value);
- mApnType.setSummary(value);
- }
-
- String protocol = protocolDescription(mDefaultApnProtocol, mProtocol);
- if (TextUtils.isEmpty(mProtocol.getValue()) && !TextUtils.isEmpty(protocol)) {
- mProtocol.setValue(mDefaultApnProtocol);
- mProtocol.setSummary(protocol);
- }
-
- String roamingProtocol = protocolDescription(mDefaultApnRoamingProtocol, mRoamingProtocol);
- if (TextUtils.isEmpty(mRoamingProtocol.getValue()) && !TextUtils.isEmpty(roamingProtocol)) {
- mRoamingProtocol.setValue(mDefaultApnRoamingProtocol);
- mRoamingProtocol.setSummary(roamingProtocol);
- }
- }
-
- /**
- * Dialog of error message.
- */
- public static class ErrorDialog extends InstrumentedDialogFragment {
- /**
- * Show error dialog.
- */
- public static void showError(ApnEditor editor) {
- final ErrorDialog dialog = new ErrorDialog();
- dialog.setTargetFragment(editor, 0);
- dialog.show(editor.getFragmentManager(), "error");
- }
-
- @Override
- public Dialog onCreateDialog(Bundle savedInstanceState) {
- final String msg = ((ApnEditor) getTargetFragment()).validateApnData();
-
- return new AlertDialog.Builder(getContext())
- .setTitle(R.string.error_title)
- .setPositiveButton(android.R.string.ok, null)
- .setMessage(msg)
- .create();
- }
-
- @Override
- public int getMetricsCategory() {
- return SettingsEnums.DIALOG_APN_EDITOR_ERROR;
- }
- }
-
- @VisibleForTesting
- ApnData getApnDataFromUri(Uri uri) {
- ApnData apnData = null;
- try (Cursor cursor = getContentResolver().query(
- uri,
- sProjection,
- null /* selection */,
- null /* selectionArgs */,
- null /* sortOrder */)) {
- if (cursor != null && cursor.moveToFirst()) {
- apnData = new ApnData(uri, cursor);
- }
- }
-
- if (apnData == null) {
- Log.d(TAG, "Can't get apnData from Uri " + uri);
- }
-
- return apnData;
- }
-
- @VisibleForTesting
boolean isUserRestricted() {
UserManager userManager = getContext().getSystemService(UserManager.class);
if (userManager == null) {
@@ -1502,80 +201,4 @@
}
return false;
}
-
- @VisibleForTesting
- static class ApnData {
- /**
- * The uri correspond to a database row of the apn data. This should be null if the apn
- * is not in the database.
- */
- Uri mUri;
-
- /** Each element correspond to a column of the database row. */
- Object[] mData;
-
- ApnData(int numberOfField) {
- mData = new Object[numberOfField];
- }
-
- ApnData(Uri uri, Cursor cursor) {
- mUri = uri;
- mData = new Object[cursor.getColumnCount()];
- for (int i = 0; i < mData.length; i++) {
- switch (cursor.getType(i)) {
- case Cursor.FIELD_TYPE_FLOAT:
- mData[i] = cursor.getFloat(i);
- break;
- case Cursor.FIELD_TYPE_INTEGER:
- mData[i] = cursor.getInt(i);
- break;
- case Cursor.FIELD_TYPE_STRING:
- mData[i] = cursor.getString(i);
- break;
- case Cursor.FIELD_TYPE_BLOB:
- mData[i] = cursor.getBlob(i);
- break;
- default:
- mData[i] = null;
- }
- }
- }
-
- Uri getUri() {
- return mUri;
- }
-
- void setUri(Uri uri) {
- mUri = uri;
- }
-
- Integer getInteger(int index) {
- return (Integer) mData[index];
- }
-
- Integer getInteger(int index, Integer defaultValue) {
- final Integer val = getInteger(index);
- return val == null ? defaultValue : val;
- }
-
- String getString(int index) {
- return (String) mData[index];
- }
- }
-
- private static int getBitmaskForTech(int radioTech) {
- if (radioTech >= 1) {
- return (1 << (radioTech - 1));
- }
- return 0;
- }
-
- private static boolean bitmaskHasTech(int bearerBitmask, int radioTech) {
- if (bearerBitmask == 0) {
- return true;
- } else if (radioTech >= 1) {
- return ((bearerBitmask & (1 << (radioTech - 1))) != 0);
- }
- return false;
- }
}
diff --git a/tests/robotests/OWNERS b/tests/robotests/OWNERS
index 8a7a27e..e15af1c 100644
--- a/tests/robotests/OWNERS
+++ b/tests/robotests/OWNERS
@@ -1,2 +1,3 @@
# We do not guard tests - everyone is welcomed to contribute to tests.
-per-file *.java=*
\ No newline at end of file
+per-file *.java=*
+per-file *.kt=*
diff --git a/tests/robotests/src/com/android/settings/accessibility/ColorAndMotionScreenTest.kt b/tests/robotests/src/com/android/settings/accessibility/ColorAndMotionScreenTest.kt
new file mode 100644
index 0000000..6d7164e
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/accessibility/ColorAndMotionScreenTest.kt
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.accessibility
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.settings.flags.Flags
+import com.android.settingslib.preference.CatalystScreenTestCase
+import com.android.settingslib.preference.PreferenceScreenCreator
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class ColorAndMotionScreenTest : CatalystScreenTestCase() {
+ override val preferenceScreenCreator: PreferenceScreenCreator = ColorAndMotionScreen()
+ override val flagName: String = Flags.FLAG_CATALYST_ACCESSIBILITY_COLOR_AND_MOTION
+
+ override fun migration() {}
+
+ @Test
+ fun key() {
+ assertThat(preferenceScreenCreator.key).isEqualTo(ColorAndMotionScreen.KEY)
+ }
+}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/accessibility/shortcuts/EditShortcutsPreferenceFragmentTest.java b/tests/robotests/src/com/android/settings/accessibility/shortcuts/EditShortcutsPreferenceFragmentTest.java
index 414fe63..b3270e9 100644
--- a/tests/robotests/src/com/android/settings/accessibility/shortcuts/EditShortcutsPreferenceFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/shortcuts/EditShortcutsPreferenceFragmentTest.java
@@ -16,6 +16,9 @@
package com.android.settings.accessibility.shortcuts;
+import static android.provider.Settings.ACTION_ACCESSIBILITY_SHORTCUT_SETTINGS;
+
+import static com.android.internal.accessibility.AccessibilityShortcutController.DALTONIZER_COMPONENT_NAME;
import static com.android.internal.accessibility.AccessibilityShortcutController.MAGNIFICATION_COMPONENT_NAME;
import static com.android.internal.accessibility.AccessibilityShortcutController.MAGNIFICATION_CONTROLLER_NAME;
import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.SOFTWARE;
@@ -45,6 +48,7 @@
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.Flags;
+import androidx.annotation.Nullable;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.testing.FragmentScenario;
import androidx.lifecycle.Lifecycle;
@@ -160,7 +164,7 @@
public void showEditShortcutScreen_inSuw_launchSubSettingWithSuw() {
EditShortcutsPreferenceFragment.showEditShortcutScreen(
mActivity, METRICS_CATEGORY, SCREEN_TITLE,
- TARGET_FAKE_COMPONENT, createSuwIntent(new Intent(), /* isInSuw= */ true));
+ TARGET_FAKE_COMPONENT, setIntentInSuw(new Intent(), /* isInSuw= */ true));
assertLaunchSubSettingWithCurrentTargetComponents(
TARGET_FAKE_COMPONENT.flattenToString(), /* isInSuw= */ true);
@@ -199,6 +203,53 @@
}
@Test
+ @EnableFlags(
+ com.android.settings.accessibility.Flags.FLAG_TOGGLE_FEATURE_FRAGMENT_COLLECTION_INFO)
+ public void shortcutDescriptionPref_defaultLaunch_notVisible() {
+ mFragmentScenario = createFragScenario(/* isInSuw= */ false, TARGET);
+ mFragmentScenario.moveToState(Lifecycle.State.CREATED);
+
+ mFragmentScenario.onFragment(fragment -> {
+ Preference preference = fragment.findPreference(
+ mContext.getString(R.string.accessibility_shortcut_description_pref));
+ assertThat(preference.isVisible()).isFalse();
+ });
+ }
+
+ @Test
+ @EnableFlags(
+ com.android.settings.accessibility.Flags.FLAG_TOGGLE_FEATURE_FRAGMENT_COLLECTION_INFO)
+ public void shortcutDescriptionPref_launchFromAction_singleTarget_notVisible() {
+ mFragmentScenario = createFragScenario(/* isInSuw= */ false, List.of(TARGET),
+ ACTION_ACCESSIBILITY_SHORTCUT_SETTINGS);
+ mFragmentScenario.moveToState(Lifecycle.State.CREATED);
+
+ mFragmentScenario.onFragment(fragment -> {
+ Preference preference = fragment.findPreference(
+ mContext.getString(R.string.accessibility_shortcut_description_pref));
+ assertThat(preference.isVisible()).isFalse();
+ });
+ }
+
+ @Test
+ @EnableFlags(
+ com.android.settings.accessibility.Flags.FLAG_TOGGLE_FEATURE_FRAGMENT_COLLECTION_INFO)
+ public void shortcutDescriptionPref_launchFromAction_multipleTargets_isVisible() {
+ mFragmentScenario = createFragScenario(/* isInSuw= */ false,
+ // Both of these components are system components with known labels, so we don't
+ // need to mock AccessibilityManager with fake labels.
+ List.of(TARGET, DALTONIZER_COMPONENT_NAME.flattenToString()),
+ ACTION_ACCESSIBILITY_SHORTCUT_SETTINGS);
+ mFragmentScenario.moveToState(Lifecycle.State.CREATED);
+
+ mFragmentScenario.onFragment(fragment -> {
+ Preference preference = fragment.findPreference(
+ mContext.getString(R.string.accessibility_shortcut_description_pref));
+ assertThat(preference.isVisible()).isTrue();
+ });
+ }
+
+ @Test
public void fragmentCreated_settingsObserversAreRegistered() {
ShadowContentResolver contentResolver = shadowOf(mContext.getContentResolver());
for (Uri uri : SHORTCUT_SETTINGS) {
@@ -654,9 +705,14 @@
private FragmentScenario<EditShortcutsPreferenceFragment> createFragScenario(
boolean isInSuw, String target) {
+ return createFragScenario(isInSuw, List.of(target), null);
+ }
+ private FragmentScenario<EditShortcutsPreferenceFragment> createFragScenario(
+ boolean isInSuw, List<String> targets, @Nullable String intentAction) {
Bundle args = new Bundle();
args.putStringArray(
- EditShortcutsPreferenceFragment.ARG_KEY_SHORTCUT_TARGETS, new String[]{target});
+ EditShortcutsPreferenceFragment.ARG_KEY_SHORTCUT_TARGETS,
+ targets.toArray(new String[0]));
FragmentScenario<EditShortcutsPreferenceFragment> scenario =
FragmentScenario.launch(
EditShortcutsPreferenceFragment.class, args,
@@ -664,7 +720,11 @@
scenario.onFragment(fragment -> {
Intent intent = fragment.requireActivity().getIntent();
intent.putExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT_TITLE, SCREEN_TITLE);
- fragment.requireActivity().setIntent(createSuwIntent(intent, isInSuw));
+ setIntentInSuw(intent, isInSuw);
+ if (intentAction != null) {
+ intent.setAction(intentAction);
+ }
+ fragment.requireActivity().setIntent(intent);
// Since the fragment is attached before we have a chance
// to modify the activity's intent; initialize controllers again
fragment.initializePreferenceControllerArguments();
@@ -672,11 +732,7 @@
return scenario;
}
- private Intent createSuwIntent(Intent intent, boolean isInSuw) {
-
- if (intent == null) {
- intent = new Intent();
- }
+ private Intent setIntentInSuw(Intent intent, boolean isInSuw) {
intent.putExtra(EXTRA_IS_SETUP_FLOW, isInSuw);
intent.putExtra(EXTRA_IS_FIRST_RUN, isInSuw);
intent.putExtra(EXTRA_IS_PRE_DEFERRED_SETUP, isInSuw);
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/BluetoothDashboardScreenTest.kt b/tests/robotests/src/com/android/settings/connecteddevice/BluetoothDashboardScreenTest.kt
new file mode 100644
index 0000000..16db841
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/connecteddevice/BluetoothDashboardScreenTest.kt
@@ -0,0 +1,56 @@
+/*
+ * 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.connecteddevice
+
+import android.content.Intent
+import android.provider.Settings.Global
+import androidx.preference.PreferenceFragmentCompat
+import androidx.test.core.app.ActivityScenario
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.settings.Settings.BluetoothDashboardActivity
+import com.android.settings.flags.Flags
+import com.android.settingslib.preference.CatalystScreenTestCase
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class BluetoothDashboardScreenTest : CatalystScreenTestCase() {
+ override val preferenceScreenCreator = BluetoothDashboardScreen()
+
+ override val flagName: String
+ get() = Flags.FLAG_CATALYST_BLUETOOTH_SWITCHBAR_SCREEN
+
+ @Test
+ fun key() {
+ assertThat(preferenceScreenCreator.key).isEqualTo(BluetoothDashboardScreen.KEY)
+ }
+
+ override fun launchFragment(
+ fragmentClass: Class<PreferenceFragmentCompat>,
+ action: (PreferenceFragmentCompat) -> Unit,
+ ) {
+ Global.putInt(appContext.contentResolver, Global.DEVICE_PROVISIONED, 1)
+ val intent = Intent(appContext, BluetoothDashboardActivity::class.java)
+ ActivityScenario.launch<BluetoothDashboardActivity>(intent).use {
+ it.onActivity { activity ->
+ val fragment = activity.supportFragmentManager.fragments[0]
+ assertThat(fragment.javaClass).isEqualTo(fragmentClass)
+ action(fragment as PreferenceFragmentCompat)
+ }
+ }
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java b/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java
index 1bc00a1..f3848b3 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java
@@ -17,10 +17,10 @@
package com.android.settings.fuelgauge;
import static com.android.settings.SettingsActivity.EXTRA_SHOW_FRAGMENT_ARGUMENTS;
-import static com.android.settings.fuelgauge.BatteryOptimizeHistoricalLogEntry.Action;
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.nullable;
@@ -49,13 +49,13 @@
import com.android.settings.R;
import com.android.settings.SettingsActivity;
+import com.android.settings.fuelgauge.BatteryOptimizeHistoricalLogEntry.Action;
import com.android.settings.fuelgauge.batteryusage.BatteryDiffEntry;
import com.android.settings.fuelgauge.batteryusage.BatteryEntry;
import com.android.settings.fuelgauge.batteryusage.ConvertUtils;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.shadow.ShadowEntityHeaderController;
import com.android.settings.widget.EntityHeaderController;
-import com.android.settingslib.PrimarySwitchPreference;
import com.android.settingslib.applications.AppUtils;
import com.android.settingslib.applications.ApplicationsState;
import com.android.settingslib.applications.instantapps.InstantAppDataProvider;
@@ -87,12 +87,12 @@
})
public class AdvancedPowerUsageDetailTest {
- @Rule
- public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+ @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
private static final String APP_LABEL = "app label";
private static final String SUMMARY = "summary";
- private static final String[] PACKAGE_NAME = {"com.android.app"};
+ private static final String PACKAGE_NAME = "com.android.app";
+ private static final String INITIATING_PACKAGE_NAME = "com.android.vending";
private static final String USAGE_PERCENT = "16%";
private static final int ICON_ID = 123;
private static final int UID = 1;
@@ -100,39 +100,43 @@
private static final long FOREGROUND_SERVICE_TIME_MS = 123;
private static final long BACKGROUND_TIME_MS = 100;
private static final long SCREEN_ON_TIME_MS = 321;
- private static final String KEY_ALLOW_BACKGROUND_USAGE = "allow_background_usage";
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private FragmentActivity mActivity;
@Mock private EntityHeaderController mEntityHeaderController;
- @Mock private LayoutPreference mHeaderPreference;
@Mock private ApplicationsState mState;
@Mock private ApplicationsState.AppEntry mAppEntry;
@Mock private BatteryEntry mBatteryEntry;
@Mock private PackageManager mPackageManager;
@Mock private InstallSourceInfo mInstallSourceInfo;
+ @Mock private LayoutPreference mLayoutPreference;
@Mock private AppOpsManager mAppOpsManager;
@Mock private LoaderManager mLoaderManager;
- @Mock private BatteryOptimizeUtils mBatteryOptimizeUtils;
+ private int mTestMode;
private Context mContext;
- private PrimarySwitchPreference mAllowBackgroundUsagePreference;
private AdvancedPowerUsageDetail mFragment;
private SettingsActivity mTestActivity;
private FakeFeatureFactory mFeatureFactory;
private MetricsFeatureProvider mMetricsFeatureProvider;
private BatteryDiffEntry mBatteryDiffEntry;
private Bundle mBundle;
+ private BatteryOptimizeUtils mBatteryOptimizeUtils;
@Before
- public void setUp() {
+ public void setUp() throws Exception {
mContext = spy(ApplicationProvider.getApplicationContext());
- when(mContext.getPackageName()).thenReturn("foo");
+ when(mContext.getPackageName()).thenReturn(PACKAGE_NAME);
+ when(mContext.getPackageManager()).thenReturn(mPackageManager);
+ when(mPackageManager.getInstallSourceInfo(anyString())).thenReturn(mInstallSourceInfo);
mFeatureFactory = FakeFeatureFactory.setupForTest();
mMetricsFeatureProvider = mFeatureFactory.metricsFeatureProvider;
+ prepareTestBatteryOptimizationUtils();
mFragment = spy(new AdvancedPowerUsageDetail());
+ mFragment.mBatteryOptimizeUtils = mBatteryOptimizeUtils;
+ doReturn(mLayoutPreference).when(mFragment).findPreference(any());
mBundle = spy(new Bundle());
doReturn(mContext).when(mFragment).getContext();
doReturn(mActivity).when(mFragment).getActivity();
@@ -195,7 +199,6 @@
when(mBatteryDiffEntry.getAppLabel()).thenReturn(APP_LABEL);
when(mBatteryDiffEntry.getAppIconId()).thenReturn(ICON_ID);
- mFragment.mHeaderPreference = mHeaderPreference;
mFragment.mState = mState;
mFragment.mBatteryOptimizeUtils = mBatteryOptimizeUtils;
mFragment.mLogStringBuilder = new StringBuilder();
@@ -219,10 +222,6 @@
.startActivityAsUser(captor.capture(), nullable(UserHandle.class));
doAnswer(callable).when(mActivity).startActivity(captor.capture());
doAnswer(callable).when(mContext).startActivity(captor.capture());
-
- mAllowBackgroundUsagePreference = new PrimarySwitchPreference(mContext);
- mAllowBackgroundUsagePreference.setKey(KEY_ALLOW_BACKGROUND_USAGE);
- mFragment.mAllowBackgroundUsagePreference = mAllowBackgroundUsagePreference;
}
@After
@@ -320,17 +319,15 @@
.isEqualTo(SCREEN_ON_TIME_MS);
assertThat(mBundle.getString(AdvancedPowerUsageDetail.EXTRA_POWER_USAGE_PERCENT))
.isEqualTo(USAGE_PERCENT);
- assertThat(mBundle.getString(AdvancedPowerUsageDetail.EXTRA_SLOT_TIME))
- .isEqualTo(null);
+ assertThat(mBundle.getString(AdvancedPowerUsageDetail.EXTRA_SLOT_TIME)).isNull();
}
-
@Test
public void startBatteryDetailPage_noBatteryUsage_hasBasicData() {
final ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
AdvancedPowerUsageDetail.startBatteryDetailPage(
- mActivity, mFragment, PACKAGE_NAME[0], UserHandle.OWNER);
+ mActivity, mFragment, PACKAGE_NAME, UserHandle.OWNER);
verify(mActivity).startActivity(captor.capture());
@@ -338,7 +335,7 @@
captor.getValue()
.getBundleExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS)
.getString(AdvancedPowerUsageDetail.EXTRA_PACKAGE_NAME))
- .isEqualTo(PACKAGE_NAME[0]);
+ .isEqualTo(PACKAGE_NAME);
assertThat(
captor.getValue()
@@ -351,62 +348,21 @@
public void startBatteryDetailPage_batteryEntryNotExisted_extractUidFromPackageName()
throws PackageManager.NameNotFoundException {
mBundle.clear();
- doReturn(UID).when(mPackageManager).getPackageUid(PACKAGE_NAME[0], 0 /* no flag */);
+ doReturn(UID).when(mPackageManager).getPackageUid(PACKAGE_NAME, 0 /* no flag */);
AdvancedPowerUsageDetail.startBatteryDetailPage(
- mActivity, mFragment, PACKAGE_NAME[0], UserHandle.OWNER);
+ mActivity, mFragment, PACKAGE_NAME, UserHandle.OWNER);
assertThat(mBundle.getInt(AdvancedPowerUsageDetail.EXTRA_UID)).isEqualTo(UID);
}
@Test
- public void initFooter_isValidPackageName_hasCorrectString() {
- when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(true);
+ public void onPause_optimizationModeIsChanged_logPreference() throws Exception {
+ mFragment.mOptimizationMode = BatteryOptimizeUtils.MODE_RESTRICTED;
+ when(mBatteryOptimizeUtils.getPackageName()).thenReturn(PACKAGE_NAME);
+ when(mInstallSourceInfo.getInitiatingPackageName()).thenReturn(INITIATING_PACKAGE_NAME);
- mFragment.initFooter();
-
- assertThat(mAllowBackgroundUsagePreference.getSummary().toString())
- .isEqualTo("This app requires optimized battery usage.");
- }
-
- @Test
- public void initFooter_isSystemOrDefaultApp_hasCorrectString() {
- when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
- when(mBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true);
-
- mFragment.initFooter();
-
- assertThat(mAllowBackgroundUsagePreference.getSummary().toString())
- .isEqualTo("This app requires unrestricted battery usage.");
- }
-
- @Test
- public void initFooter_hasCorrectString() {
- when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
- when(mBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(false);
-
- mFragment.initFooter();
-
- assertThat(mAllowBackgroundUsagePreference.getSummary().toString())
- .isEqualTo("Enable for real-time updates, disable to save battery");
- }
-
- @Test
- public void onPause_optimizationModeChanged_logPreference()
- throws PackageManager.NameNotFoundException, InterruptedException {
- final String packageName = "testPackageName";
- final int restrictedMode = BatteryOptimizeUtils.MODE_RESTRICTED;
- final int optimizedMode = BatteryOptimizeUtils.MODE_OPTIMIZED;
- mFragment.mOptimizationMode = restrictedMode;
- when(mBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(restrictedMode);
- when(mBatteryOptimizeUtils.getPackageName()).thenReturn(packageName);
- when(mContext.getPackageManager()).thenReturn(mPackageManager);
- when(mPackageManager.getInstallSourceInfo(anyString())).thenReturn(mInstallSourceInfo);
- when(mInstallSourceInfo.getInitiatingPackageName()).thenReturn("com.android.vending");
-
- mFragment.onPreferenceChange(mAllowBackgroundUsagePreference, true);
- verify(mBatteryOptimizeUtils).setAppUsageState(optimizedMode, Action.APPLY);
- when(mBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(optimizedMode);
+ mBatteryOptimizeUtils.setAppUsageState(BatteryOptimizeUtils.MODE_OPTIMIZED, Action.APPLY);
mFragment.onPause();
TimeUnit.SECONDS.sleep(1);
@@ -415,27 +371,18 @@
SettingsEnums.LEAVE_APP_BATTERY_USAGE,
SettingsEnums.ACTION_APP_BATTERY_USAGE_ALLOW_BACKGROUND,
SettingsEnums.FUELGAUGE_POWER_USAGE_DETAIL,
- packageName,
+ PACKAGE_NAME,
/* consumed battery */ 0);
}
@Test
- public void onPause_optimizationModeIsNotChanged_notInvokeLogging()
- throws PackageManager.NameNotFoundException, InterruptedException {
- final int restrictedMode = BatteryOptimizeUtils.MODE_RESTRICTED;
- final int optimizedMode = BatteryOptimizeUtils.MODE_OPTIMIZED;
- mFragment.mOptimizationMode = restrictedMode;
- when(mBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(restrictedMode);
- when(mContext.getPackageManager()).thenReturn(mPackageManager);
- when(mPackageManager.getInstallSourceInfo(anyString())).thenReturn(mInstallSourceInfo);
- when(mInstallSourceInfo.getInitiatingPackageName()).thenReturn("com.android.vending");
+ public void onPause_optimizationModeIsNotChanged_notInvokeLogging() throws Exception {
+ mFragment.mOptimizationMode = BatteryOptimizeUtils.MODE_RESTRICTED;
+ when(mBatteryOptimizeUtils.getPackageName()).thenReturn(PACKAGE_NAME);
+ when(mInstallSourceInfo.getInitiatingPackageName()).thenReturn(INITIATING_PACKAGE_NAME);
- mFragment.onPreferenceChange(mAllowBackgroundUsagePreference, true);
- verify(mBatteryOptimizeUtils).setAppUsageState(optimizedMode, Action.APPLY);
- when(mBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(optimizedMode);
- mFragment.onPreferenceChange(mAllowBackgroundUsagePreference, false);
- verify(mBatteryOptimizeUtils).setAppUsageState(restrictedMode, Action.APPLY);
- when(mBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(restrictedMode);
+ mBatteryOptimizeUtils.setAppUsageState(BatteryOptimizeUtils.MODE_OPTIMIZED, Action.APPLY);
+ mBatteryOptimizeUtils.setAppUsageState(BatteryOptimizeUtils.MODE_RESTRICTED, Action.APPLY);
mFragment.onPause();
TimeUnit.SECONDS.sleep(1);
@@ -446,4 +393,16 @@
public void shouldSkipForInitialSUW_returnTrue() {
assertThat(mFragment.shouldSkipForInitialSUW()).isTrue();
}
+
+ private void prepareTestBatteryOptimizationUtils() {
+ mBatteryOptimizeUtils = spy(new BatteryOptimizeUtils(mContext, UID, PACKAGE_NAME));
+ Answer<Void> setTestMode =
+ invocation -> {
+ mTestMode = invocation.getArgument(0);
+ return null;
+ };
+ doAnswer(setTestMode).when(mBatteryOptimizeUtils).setAppUsageState(anyInt(), any());
+ Answer<Integer> getTestMode = invocation -> mTestMode;
+ doAnswer(getTestMode).when(mBatteryOptimizeUtils).getAppOptimizationMode();
+ }
}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/AllowBackgroundPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/AllowBackgroundPreferenceControllerTest.java
deleted file mode 100644
index 261a315..0000000
--- a/tests/robotests/src/com/android/settings/fuelgauge/AllowBackgroundPreferenceControllerTest.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;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-import android.content.pm.PackageManager;
-
-import com.android.settingslib.widget.MainSwitchPreference;
-
-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;
-
-@RunWith(RobolectricTestRunner.class)
-public class AllowBackgroundPreferenceControllerTest {
- private static final int UID = 12345;
- private static final String PACKAGE_NAME = "com.android.app";
-
- private AllowBackgroundPreferenceController mController;
- private MainSwitchPreference mMainSwitchPreference;
- private BatteryOptimizeUtils mBatteryOptimizeUtils;
-
- @Mock private PackageManager mMockPackageManager;
-
- @Before
- public void setUp() throws Exception {
- MockitoAnnotations.initMocks(this);
-
- Context context = spy(RuntimeEnvironment.application);
- BatteryUtils.getInstance(context).reset();
- doReturn(UID)
- .when(mMockPackageManager)
- .getPackageUid(PACKAGE_NAME, PackageManager.GET_META_DATA);
-
- mController = new AllowBackgroundPreferenceController(context, UID, PACKAGE_NAME);
- mMainSwitchPreference = new MainSwitchPreference(RuntimeEnvironment.application);
- mBatteryOptimizeUtils = spy(new BatteryOptimizeUtils(context, UID, PACKAGE_NAME));
- mController.mBatteryOptimizeUtils = mBatteryOptimizeUtils;
- }
-
- @Test
- public void testUpdateState_isValidPackage_prefEnabled() {
- when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
- when(mBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(false);
-
- mController.updateState(mMainSwitchPreference);
-
- assertThat(mBatteryOptimizeUtils.isOptimizeModeMutable()).isTrue();
- assertThat(mMainSwitchPreference.isEnabled()).isTrue();
- }
-
- @Test
- public void testUpdateState_invalidPackage_prefDisabled() {
- when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(true);
- when(mBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(false);
-
- mController.updateState(mMainSwitchPreference);
-
- assertThat(mBatteryOptimizeUtils.isOptimizeModeMutable()).isFalse();
- assertThat(mMainSwitchPreference.isEnabled()).isFalse();
- }
-
- @Test
- public void testUpdateState_isSystemOrDefaultAppAndRestrictedStates_prefChecked() {
- when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
- when(mBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true);
- when(mBatteryOptimizeUtils.getAppOptimizationMode())
- .thenReturn(BatteryOptimizeUtils.MODE_RESTRICTED);
-
- mController.updateState(mMainSwitchPreference);
-
- assertThat(mMainSwitchPreference.isEnabled()).isFalse();
- assertThat(mMainSwitchPreference.isChecked()).isFalse();
- }
-
- @Test
- public void testUpdateState_isSystemOrDefaultApp_prefUnchecked() {
- when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
- when(mBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true);
- when(mBatteryOptimizeUtils.getAppOptimizationMode())
- .thenReturn(BatteryOptimizeUtils.MODE_OPTIMIZED);
-
- mController.updateState(mMainSwitchPreference);
-
- assertThat(mMainSwitchPreference.isEnabled()).isFalse();
- assertThat(mMainSwitchPreference.isChecked()).isTrue();
- }
-
- @Test
- public void testUpdateState_isRestrictedStates_prefChecked() {
- when(mBatteryOptimizeUtils.isOptimizeModeMutable()).thenReturn(true);
- when(mBatteryOptimizeUtils.getAppOptimizationMode())
- .thenReturn(BatteryOptimizeUtils.MODE_RESTRICTED);
-
- mController.updateState(mMainSwitchPreference);
-
- assertThat(mMainSwitchPreference.isEnabled()).isTrue();
- assertThat(mMainSwitchPreference.isChecked()).isFalse();
- }
-
- @Test
- public void testUpdateState_prefUnchecked() {
- when(mBatteryOptimizeUtils.isOptimizeModeMutable()).thenReturn(true);
- when(mBatteryOptimizeUtils.getAppOptimizationMode())
- .thenReturn(BatteryOptimizeUtils.MODE_OPTIMIZED);
-
- mController.updateState(mMainSwitchPreference);
-
- assertThat(mMainSwitchPreference.isEnabled()).isTrue();
- assertThat(mMainSwitchPreference.isChecked()).isTrue();
- }
-
- @Test
- public void testHandlePreferenceTreeClick_samePrefKey_verifyAction() {
- mMainSwitchPreference.setKey(
- AllowBackgroundPreferenceController.KEY_ALLOW_BACKGROUND_USAGE);
- mController.handlePreferenceTreeClick(mMainSwitchPreference);
-
- assertThat(mController.handlePreferenceTreeClick(mMainSwitchPreference)).isTrue();
- }
-
- @Test
- public void testHandlePreferenceTreeClick_incorrectPrefKey_noAction() {
- assertThat(mController.handlePreferenceTreeClick(mMainSwitchPreference)).isFalse();
- }
-}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BackgroundUsageAllowabilityPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BackgroundUsageAllowabilityPreferenceControllerTest.java
new file mode 100644
index 0000000..190446e
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BackgroundUsageAllowabilityPreferenceControllerTest.java
@@ -0,0 +1,202 @@
+/*
+ * 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.fuelgauge;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.doAnswer;
+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 android.content.Context;
+
+import androidx.test.core.app.ApplicationProvider;
+
+import com.android.settings.R;
+import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.fuelgauge.BatteryOptimizeHistoricalLogEntry.Action;
+import com.android.settingslib.PrimarySwitchPreference;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.stubbing.Answer;
+import org.robolectric.RobolectricTestRunner;
+
+@RunWith(RobolectricTestRunner.class)
+public class BackgroundUsageAllowabilityPreferenceControllerTest {
+ private static final int UID = 12345;
+ private static final String PACKAGE_NAME = "com.android.app";
+
+ private int mTestMode;
+ private Context mContext;
+ private BackgroundUsageAllowabilityPreferenceController mBackgroundUsageController;
+ private BatteryOptimizeUtils mBatteryOptimizeUtils;
+
+ @Mock DashboardFragment mDashboardFragment;
+ @Mock PrimarySwitchPreference mBackgroundUsageAllowabilityPreference;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+
+ mContext = spy(ApplicationProvider.getApplicationContext());
+ prepareTestBatteryOptimizationUtils();
+ mBackgroundUsageController =
+ spy(
+ new BackgroundUsageAllowabilityPreferenceController(
+ mContext,
+ mDashboardFragment,
+ /* preferenceKey= */ "test",
+ mBatteryOptimizeUtils));
+ mBackgroundUsageController.mBackgroundUsageAllowabilityPreference =
+ mBackgroundUsageAllowabilityPreference;
+ }
+
+ @Test
+ public void initPreferences_immutableOptimized_setExpectedContent() {
+ doReturn(false).when(mBatteryOptimizeUtils).isOptimizeModeMutable();
+ doReturn(true).when(mBatteryOptimizeUtils).isDisabledForOptimizeModeOnly();
+
+ mBackgroundUsageController.initPreferences();
+
+ verify(mBackgroundUsageAllowabilityPreference).setEnabled(false);
+ verify(mBackgroundUsageAllowabilityPreference).setSwitchEnabled(false);
+ verify(mBackgroundUsageAllowabilityPreference)
+ .setSummary(
+ mContext.getString(
+ R.string.manager_battery_usage_footer_limited,
+ mContext.getString(R.string.manager_battery_usage_optimized_only)));
+ verify(mBackgroundUsageAllowabilityPreference, never())
+ .setOnPreferenceChangeListener(any());
+ verify(mBackgroundUsageAllowabilityPreference, never()).setOnPreferenceClickListener(any());
+ }
+
+ @Test
+ public void initPreferences_immutableUnrestricted_setExpectedContent() {
+ doReturn(false).when(mBatteryOptimizeUtils).isOptimizeModeMutable();
+ doReturn(false).when(mBatteryOptimizeUtils).isDisabledForOptimizeModeOnly();
+ doReturn(true).when(mBatteryOptimizeUtils).isSystemOrDefaultApp();
+
+ mBackgroundUsageController.initPreferences();
+
+ verify(mBackgroundUsageAllowabilityPreference).setEnabled(false);
+ verify(mBackgroundUsageAllowabilityPreference).setSwitchEnabled(false);
+ verify(mBackgroundUsageAllowabilityPreference)
+ .setSummary(
+ mContext.getString(
+ R.string.manager_battery_usage_footer_limited,
+ mContext.getString(
+ R.string.manager_battery_usage_unrestricted_only)));
+ verify(mBackgroundUsageAllowabilityPreference, never())
+ .setOnPreferenceChangeListener(any());
+ verify(mBackgroundUsageAllowabilityPreference, never()).setOnPreferenceClickListener(any());
+ }
+
+ @Test
+ public void initPreferences_mutableMode_setExpectedContent() {
+ doReturn(true).when(mBatteryOptimizeUtils).isOptimizeModeMutable();
+ doReturn(false).when(mBatteryOptimizeUtils).isDisabledForOptimizeModeOnly();
+ doReturn(false).when(mBatteryOptimizeUtils).isSystemOrDefaultApp();
+
+ mBackgroundUsageController.initPreferences();
+
+ verify(mBackgroundUsageAllowabilityPreference).setEnabled(true);
+ verify(mBackgroundUsageAllowabilityPreference).setSwitchEnabled(true);
+ verify(mBackgroundUsageAllowabilityPreference)
+ .setSummary(
+ mContext.getString(
+ R.string.manager_battery_usage_allow_background_usage_summary));
+ verify(mBackgroundUsageAllowabilityPreference).setOnPreferenceChangeListener(any());
+ verify(mBackgroundUsageAllowabilityPreference).setOnPreferenceClickListener(any());
+ }
+
+ @Test
+ public void updatePreferences_setIntoUnrestrictedMode_setExpectedPrefStatus() {
+ mTestMode = BatteryOptimizeUtils.MODE_UNRESTRICTED;
+
+ mBackgroundUsageController.updatePreferences(mTestMode);
+
+ verifyPreferences(mTestMode);
+ }
+
+ @Test
+ public void updatePreferences_setIntoOptimizedMode_setExpectedPrefStatus() {
+ mTestMode = BatteryOptimizeUtils.MODE_OPTIMIZED;
+
+ mBackgroundUsageController.updatePreferences(mTestMode);
+
+ verifyPreferences(mTestMode);
+ }
+
+ @Test
+ public void updatePreferences_setIntoRestrictedMode_setExpectedPrefStatus() {
+ mTestMode = BatteryOptimizeUtils.MODE_RESTRICTED;
+
+ mBackgroundUsageController.updatePreferences(mTestMode);
+
+ verifyPreferences(mTestMode);
+ }
+
+ @Test
+ public void handleBatteryOptimizeModeUpdated_modeChange_setExpectedPrefStatus() {
+ mTestMode = BatteryOptimizeUtils.MODE_RESTRICTED;
+
+ mBackgroundUsageController.handleBatteryOptimizeModeUpdated(
+ BatteryOptimizeUtils.MODE_OPTIMIZED);
+
+ verify(mBatteryOptimizeUtils)
+ .setAppUsageState(BatteryOptimizeUtils.MODE_OPTIMIZED, Action.APPLY);
+ assertThat(mTestMode).isEqualTo(BatteryOptimizeUtils.MODE_OPTIMIZED);
+ verifyPreferences(mTestMode);
+ }
+
+ @Test
+ public void handleBatteryOptimizeModeUpdated_modeNotChange_setExpectedPrefStatus() {
+ mTestMode = BatteryOptimizeUtils.MODE_RESTRICTED;
+
+ mBackgroundUsageController.handleBatteryOptimizeModeUpdated(
+ BatteryOptimizeUtils.MODE_RESTRICTED);
+
+ verify(mBatteryOptimizeUtils, never()).setAppUsageState(anyInt(), any());
+ assertThat(mTestMode).isEqualTo(BatteryOptimizeUtils.MODE_RESTRICTED);
+ verify(mBackgroundUsageController, never()).updatePreferences(mTestMode);
+ }
+
+ private void prepareTestBatteryOptimizationUtils() {
+ mBatteryOptimizeUtils = spy(new BatteryOptimizeUtils(mContext, UID, PACKAGE_NAME));
+ Answer<Void> setTestMode =
+ invocation -> {
+ mTestMode = invocation.getArgument(0);
+ return null;
+ };
+ doAnswer(setTestMode).when(mBatteryOptimizeUtils).setAppUsageState(anyInt(), any());
+ Answer<Integer> getTestMode = invocation -> mTestMode;
+ doAnswer(getTestMode).when(mBatteryOptimizeUtils).getAppOptimizationMode();
+ }
+
+ private void verifyPreferences(int mode) {
+ boolean isAllowBackground = mode != BatteryOptimizeUtils.MODE_RESTRICTED;
+ verify(mBackgroundUsageAllowabilityPreference).setChecked(isAllowBackground);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryOptimizationModePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryOptimizationModePreferenceControllerTest.java
new file mode 100644
index 0000000..2ddc7eb
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryOptimizationModePreferenceControllerTest.java
@@ -0,0 +1,179 @@
+/*
+ * 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.fuelgauge;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.doAnswer;
+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 android.content.Context;
+
+import androidx.test.core.app.ApplicationProvider;
+
+import com.android.settingslib.widget.MainSwitchPreference;
+import com.android.settingslib.widget.SelectorWithWidgetPreference;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.stubbing.Answer;
+import org.robolectric.RobolectricTestRunner;
+
+@RunWith(RobolectricTestRunner.class)
+public class BatteryOptimizationModePreferenceControllerTest {
+ private static final int UID = 12345;
+ private static final String PACKAGE_NAME = "com.android.app";
+
+ private int mTestMode;
+ private Context mContext;
+ private BatteryOptimizationModePreferenceController mBackgroundUsageController;
+ private BatteryOptimizeUtils mBatteryOptimizeUtils;
+
+ @Mock MainSwitchPreference mBackgroundUsageAllowabilityPreference;
+ @Mock SelectorWithWidgetPreference mOptimizedPreference;
+ @Mock SelectorWithWidgetPreference mUnrestrictedPreference;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+
+ mContext = spy(ApplicationProvider.getApplicationContext());
+ prepareTestBatteryOptimizationUtils();
+ mBackgroundUsageController =
+ spy(
+ new BatteryOptimizationModePreferenceController(
+ mContext, "test", mBatteryOptimizeUtils));
+ mBackgroundUsageController.mBackgroundUsageAllowabilityPreference =
+ mBackgroundUsageAllowabilityPreference;
+ mBackgroundUsageController.mOptimizedPreference = mOptimizedPreference;
+ mBackgroundUsageController.mUnrestrictedPreference = mUnrestrictedPreference;
+ }
+
+ @Test
+ public void initPreferences_mutableMode_setEnabled() {
+ doReturn(true).when(mBatteryOptimizeUtils).isOptimizeModeMutable();
+
+ mBackgroundUsageController.initPreferences();
+
+ verify(mBackgroundUsageAllowabilityPreference).setEnabled(true);
+ verify(mOptimizedPreference).setEnabled(true);
+ verify(mUnrestrictedPreference).setEnabled(true);
+ verify(mBackgroundUsageAllowabilityPreference, never()).setOnPreferenceClickListener(any());
+ verify(mBackgroundUsageAllowabilityPreference).setOnPreferenceChangeListener(any());
+ verify(mOptimizedPreference).setOnPreferenceClickListener(any());
+ verify(mUnrestrictedPreference).setOnPreferenceClickListener(any());
+ }
+
+ @Test
+ public void initPreferences_immutableMode_setDisabledAndSkipSetListeners() {
+ doReturn(false).when(mBatteryOptimizeUtils).isOptimizeModeMutable();
+
+ mBackgroundUsageController.initPreferences();
+
+ verify(mBackgroundUsageAllowabilityPreference).setEnabled(false);
+ verify(mOptimizedPreference).setEnabled(false);
+ verify(mUnrestrictedPreference).setEnabled(false);
+ verify(mBackgroundUsageAllowabilityPreference, never()).setOnPreferenceClickListener(any());
+ verify(mBackgroundUsageAllowabilityPreference, never())
+ .setOnPreferenceChangeListener(any());
+ verify(mOptimizedPreference, never()).setOnPreferenceClickListener(any());
+ verify(mUnrestrictedPreference, never()).setOnPreferenceClickListener(any());
+ }
+
+ @Test
+ public void updatePreferences_setIntoUnrestrictedMode_setExpectedPrefStatus() {
+ mTestMode = BatteryOptimizeUtils.MODE_UNRESTRICTED;
+
+ mBackgroundUsageController.updatePreferences(mTestMode);
+
+ verifyPreferences(mTestMode);
+ }
+
+ @Test
+ public void updatePreferences_setIntoOptimizedMode_setExpectedPrefStatus() {
+ mTestMode = BatteryOptimizeUtils.MODE_OPTIMIZED;
+
+ mBackgroundUsageController.updatePreferences(mTestMode);
+
+ verifyPreferences(mTestMode);
+ }
+
+ @Test
+ public void updatePreferences_setIntoRestrictedMode_setExpectedPrefStatus() {
+ mTestMode = BatteryOptimizeUtils.MODE_RESTRICTED;
+
+ mBackgroundUsageController.updatePreferences(mTestMode);
+
+ verifyPreferences(mTestMode);
+ }
+
+ @Test
+ public void handleBatteryOptimizeModeUpdated_modeChange_setExpectedPrefStatus() {
+ mTestMode = BatteryOptimizeUtils.MODE_RESTRICTED;
+
+ mBackgroundUsageController.handleBatteryOptimizeModeUpdated(
+ BatteryOptimizeUtils.MODE_OPTIMIZED);
+
+ verify(mBatteryOptimizeUtils)
+ .setAppUsageState(
+ BatteryOptimizeUtils.MODE_OPTIMIZED,
+ BatteryOptimizeHistoricalLogEntry.Action.APPLY);
+ assertThat(mTestMode).isEqualTo(BatteryOptimizeUtils.MODE_OPTIMIZED);
+ verifyPreferences(mBatteryOptimizeUtils.getAppOptimizationMode());
+ }
+
+ @Test
+ public void handleBatteryOptimizeModeUpdated_modeNotChange_setExpectedPrefStatus() {
+ mTestMode = BatteryOptimizeUtils.MODE_RESTRICTED;
+
+ mBackgroundUsageController.handleBatteryOptimizeModeUpdated(
+ BatteryOptimizeUtils.MODE_RESTRICTED);
+
+ verify(mBatteryOptimizeUtils, never()).setAppUsageState(anyInt(), any());
+ assertThat(mTestMode).isEqualTo(BatteryOptimizeUtils.MODE_RESTRICTED);
+ verify(mBackgroundUsageController, never()).updatePreferences(anyInt());
+ }
+
+ private void prepareTestBatteryOptimizationUtils() {
+ mBatteryOptimizeUtils = spy(new BatteryOptimizeUtils(mContext, UID, PACKAGE_NAME));
+ Answer<Void> setTestMode =
+ invocation -> {
+ mTestMode = invocation.getArgument(0);
+ return null;
+ };
+ doAnswer(setTestMode).when(mBatteryOptimizeUtils).setAppUsageState(anyInt(), any());
+ Answer<Integer> getTestMode = invocation -> mTestMode;
+ doAnswer(getTestMode).when(mBatteryOptimizeUtils).getAppOptimizationMode();
+ }
+
+ private void verifyPreferences(int mode) {
+ boolean isAllowBackground = mode != BatteryOptimizeUtils.MODE_RESTRICTED;
+ verify(mBackgroundUsageAllowabilityPreference).setChecked(isAllowBackground);
+ verify(mOptimizedPreference).setEnabled(isAllowBackground);
+ verify(mUnrestrictedPreference).setEnabled(isAllowBackground);
+ verify(mOptimizedPreference).setChecked(mode == BatteryOptimizeUtils.MODE_OPTIMIZED);
+ verify(mUnrestrictedPreference).setChecked(mode == BatteryOptimizeUtils.MODE_UNRESTRICTED);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/OptimizedPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/OptimizedPreferenceControllerTest.java
deleted file mode 100644
index 6656471..0000000
--- a/tests/robotests/src/com/android/settings/fuelgauge/OptimizedPreferenceControllerTest.java
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright (C) 2021 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;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-import android.content.pm.PackageManager;
-
-import com.android.settingslib.widget.SelectorWithWidgetPreference;
-
-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;
-
-@RunWith(RobolectricTestRunner.class)
-public class OptimizedPreferenceControllerTest {
- private static final int UID = 12345;
- private static final String PACKAGE_NAME = "com.android.app";
-
- private OptimizedPreferenceController mController;
- private SelectorWithWidgetPreference mPreference;
- private BatteryOptimizeUtils mBatteryOptimizeUtils;
-
- @Mock PackageManager mMockPackageManager;
-
- @Before
- public void setUp() throws Exception {
- MockitoAnnotations.initMocks(this);
-
- Context context = spy(RuntimeEnvironment.application);
- BatteryUtils.getInstance(context).reset();
- doReturn(UID)
- .when(mMockPackageManager)
- .getPackageUid(PACKAGE_NAME, PackageManager.GET_META_DATA);
-
- mController = new OptimizedPreferenceController(context, UID, PACKAGE_NAME);
- mPreference = new SelectorWithWidgetPreference(RuntimeEnvironment.application);
- mBatteryOptimizeUtils = spy(new BatteryOptimizeUtils(context, UID, PACKAGE_NAME));
- mController.mBatteryOptimizeUtils = mBatteryOptimizeUtils;
- }
-
- @Test
- public void testUpdateState_invalidPackage_prefEnabled() {
- when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(true);
-
- mController.updateState(mPreference);
-
- assertThat(mPreference.isEnabled()).isFalse();
- assertThat(mPreference.isChecked()).isTrue();
- }
-
- @Test
- public void testUpdateState_isSystemOrDefaultAppAndOptimizeStates_prefChecked() {
- when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
- when(mBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true);
- when(mBatteryOptimizeUtils.getAppOptimizationMode())
- .thenReturn(BatteryOptimizeUtils.MODE_OPTIMIZED);
-
- mController.updateState(mPreference);
-
- assertThat(mPreference.isChecked()).isTrue();
- }
-
- @Test
- public void testUpdateState_isSystemOrDefaultApp_prefUnchecked() {
- when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
- when(mBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true);
-
- mController.updateState(mPreference);
-
- assertThat(mPreference.isChecked()).isFalse();
- assertThat(mPreference.isEnabled()).isFalse();
- }
-
- @Test
- public void testUpdateState_isOptimizedStates_prefChecked() {
- when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
- when(mBatteryOptimizeUtils.getAppOptimizationMode())
- .thenReturn(BatteryOptimizeUtils.MODE_OPTIMIZED);
-
- mController.updateState(mPreference);
-
- assertThat(mPreference.isChecked()).isTrue();
- }
-
- @Test
- public void testUpdateState_prefUnchecked() {
- when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
-
- mController.updateState(mPreference);
-
- assertThat(mPreference.isChecked()).isFalse();
- }
-
- @Test
- public void testHandlePreferenceTreeClick_samePrefKey_verifyAction() {
- mPreference.setKey(mController.KEY_OPTIMIZED_PREF);
- mController.handlePreferenceTreeClick(mPreference);
-
- assertThat(mController.handlePreferenceTreeClick(mPreference)).isTrue();
- }
-
- @Test
- public void testHandlePreferenceTreeClick_incorrectPrefKey_noAction() {
- assertThat(mController.handlePreferenceTreeClick(mPreference)).isFalse();
- }
-}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/PowerBackgroundUsageDetailTest.java b/tests/robotests/src/com/android/settings/fuelgauge/PowerBackgroundUsageDetailTest.java
index 9061117..9f98d78 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/PowerBackgroundUsageDetailTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/PowerBackgroundUsageDetailTest.java
@@ -17,10 +17,10 @@
package com.android.settings.fuelgauge;
import static com.android.settings.SettingsActivity.EXTRA_SHOW_FRAGMENT_ARGUMENTS;
-import static com.android.settings.fuelgauge.BatteryOptimizeHistoricalLogEntry.Action;
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.nullable;
@@ -42,16 +42,17 @@
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.UserHandle;
-import android.widget.CompoundButton;
import androidx.fragment.app.FragmentActivity;
import androidx.loader.app.LoaderManager;
import androidx.test.core.app.ApplicationProvider;
+import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.fuelgauge.batteryusage.BatteryEntry;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.shadow.ShadowEntityHeaderController;
+import com.android.settings.testutils.shadow.ShadowHelpUtils;
import com.android.settings.widget.EntityHeaderController;
import com.android.settingslib.applications.AppUtils;
import com.android.settingslib.applications.ApplicationsState;
@@ -59,8 +60,6 @@
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
import com.android.settingslib.widget.FooterPreference;
import com.android.settingslib.widget.LayoutPreference;
-import com.android.settingslib.widget.MainSwitchPreference;
-import com.android.settingslib.widget.SelectorWithWidgetPreference;
import org.junit.After;
import org.junit.Before;
@@ -83,36 +82,33 @@
@Config(
shadows = {
ShadowEntityHeaderController.class,
+ ShadowHelpUtils.class,
com.android.settings.testutils.shadow.ShadowFragment.class,
})
public class PowerBackgroundUsageDetailTest {
- @Rule
- public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+ @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
private static final String APP_LABEL = "app label";
private static final String SUMMARY = "summary";
private static final int ICON_ID = 123;
private static final int UID = 1;
- private static final String KEY_PREF_UNRESTRICTED = "unrestricted_preference";
- private static final String KEY_PREF_OPTIMIZED = "optimized_preference";
- private static final String KEY_ALLOW_BACKGROUND_USAGE = "allow_background_usage";
+ private static final String PACKAGE_NAME = "com.android.app";
+ private static final String KEY_PREF_HEADER = "header_view";
+ private static final String KEY_FOOTER_PREFERENCE = "app_usage_footer_preference";
+ private static final String INITIATING_PACKAGE_NAME = "com.android.vending";
+ private int mTestMode;
private Context mContext;
private PowerBackgroundUsageDetail mFragment;
- private FooterPreference mFooterPreference;
- private MainSwitchPreference mMainSwitchPreference;
private MetricsFeatureProvider mMetricsFeatureProvider;
- private SelectorWithWidgetPreference mOptimizePreference;
- private SelectorWithWidgetPreference mUnrestrictedPreference;
private SettingsActivity mTestActivity;
+ private BatteryOptimizeUtils mBatteryOptimizeUtils;
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private FragmentActivity mActivity;
@Mock private EntityHeaderController mEntityHeaderController;
- @Mock private BatteryOptimizeUtils mBatteryOptimizeUtils;
- @Mock private LayoutPreference mHeaderPreference;
@Mock private ApplicationsState mState;
@Mock private Bundle mBundle;
@Mock private LoaderManager mLoaderManager;
@@ -120,21 +116,26 @@
@Mock private BatteryEntry mBatteryEntry;
@Mock private PackageManager mPackageManager;
@Mock private AppOpsManager mAppOpsManager;
- @Mock private CompoundButton mMockSwitch;
@Mock private InstallSourceInfo mInstallSourceInfo;
+ @Mock private LayoutPreference mLayoutPreference;
+ @Mock private FooterPreference mFooterPreference;
@Before
public void setUp() throws Exception {
mContext = spy(ApplicationProvider.getApplicationContext());
- when(mContext.getPackageName()).thenReturn("foo");
+ when(mContext.getPackageName()).thenReturn(PACKAGE_NAME);
when(mContext.getPackageManager()).thenReturn(mPackageManager);
when(mPackageManager.getInstallSourceInfo(anyString())).thenReturn(mInstallSourceInfo);
final FakeFeatureFactory fakeFeatureFactory = FakeFeatureFactory.setupForTest();
mMetricsFeatureProvider = fakeFeatureFactory.metricsFeatureProvider;
+ prepareTestBatteryOptimizationUtils();
mFragment = spy(new PowerBackgroundUsageDetail());
+ mFragment.mBatteryOptimizeUtils = mBatteryOptimizeUtils;
mFragment.mLogStringBuilder = new StringBuilder();
+ doReturn(mLayoutPreference).when(mFragment).findPreference(KEY_PREF_HEADER);
+ doReturn(mFooterPreference).when(mFragment).findPreference(KEY_FOOTER_PREFERENCE);
doReturn(mContext).when(mFragment).getContext();
doReturn(mActivity).when(mFragment).getActivity();
doReturn(SUMMARY).when(mFragment).getString(anyInt());
@@ -169,9 +170,7 @@
when(mBatteryEntry.getLabel()).thenReturn(APP_LABEL);
mBatteryEntry.mIconId = ICON_ID;
- mFragment.mHeaderPreference = mHeaderPreference;
mFragment.mState = mState;
- mFragment.mBatteryOptimizeUtils = mBatteryOptimizeUtils;
mAppEntry.info = mock(ApplicationInfo.class);
mTestActivity = spy(new SettingsActivity());
@@ -191,23 +190,12 @@
.when(mActivity)
.startActivityAsUser(captor.capture(), nullable(UserHandle.class));
doAnswer(callable).when(mActivity).startActivity(captor.capture());
-
- mFooterPreference = spy(new FooterPreference(mContext));
- mMainSwitchPreference = spy(new MainSwitchPreference(mContext));
- mMainSwitchPreference.setKey(KEY_ALLOW_BACKGROUND_USAGE);
- mOptimizePreference = spy(new SelectorWithWidgetPreference(mContext));
- mOptimizePreference.setKey(KEY_PREF_OPTIMIZED);
- mUnrestrictedPreference = spy(new SelectorWithWidgetPreference(mContext));
- mUnrestrictedPreference.setKey(KEY_PREF_UNRESTRICTED);
- mFragment.mFooterPreference = mFooterPreference;
- mFragment.mMainSwitchPreference = mMainSwitchPreference;
- mFragment.mOptimizePreference = mOptimizePreference;
- mFragment.mUnrestrictedPreference = mUnrestrictedPreference;
}
@After
public void reset() {
ShadowEntityHeaderController.reset();
+ ShadowHelpUtils.reset();
}
@Test
@@ -258,91 +246,64 @@
}
@Test
- public void initFooter_hasCorrectString() {
- when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
- when(mBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(false);
-
+ public void initFooter_setExpectedFooterContent() {
mFragment.initFooter();
- assertThat(mFooterPreference.getTitle().toString())
- .isEqualTo("Changing how an app uses your battery can affect its performance.");
+ verify(mFooterPreference)
+ .setTitle(mContext.getString(R.string.manager_battery_usage_footer));
+ verify(mFooterPreference).setLearnMoreAction(any());
+ verify(mFooterPreference)
+ .setLearnMoreText(mContext.getString(R.string.manager_battery_usage_link_a11y));
}
@Test
- public void onSwitchChanged_fromUnrestrictedModeSetDisabled_becomeRestrictedMode() {
- final int restrictedMode = BatteryOptimizeUtils.MODE_RESTRICTED;
- final int optimizedMode = BatteryOptimizeUtils.MODE_OPTIMIZED;
- mFragment.mOptimizationMode = optimizedMode;
+ public void onPause_optimizationModeIsChanged_logPreference() throws Exception {
+ mFragment.mOptimizationMode = BatteryOptimizeUtils.MODE_OPTIMIZED;
+ when(mBatteryOptimizeUtils.getPackageName()).thenReturn(PACKAGE_NAME);
+ when(mInstallSourceInfo.getInitiatingPackageName()).thenReturn(INITIATING_PACKAGE_NAME);
- mFragment.onCheckedChanged(mMockSwitch, /* isChecked= */ false);
-
- verify(mOptimizePreference).setEnabled(false);
- verify(mUnrestrictedPreference).setEnabled(false);
- verify(mFragment).onRadioButtonClicked(null);
- verify(mMainSwitchPreference).setChecked(false);
- assertThat(mFragment.getSelectedPreference()).isEqualTo(restrictedMode);
- verify(mBatteryOptimizeUtils).setAppUsageState(restrictedMode, Action.APPLY);
- }
-
- @Test
- public void onSwitchChanged_fromRestrictedModeSetEnabled_becomeOptimizedMode() {
- final int restrictedMode = BatteryOptimizeUtils.MODE_RESTRICTED;
- final int optimizedMode = BatteryOptimizeUtils.MODE_OPTIMIZED;
- mFragment.mOptimizationMode = restrictedMode;
-
- mFragment.onCheckedChanged(mMockSwitch, /* isChecked= */ true);
-
- verify(mOptimizePreference).setEnabled(true);
- verify(mUnrestrictedPreference).setEnabled(true);
- verify(mFragment).onRadioButtonClicked(mOptimizePreference);
- verify(mMainSwitchPreference).setChecked(true);
- verify(mOptimizePreference).setChecked(true);
- assertThat(mFragment.getSelectedPreference()).isEqualTo(optimizedMode);
- verify(mBatteryOptimizeUtils).setAppUsageState(optimizedMode, Action.APPLY);
- }
-
- @Test
- public void onPause_optimizationModeChanged_logPreference() throws Exception {
- final String packageName = "testPackageName";
- final int restrictedMode = BatteryOptimizeUtils.MODE_RESTRICTED;
- final int optimizedMode = BatteryOptimizeUtils.MODE_OPTIMIZED;
- mFragment.mOptimizationMode = restrictedMode;
- when(mBatteryOptimizeUtils.getPackageName()).thenReturn(packageName);
- when(mInstallSourceInfo.getInitiatingPackageName()).thenReturn("com.android.vending");
-
- mFragment.onCheckedChanged(mMockSwitch, /* isChecked= */ true);
- verify(mBatteryOptimizeUtils).setAppUsageState(optimizedMode, Action.APPLY);
- when(mBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(optimizedMode);
+ mTestMode = BatteryOptimizeUtils.MODE_UNRESTRICTED;
+ assertThat(mBatteryOptimizeUtils.getAppOptimizationMode())
+ .isEqualTo(BatteryOptimizeUtils.MODE_UNRESTRICTED);
mFragment.onPause();
TimeUnit.SECONDS.sleep(1);
verify(mMetricsFeatureProvider)
.action(
SettingsEnums.LEAVE_POWER_USAGE_MANAGE_BACKGROUND,
- SettingsEnums.ACTION_APP_BATTERY_USAGE_OPTIMIZED,
+ SettingsEnums.ACTION_APP_BATTERY_USAGE_UNRESTRICTED,
SettingsEnums.FUELGAUGE_POWER_USAGE_MANAGE_BACKGROUND,
- packageName,
+ PACKAGE_NAME,
/* consumed battery */ 0);
}
@Test
public void onPause_optimizationModeIsNotChanged_notInvokeLogging() throws Exception {
- final String packageName = "testPackageName";
- final int restrictedMode = BatteryOptimizeUtils.MODE_RESTRICTED;
- final int optimizedMode = BatteryOptimizeUtils.MODE_OPTIMIZED;
- mFragment.mOptimizationMode = restrictedMode;
- when(mBatteryOptimizeUtils.getPackageName()).thenReturn(packageName);
- when(mInstallSourceInfo.getInitiatingPackageName()).thenReturn("com.android.vending");
+ mFragment.mOptimizationMode = BatteryOptimizeUtils.MODE_OPTIMIZED;
+ when(mBatteryOptimizeUtils.getPackageName()).thenReturn(PACKAGE_NAME);
+ when(mInstallSourceInfo.getInitiatingPackageName()).thenReturn(INITIATING_PACKAGE_NAME);
- mFragment.onCheckedChanged(mMockSwitch, /* isChecked= */ true);
- verify(mBatteryOptimizeUtils).setAppUsageState(optimizedMode, Action.APPLY);
- when(mBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(optimizedMode);
- mFragment.onCheckedChanged(mMockSwitch, /* isChecked= */ false);
- verify(mBatteryOptimizeUtils).setAppUsageState(restrictedMode, Action.APPLY);
- when(mBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(restrictedMode);
+ mTestMode = BatteryOptimizeUtils.MODE_UNRESTRICTED;
+ assertThat(mBatteryOptimizeUtils.getAppOptimizationMode())
+ .isEqualTo(BatteryOptimizeUtils.MODE_UNRESTRICTED);
+ mTestMode = BatteryOptimizeUtils.MODE_OPTIMIZED;
+ assertThat(mBatteryOptimizeUtils.getAppOptimizationMode())
+ .isEqualTo(BatteryOptimizeUtils.MODE_OPTIMIZED);
mFragment.onPause();
TimeUnit.SECONDS.sleep(1);
verifyNoInteractions(mMetricsFeatureProvider);
}
+
+ private void prepareTestBatteryOptimizationUtils() {
+ mBatteryOptimizeUtils = spy(new BatteryOptimizeUtils(mContext, UID, PACKAGE_NAME));
+ Answer<Void> setTestMode =
+ invocation -> {
+ mTestMode = invocation.getArgument(0);
+ return null;
+ };
+ doAnswer(setTestMode).when(mBatteryOptimizeUtils).setAppUsageState(anyInt(), any());
+ Answer<Integer> getTestMode = invocation -> mTestMode;
+ doAnswer(getTestMode).when(mBatteryOptimizeUtils).getAppOptimizationMode();
+ }
}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/UnrestrictedPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/UnrestrictedPreferenceControllerTest.java
deleted file mode 100644
index 0c6f7da..0000000
--- a/tests/robotests/src/com/android/settings/fuelgauge/UnrestrictedPreferenceControllerTest.java
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Copyright (C) 2021 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;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-import android.content.pm.PackageManager;
-
-import com.android.settingslib.widget.SelectorWithWidgetPreference;
-
-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;
-
-@RunWith(RobolectricTestRunner.class)
-public class UnrestrictedPreferenceControllerTest {
- private static final int UID = 12345;
- private static final String PACKAGE_NAME = "com.android.app";
-
- private UnrestrictedPreferenceController mController;
- private SelectorWithWidgetPreference mPreference;
- private BatteryOptimizeUtils mBatteryOptimizeUtils;
-
- @Mock PackageManager mMockPackageManager;
-
- @Before
- public void setUp() throws Exception {
- MockitoAnnotations.initMocks(this);
-
- Context context = spy(RuntimeEnvironment.application);
- BatteryUtils.getInstance(context).reset();
- doReturn(UID)
- .when(mMockPackageManager)
- .getPackageUid(PACKAGE_NAME, PackageManager.GET_META_DATA);
-
- mController = new UnrestrictedPreferenceController(context, UID, PACKAGE_NAME);
- mPreference = new SelectorWithWidgetPreference(RuntimeEnvironment.application);
- mBatteryOptimizeUtils = spy(new BatteryOptimizeUtils(context, UID, PACKAGE_NAME));
- mController.mBatteryOptimizeUtils = mBatteryOptimizeUtils;
- }
-
- @Test
- public void testUpdateState_isValidPackage_prefEnabled() {
- when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
- when(mBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(false);
-
- mController.updateState(mPreference);
-
- assertThat(mBatteryOptimizeUtils.isOptimizeModeMutable()).isTrue();
- assertThat(mPreference.isEnabled()).isTrue();
- }
-
- @Test
- public void testUpdateState_invalidPackage_prefDisabled() {
- when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(true);
- when(mBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(false);
-
- mController.updateState(mPreference);
-
- assertThat(mBatteryOptimizeUtils.isOptimizeModeMutable()).isFalse();
- assertThat(mPreference.isEnabled()).isFalse();
- }
-
- @Test
- public void testUpdateState_isSystemOrDefaultAppAndUnrestrictedStates_prefChecked() {
- when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
- when(mBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true);
- when(mBatteryOptimizeUtils.getAppOptimizationMode())
- .thenReturn(BatteryOptimizeUtils.MODE_UNRESTRICTED);
-
- mController.updateState(mPreference);
-
- assertThat(mPreference.isChecked()).isTrue();
- }
-
- @Test
- public void testUpdateState_isSystemOrDefaultApp_prefUnchecked() {
- when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
- when(mBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true);
- when(mBatteryOptimizeUtils.getAppOptimizationMode())
- .thenReturn(BatteryOptimizeUtils.MODE_OPTIMIZED);
-
- mController.updateState(mPreference);
-
- assertThat(mPreference.isEnabled()).isFalse();
- assertThat(mPreference.isChecked()).isFalse();
- }
-
- @Test
- public void testUpdateState_isUnrestrictedStates_prefChecked() {
- when(mBatteryOptimizeUtils.isOptimizeModeMutable()).thenReturn(true);
- when(mBatteryOptimizeUtils.getAppOptimizationMode())
- .thenReturn(BatteryOptimizeUtils.MODE_UNRESTRICTED);
-
- mController.updateState(mPreference);
-
- assertThat(mPreference.isEnabled()).isTrue();
- assertThat(mPreference.isChecked()).isTrue();
- }
-
- @Test
- public void testUpdateState_prefUnchecked() {
- when(mBatteryOptimizeUtils.isOptimizeModeMutable()).thenReturn(true);
- when(mBatteryOptimizeUtils.getAppOptimizationMode())
- .thenReturn(BatteryOptimizeUtils.MODE_OPTIMIZED);
-
- mController.updateState(mPreference);
-
- assertThat(mPreference.isEnabled()).isTrue();
- assertThat(mPreference.isChecked()).isFalse();
- }
-
- @Test
- public void testHandlePreferenceTreeClick_samePrefKey_verifyAction() {
- mPreference.setKey(mController.KEY_UNRESTRICTED_PREF);
- mController.handlePreferenceTreeClick(mPreference);
-
- assertThat(mController.handlePreferenceTreeClick(mPreference)).isTrue();
- }
-
- @Test
- public void testHandlePreferenceTreeClick_incorrectPrefKey_noAction() {
- assertThat(mController.handlePreferenceTreeClick(mPreference)).isFalse();
- }
-}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/PowerUsageSummaryScreenTest.kt b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/PowerUsageSummaryScreenTest.kt
new file mode 100644
index 0000000..80a6b2e
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/PowerUsageSummaryScreenTest.kt
@@ -0,0 +1,101 @@
+/*
+ * 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.fuelgauge.batteryusage
+
+import android.content.ContextWrapper
+import android.content.res.Resources
+import android.platform.test.annotations.DisableFlags
+import android.platform.test.annotations.EnableFlags
+import androidx.fragment.app.testing.FragmentScenario
+import androidx.preference.PreferenceFragmentCompat
+import com.android.settings.R
+import com.android.settings.flags.Flags
+import com.android.settings.testutils.shadow.ShadowUtils
+import com.android.settingslib.preference.CatalystScreenTestCase
+import com.google.common.truth.Truth.assertThat
+import org.junit.After
+import org.junit.Test
+import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.kotlin.doReturn
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.stub
+import org.robolectric.annotation.Config
+
+@Config(shadows = [ShadowUtils::class])
+class PowerUsageSummaryScreenTest : CatalystScreenTestCase() {
+
+ override val preferenceScreenCreator = PowerUsageSummaryScreen()
+
+ override val flagName: String
+ get() = Flags.FLAG_CATALYST_POWER_USAGE_SUMMARY_SCREEN
+
+ private val mockResources = mock<Resources>()
+
+ private val context =
+ object : ContextWrapper(appContext) {
+ override fun getResources(): Resources = mockResources
+ }
+
+ @After
+ fun tearDown() {
+ ShadowUtils.reset()
+ }
+
+ @Test
+ fun key() {
+ assertThat(preferenceScreenCreator.key).isEqualTo(PowerUsageSummaryScreen.KEY)
+ }
+
+ @Test
+ fun isAvailable_configTrue_shouldReturnTrue() {
+ mockResources.stub { on { getBoolean(anyInt()) } doReturn true }
+
+ assertThat(preferenceScreenCreator.isAvailable(context)).isTrue()
+ }
+
+ @Test
+ fun isAvailable_configFalse_shouldReturnFalse() {
+ mockResources.stub { on { getBoolean(anyInt()) } doReturn false }
+
+ assertThat(preferenceScreenCreator.isAvailable(context)).isFalse()
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_HOMEPAGE_REVAMP)
+ fun getIcon_whenHomePageRevampFlagOn() {
+ assertThat(preferenceScreenCreator.getIcon(context))
+ .isEqualTo(R.drawable.ic_settings_battery_filled)
+ }
+
+ @Test
+ @DisableFlags(Flags.FLAG_HOMEPAGE_REVAMP)
+ fun getIcon_whenHomePageRevampFlagOff() {
+ assertThat(preferenceScreenCreator.getIcon(context))
+ .isEqualTo(R.drawable.ic_settings_battery_white)
+ }
+
+ override fun migration() {
+ ShadowUtils.setIsBatteryPresent(false)
+
+ super.migration()
+ }
+
+ override fun launchFragmentScenario(fragmentClass: Class<PreferenceFragmentCompat>) =
+ FragmentScenario.launch(
+ fragmentClass,
+ themeResId = R.style.Theme_CollapsingToolbar_Settings,
+ )
+}
diff --git a/tests/robotests/src/com/android/settings/location/LocationScreenTest.kt b/tests/robotests/src/com/android/settings/location/LocationScreenTest.kt
new file mode 100644
index 0000000..1d1696d
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/location/LocationScreenTest.kt
@@ -0,0 +1,73 @@
+/*
+ * 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.location
+
+import android.content.Context
+import android.content.ContextWrapper
+import android.location.LocationManager
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.settings.R
+import com.android.settings.flags.Flags
+import com.android.settingslib.preference.CatalystScreenTestCase
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.kotlin.doReturn
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.stub
+
+@RunWith(AndroidJUnit4::class)
+class LocationScreenTest : CatalystScreenTestCase() {
+ override val preferenceScreenCreator = LocationScreen()
+
+ override val flagName: String
+ get() = Flags.FLAG_CATALYST_LOCATION_SETTINGS
+
+ private val mockLocationManager = mock<LocationManager>()
+
+ private val context =
+ object : ContextWrapper(appContext) {
+ override fun getSystemService(name: String): Any =
+ when (name) {
+ Context.LOCATION_SERVICE -> mockLocationManager
+ else -> super.getSystemService(name)
+ }
+ }
+
+ @Test
+ fun key() {
+ assertThat(preferenceScreenCreator.key).isEqualTo(LocationScreen.KEY)
+ }
+
+ @Test
+ fun getSummary_enableLocation_shouldReturnLoading() {
+ mockLocationManager.stub { on { isLocationEnabled } doReturn true }
+
+ assertThat(preferenceScreenCreator.getSummary(context)).isEqualTo(
+ context.getString(R.string.location_settings_loading_app_permission_stats))
+ }
+
+ @Test
+ fun getSummary_disableLocation_shouldReturnLocationOff() {
+ mockLocationManager.stub { on { isLocationEnabled } doReturn false }
+
+ assertThat(preferenceScreenCreator.getSummary(context)).isEqualTo(
+ context.getString(R.string.location_settings_summary_location_off))
+ }
+
+ override fun migration() {
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/network/MobileNetworkListScreenTest.kt b/tests/robotests/src/com/android/settings/network/MobileNetworkListScreenTest.kt
new file mode 100644
index 0000000..1d7a1d9
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/network/MobileNetworkListScreenTest.kt
@@ -0,0 +1,36 @@
+/*
+ * 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
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.settings.flags.Flags
+import com.android.settingslib.preference.CatalystScreenTestCase
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class MobileNetworkListScreenTest : CatalystScreenTestCase() {
+ override val preferenceScreenCreator = MobileNetworkListScreen()
+
+ override val flagName: String
+ get() = Flags.FLAG_CATALYST_MOBILE_NETWORK_LIST
+
+ @Test
+ fun key() {
+ assertThat(preferenceScreenCreator.key).isEqualTo(MobileNetworkListScreen.KEY)
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/network/NetworkProviderSettingsTest.java b/tests/robotests/src/com/android/settings/network/NetworkProviderSettingsTest.java
index 400f73f..df399d7 100644
--- a/tests/robotests/src/com/android/settings/network/NetworkProviderSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/network/NetworkProviderSettingsTest.java
@@ -70,6 +70,7 @@
import com.android.settings.AirplaneModeEnabler;
import com.android.settings.R;
+import com.android.settings.dashboard.DashboardFeatureProvider;
import com.android.settings.datausage.DataUsagePreference;
import com.android.settings.testutils.shadow.ShadowDataUsageUtils;
import com.android.settings.testutils.shadow.ShadowFragment;
@@ -98,6 +99,7 @@
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import org.robolectric.shadows.ShadowToast;
+import org.robolectric.util.ReflectionHelpers;
import java.util.List;
@@ -190,6 +192,9 @@
.when(mFirstWifiEntryPreferenceCategory).getKey();
mNetworkProviderSettings.mFirstWifiEntryPreferenceCategory =
mFirstWifiEntryPreferenceCategory;
+
+ ReflectionHelpers.setField(mNetworkProviderSettings, "mDashboardFeatureProvider",
+ mock(DashboardFeatureProvider.class));
}
@Test
diff --git a/tests/robotests/src/com/android/settings/network/apn/ApnEditorTest.java b/tests/robotests/src/com/android/settings/network/apn/ApnEditorTest.java
deleted file mode 100644
index d8895d5..0000000
--- a/tests/robotests/src/com/android/settings/network/apn/ApnEditorTest.java
+++ /dev/null
@@ -1,625 +0,0 @@
-/*
- * Copyright (C) 2018 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.apn;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.doNothing;
-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;
-
-import android.content.ContentResolver;
-import android.content.ContentValues;
-import android.content.Context;
-import android.content.Intent;
-import android.content.res.Resources;
-import android.database.Cursor;
-import android.net.Uri;
-import android.os.PersistableBundle;
-import android.os.UserManager;
-import android.telephony.CarrierConfigManager;
-import android.view.KeyEvent;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.View;
-
-import androidx.fragment.app.FragmentActivity;
-import androidx.preference.EditTextPreference;
-import androidx.preference.ListPreference;
-import androidx.preference.MultiSelectListPreference;
-import androidx.preference.SwitchPreference;
-
-import com.android.settings.R;
-import com.android.settings.network.ProxySubscriptionManager;
-import com.android.settings.network.apn.ApnEditor.ApnData;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Captor;
-import org.mockito.Mock;
-import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
-
-@RunWith(RobolectricTestRunner.class)
-@Config(shadows = {
- com.android.settings.testutils.shadow.ShadowFragment.class,
-})
-public class ApnEditorTest {
-
- private static final Object[] APN_DATA = {
- 0, /* ID */
- "apn_name" /* apn name */,
- "apn.com" /* apn */,
- "" /* proxy */,
- "" /* port */,
- "" /* username */,
- "" /* server */,
- "" /* password */,
- "" /* MMSC */,
- "123" /* MCC */,
- "456" /* MNC */,
- "123456" /* operator numeric */,
- "" /* MMS proxy */,
- "" /* MMS port */,
- 0 /* Authentication type */,
- "default,supl,ia" /* APN type */,
- "IP" /* APN protocol */,
- 1 /* APN enable/disable */,
- 0 /* Bearer */,
- 0 /* Bearer BITMASK*/,
- "IPV6" /* APN roaming protocol */,
- "None" /* MVNO type */,
- "", /* MVNO value */
- };
-
- private static final int CURSOR_INTEGER_INDEX = 0;
- private static final int CURSOR_STRING_INDEX = 1;
-
- private static final Uri APN_URI = Uri.parse("Apn://row/1");
-
- @Mock
- private Cursor mCursor;
-
- @Mock
- private FragmentActivity mActivity;
- @Mock
- private UserManager mUserManager;
- @Mock
- private ProxySubscriptionManager mProxySubscriptionMgr;
- @Mock
- private CarrierConfigManager mCarrierConfigManager;
- @Captor
- private ArgumentCaptor<Uri> mUriCaptor;
-
- private ApnEditor mApnEditorUT;
- private Context mContext;
- private Resources mResources;
- private PersistableBundle mBundle = new PersistableBundle();
-
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
- mContext = spy(RuntimeEnvironment.application);
-
- mResources = mContext.getResources();
- mApnEditorUT = spy(new ApnEditor());
-
- doReturn(mActivity).when(mApnEditorUT).getActivity();
- doReturn(mResources).when(mApnEditorUT).getResources();
- doNothing().when(mApnEditorUT).finish();
- doNothing().when(mApnEditorUT).showError();
- doReturn(mContext).when(mApnEditorUT).getContext();
- doReturn(mContext.getTheme()).when(mActivity).getTheme();
- doReturn(mContext.getContentResolver()).when(mActivity).getContentResolver();
-
- doReturn(mUserManager).when(mContext).getSystemService(UserManager.class);
- doReturn(true).when(mUserManager).isAdminUser();
- doReturn(false).when(mUserManager)
- .hasUserRestriction(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS);
- doReturn(mCarrierConfigManager).when(mContext)
- .getSystemService(Context.CARRIER_CONFIG_SERVICE);
- doReturn(mBundle).when(mCarrierConfigManager).getConfigForSubId(anyInt());
-
- setMockPreference(mContext);
- mApnEditorUT.mApnData = new FakeApnData(APN_DATA);
- mApnEditorUT.sNotSet = "Not Set";
- }
-
- @Test
- public void testApnEditor_doesNotUseManagedQuery() {
- mApnEditorUT.getApnDataFromUri(Mockito.mock(Uri.class));
-
- verify(mActivity, never()).managedQuery(
- any(Uri.class),
- any(String[].class),
- any(String.class),
- any(String.class));
-
- verify(mActivity, never()).managedQuery(
- any(Uri.class),
- any(String[].class),
- any(String.class),
- any(String[].class),
- any(String.class));
- }
-
- @Test
- public void getApnDataFromUri_emptyCursor_returnsNull() {
- var mockContentResolver = mock(ContentResolver.class);
- var mockCursor = mock(Cursor.class);
- doReturn(mockContentResolver).when(mActivity).getContentResolver();
- when(mockContentResolver.query(any(), any(), any(), any(), any())).thenReturn(mockCursor);
- when(mockCursor.moveToFirst()).thenReturn(false);
-
- var apnData = mApnEditorUT.getApnDataFromUri(mock(Uri.class));
-
- assertThat(apnData).isNull();
- }
-
- @Test
- public void testSetStringValue_valueChanged_shouldSetValue() {
- // GIVEN an APN value which is different than the APN value in database
- final String apnKey = "apn";
- final String apnValue = "testing.com";
- final ContentValues cv = new ContentValues();
-
- // WHEN try to check and set the apn value
- final boolean isDiff = mApnEditorUT.setStringValueAndCheckIfDiff(
- cv, apnKey, apnValue, false /* assumeDiff */, ApnEditor.APN_INDEX);
-
- // THEN the APN value is different than the one in database, and it has been stored in the
- // given ContentValues
- assertThat(isDiff).isTrue();
- assertThat(apnValue).isEqualTo(cv.getAsString(apnKey));
- }
-
- @Test
- public void testSetStringValue_valueNotChanged_shouldNotSetValue() {
- // GIVEN an APN value which is same as the APN value in database
- final String apnKey = "apn";
- final String apnValue = (String) APN_DATA[ApnEditor.APN_INDEX];
- final ContentValues cv = new ContentValues();
-
- // WHEN try to check and set the apn value
- final boolean isDiff = mApnEditorUT.setStringValueAndCheckIfDiff(
- cv, apnKey, apnValue, false /* assumeDiff */, ApnEditor.APN_INDEX);
-
- // THEN the APN value is same as the one in database, and the new APN value is not stored
- // in the given ContentValues
- assertThat(isDiff).isFalse();
- assertThat(cv.get(apnKey)).isNull();
- }
-
- @Test
- public void testSetStringValue_nullValue_shouldNotSetValue_shouldNotSetValue() {
- // GIVEN a null APN value
- final String apnKey = "apn";
- final String apnValue = null;
- final ContentValues cv = new ContentValues();
-
- // WHEN try to check and set the apn value
- final boolean isDiff = mApnEditorUT.setStringValueAndCheckIfDiff(
- cv, apnKey, apnValue, false /* assumeDiff */, ApnEditor.APN_INDEX);
-
- // THEN the APN value is different than the one in database, but the null value is not
- // stored in the given ContentValues
- assertThat(isDiff).isTrue();
- assertThat(cv.get(apnKey)).isNull();
- }
-
- @Test
- public void testSetIntValue_valueChanged_shouldSetValue() {
- // GIVEN a value indicated whether the apn is enabled, and it's different than the value in
- // the database
- final String apnEnabledKey = "apn_enabled";
- final int apnEnabledValue = 0;
- final ContentValues cv = new ContentValues();
-
- // WHEN try to check and set the apn enabled
- final boolean isDiff = mApnEditorUT.setIntValueAndCheckIfDiff(
- cv,
- apnEnabledKey,
- apnEnabledValue,
- false /* assumeDiff */,
- ApnEditor.CARRIER_ENABLED_INDEX);
-
- // THEN the apn enabled field is different than the one in database, and it has been stored
- // in the given ContentValues
- assertThat(isDiff).isTrue();
- assertThat(cv.getAsInteger(apnEnabledKey)).isEqualTo(apnEnabledValue);
- }
-
- @Test
- public void testSetIntValue_valueNotChanged_shouldNotSetValue() {
- // GIVEN a value indicated whether the apn is enabled, and it's same as the one in the
- // database
- final String apnEnabledKey = "apn_enabled";
- final int apnEnabledValue = (int) APN_DATA[ApnEditor.CARRIER_ENABLED_INDEX];
- final ContentValues cv = new ContentValues();
-
- // WHEN try to check and set the apn enabled
- final boolean isDiff = mApnEditorUT.setIntValueAndCheckIfDiff(
- cv,
- apnEnabledKey,
- apnEnabledValue,
- false /* assumeDiff */,
- ApnEditor.CARRIER_ENABLED_INDEX);
-
- // THEN the apn enabled field is same as the one in the database, and the filed is not
- // stored in the given ContentValues
- assertThat(isDiff).isFalse();
- assertThat(cv.get(apnEnabledKey)).isNull();
- }
-
- @Test
- public void testValidateApnData_validData_shouldReturnNull() {
- // GIVEN a valid apn data
- mApnEditorUT.fillUI(true /* firstTime */);
-
- // WHEN validate the apn data
- final String errMsg = mApnEditorUT.validateApnData();
-
- // THEN the error message should be null
- assertThat(errMsg).isNull();
- }
-
- @Test
- public void testValidateApn_apnNameNotSet_shouldReturnErrorMessage() {
- // GIVEN a apn data without the apn name
- mApnEditorUT.mApnData.mData[ApnEditor.NAME_INDEX] = "";
- mApnEditorUT.fillUI(true /* firstTime */);
-
- // THEN validate the apn data
- final String errMsg = mApnEditorUT.validateApnData();
-
- // THEN the error message indicated the apn name not set is returned
- assertThat(errMsg).isEqualTo(mResources.getString(R.string.error_name_empty));
- }
-
- @Test
- public void testValidateApnData_apnNotSet_shouldReturnErrorMessage() {
- // GIVEN a apn data without the apn
- mApnEditorUT.mApnData.mData[ApnEditor.APN_INDEX] = "";
- mApnEditorUT.fillUI(true /* firstTime */);
-
- // THEN validate the apn data
- final String errMsg = mApnEditorUT.validateApnData();
-
- // THEN the error message indicated the apn not set is returned
- assertThat(errMsg).isEqualTo(mResources.getString(R.string.error_apn_empty));
- }
-
- @Test
- public void testValidateApnData_mccInvalid_shouldReturnErrorMessage() {
- // The length of the mcc should be 3
- mApnEditorUT.mApnData.mData[ApnEditor.MCC_INDEX] = "1324";
- mApnEditorUT.fillUI(true /* firstTime */);
-
- // WHEN validate the apn data
- final String errMsg = mApnEditorUT.validateApnData();
-
- // THEN the error message indicated the mcc invalid is returned
- assertThat(errMsg).isEqualTo(mResources.getString(R.string.error_mcc_not3));
- }
-
- @Test
- public void testValidateApnData_mncInvalid_shouldReturnErrorMessage() {
- // GIVEN an apn data with invalid mnc
- // The length of the mnc should be 2 or 3
- mApnEditorUT.mApnData.mData[ApnEditor.MNC_INDEX] = "1324";
- mApnEditorUT.fillUI(true /* firstTime */);
-
- // WHEN validate the apn data
- final String errMsg = mApnEditorUT.validateApnData();
-
- // THEN the error message indicated the mnc invalid is returned
- assertThat(errMsg).isEqualTo(mResources.getString(R.string.error_mnc_not23));
- }
-
- @Test
- public void testSaveApnData_pressBackButtonWithValidApnData_shouldSaveApnData() {
- // GIVEN a valid apn data
- mApnEditorUT.fillUI(true /* firstTime */);
-
- // WHEN press the back button
- final KeyEvent event = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK);
- mApnEditorUT.onKey(new View(mContext), KeyEvent.KEYCODE_BACK, event);
-
- // THEN the apn data is saved and the apn editor is closed
- verify(mApnEditorUT).validateAndSaveApnData();
- verify(mApnEditorUT).finish();
- }
-
- @Test
- public void testSaveApnData_pressSaveButtonWithValidApnData_shouldSaveApnData() {
- // GIVEN a valid apn data
- mApnEditorUT.fillUI(true /* firstTime */);
-
- // WHEN press the save button
- MenuItem item = Mockito.mock(MenuItem.class);
- // Menu.FIRST + 1 indicated the SAVE option in ApnEditor
- doReturn(Menu.FIRST + 1).when(item).getItemId();
- mApnEditorUT.onOptionsItemSelected(item);
-
- // THEN the apn data is saved and the apn editor is closed
- verify(mApnEditorUT).validateAndSaveApnData();
- verify(mApnEditorUT).finish();
- }
-
- @Test
- public void testSaveApnData_apnDataInvalid_shouldNotSaveApnData() {
- // GIVEN an invalid apn data
- // The valid apn data should contains a non-empty apn name
- mApnEditorUT.mApnData.mData[ApnEditor.NAME_INDEX] = "";
- mApnEditorUT.fillUI(true /* firstTime */);
-
- // WHEN press the save button
- final MenuItem item = Mockito.mock(MenuItem.class);
- // Menu.FIRST + 1 indicated the SAVE option in ApnEditor
- doReturn(Menu.FIRST + 1).when(item).getItemId();
- mApnEditorUT.onOptionsItemSelected(item);
-
- // THEN the error dialog is shown
- verify(mApnEditorUT).validateAndSaveApnData();
- verify(mApnEditorUT).showError();
- }
-
- @Test
- public void testDeleteApnData_shouldDeleteData() {
- // GIVEN a valid apn data correspond a row in database
- final Uri apnUri = Uri.parse("content://telephony/carriers/1");
- mApnEditorUT.mApnData = new FakeApnData(APN_DATA, apnUri);
- mApnEditorUT.fillUI(true /* firstTime */);
- ContentResolver mockContentResolver = Mockito.mock(ContentResolver.class);
- doReturn(mockContentResolver).when(mActivity).getContentResolver();
-
- // WHEN press the save button
- final MenuItem item = Mockito.mock(MenuItem.class);
- // Menu.FIRST indicated the DELETE option in ApnEditor
- doReturn(Menu.FIRST).when(item).getItemId();
- mApnEditorUT.onOptionsItemSelected(item);
-
- // THEN the apn data is deleted and the apn editor is closed
- verify(mockContentResolver).delete(mUriCaptor.capture(), any(), any());
- assertThat(apnUri).isEqualTo(mUriCaptor.getValue());
- verify(mApnEditorUT).finish();
- }
-
- @Test
- public void testDeleteApnData_shouldNotPresentMenuWhenNotSupportAdding() {
- mBundle.putBoolean(CarrierConfigManager.KEY_ALLOW_ADDING_APNS_BOOL, false);
-
- MenuItem item = Mockito.mock(MenuItem.class);
- Menu menu = Mockito.mock(Menu.class);
- doReturn(item).when(menu).add(anyInt(), anyInt(), anyInt(), anyInt());
-
- mApnEditorUT.getCarrierCustomizedConfig(mContext);
- mApnEditorUT.onCreateOptionsMenu(menu, null);
-
- verify(menu, times(0)).add(anyInt(), eq(ApnEditor.MENU_DELETE), anyInt(), anyInt());
- }
-
- @Test(expected = ClassCastException.class)
- public void testApnData_invalidIntegerType_throwsInvalidTypeException() {
- // GIVEN a ApnData constructed from cursor
- initCursor();
- final ApnData data = new ApnData(APN_URI, mCursor);
-
- // WHEN get a string from an integer column
- // THEN the InvalidTypeException is threw
- data.getString(CURSOR_INTEGER_INDEX);
- }
-
- @Test(expected = ClassCastException.class)
- public void testApnData_invalidStringType_throwsInvalidTypeException() {
- // GIVEN a ApnData constructed from cursor
- initCursor();
- final ApnData data = new ApnData(APN_URI, mCursor);
-
- // WHEN get a integer from a string column
- // THEN the InvalidTypeException is threw
- data.getInteger(CURSOR_STRING_INDEX);
- }
-
- @Test
- public void testApnData_validIntegerType_returnCorrectValue() {
- // GIVEN a ApnData constructed from cursor
- initCursor();
- final ApnData data = new ApnData(APN_URI, mCursor);
-
- // WHEN get integer from an integer column
- final int val = data.getInteger(CURSOR_INTEGER_INDEX);
-
- // THEN the integer is returned correctly
- assertThat(val).isEqualTo(mCursor.getInt(CURSOR_INTEGER_INDEX));
- }
-
- @Test
- public void testApnData_validStringType_returnCorrectValue() {
- // GIVEN a ApnData constructed from cursor
- initCursor();
- final ApnData data = new ApnData(APN_URI, mCursor);
-
- // WHEN get string from a string column
- final String str = data.getString(CURSOR_STRING_INDEX);
-
- // THEN the integer is returned correctly
- assertThat(str).isEqualTo(mCursor.getString(CURSOR_STRING_INDEX));
- }
-
- @Test
- public void testApnData_nullValueColumn_returnNull() {
- // GIVEN a empty ApnData
- final ApnData data = new ApnData(3);
-
- // WHEN get string value from a null column
- final String str = data.getString(0);
-
- // THEN the null value is returned
- assertThat(str).isNull();
- }
-
- @Test
- public void formatInteger_shouldParseString() {
- assertThat(ApnEditor.formatInteger("42")).isEqualTo("42");
- assertThat(ApnEditor.formatInteger("01")).isEqualTo("01");
- assertThat(ApnEditor.formatInteger("001")).isEqualTo("001");
- }
-
- @Test
- public void formatInteger_shouldIgnoreNonIntegers() {
- assertThat(ApnEditor.formatInteger("not an int")).isEqualTo("not an int");
- }
-
- @Test
- public void onCreate_notAdminUser_shouldFinish() {
- doReturn(false).when(mUserManager).isAdminUser();
-
- mApnEditorUT.onCreate(null);
-
- verify(mApnEditorUT).finish();
- }
-
- @Test
- public void onCreate_hasUserRestriction_shouldFinish() {
- doReturn(true).when(mUserManager)
- .hasUserRestriction(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS);
-
- mApnEditorUT.onCreate(null);
-
- verify(mApnEditorUT).finish();
- }
-
- @Test
- public void onCreate_noAction_shouldFinishAndNoCrash() {
- ProxySubscriptionManager proxySubscriptionMgr = mock(ProxySubscriptionManager.class);
- mApnEditorUT.mProxySubscriptionMgr = proxySubscriptionMgr;
- doReturn(new Intent()).when(mActivity).getIntent();
- doNothing().when(mApnEditorUT).addPreferencesFromResource(anyInt());
-
- mApnEditorUT.onCreate(null);
-
- verify(mApnEditorUT).finish();
- }
-
- @Test
- public void testOnViewStateRestored_customizedValueWithoutDefault_shouldShowCustomized() {
- mApnEditorUT.mDefaultApnProtocol = "IP";
- mApnEditorUT.mApnData.mData[ApnEditor.PROTOCOL_INDEX] = null;
- mApnEditorUT.mProtocol.setEntryValues(new CharSequence[]{"IP", "IPV6", "IPV4V6"});
-
- mApnEditorUT.onViewStateRestored(null);
-
- assertThat(mApnEditorUT.mProtocol.getSummary()).isEqualTo("IPv4");
- }
-
- @Test
- public void testOnViewStateRestored_customizedValueWithDefault_shouldShowDefault() {
- mApnEditorUT.mDefaultApnProtocol = "IP";
- mApnEditorUT.mApnData.mData[ApnEditor.PROTOCOL_INDEX] = "IPV6";
- mApnEditorUT.mProtocol.setEntryValues(new CharSequence[]{"IP", "IPV6", "IPV4V6"});
-
- mApnEditorUT.onViewStateRestored(null);
-
- assertThat(mApnEditorUT.mProtocol.getSummary()).isEqualTo("IPv6");
- }
-
- @Test
- public void getUserEnteredApnType_emptyApnType_shouldReturnDefault() {
- // case 1
- // GIVEN read only APN types with DUN
- mApnEditorUT.mReadOnlyApnTypes = new String [] {"dun"};
- // GIVEN read specificApnTypeForEmptyInput with DEFAULT,DUN
- mApnEditorUT.mDefaultApnTypes = new String [] {"default", "dun"};
-
- // Input empty in TYPE
- mApnEditorUT.mApnData.mData[ApnEditor.TYPE_INDEX] = "";
- mApnEditorUT.onViewStateRestored(null);
-
- // THEN APN type should be default
- assertThat(mApnEditorUT.getUserEnteredApnType()).isEqualTo("default");
-
- // case 2
- // GIVEN read only APN types with DUN
- mApnEditorUT.mReadOnlyApnTypes = new String [] {"dun"};
- // GIVEN read specificApnTypeForEmptyInput with DEFAULT
- mApnEditorUT.mDefaultApnTypes = new String [] {"default"};
-
- // Input empty in TYPE
- mApnEditorUT.mApnData.mData[ApnEditor.TYPE_INDEX] = "";
- mApnEditorUT.onViewStateRestored(null);
-
- // THEN APN type should be default
- assertThat(mApnEditorUT.getUserEnteredApnType()).isEqualTo("default");
- }
-
- private void initCursor() {
- doReturn(2).when(mCursor).getColumnCount();
- doReturn(2).when(mCursor).getInt(CURSOR_INTEGER_INDEX);
- doReturn("str").when(mCursor).getString(CURSOR_STRING_INDEX);
- doReturn(Cursor.FIELD_TYPE_INTEGER).when(mCursor).getType(CURSOR_INTEGER_INDEX);
- doReturn(Cursor.FIELD_TYPE_STRING).when(mCursor).getType(CURSOR_STRING_INDEX);
- }
-
- private void setMockPreference(Context context) {
- mApnEditorUT.mName = new EditTextPreference(context);
- mApnEditorUT.mApn = new EditTextPreference(context);
- mApnEditorUT.mProxy = new EditTextPreference(context);
- mApnEditorUT.mPort = new EditTextPreference(context);
- mApnEditorUT.mUser = new EditTextPreference(context);
- mApnEditorUT.mServer = new EditTextPreference(context);
- mApnEditorUT.mPassword = new EditTextPreference(context);
- mApnEditorUT.mMmsc = new EditTextPreference(context);
- mApnEditorUT.mMcc = new EditTextPreference(context);
- mApnEditorUT.mMnc = new EditTextPreference(context);
- mApnEditorUT.mMmsProxy = new EditTextPreference(context);
- mApnEditorUT.mMmsPort = new EditTextPreference(context);
- mApnEditorUT.mAuthType = new ListPreference(context);
- mApnEditorUT.mApnType = new EditTextPreference(context);
- mApnEditorUT.mProtocol = new ListPreference(context);
- mApnEditorUT.mRoamingProtocol = new ListPreference(context);
- mApnEditorUT.mCarrierEnabled = new SwitchPreference(context);
- mApnEditorUT.mBearerMulti = new MultiSelectListPreference(context);
- mApnEditorUT.mMvnoType = new ListPreference(context);
- mApnEditorUT.mMvnoMatchData = new EditTextPreference(context);
- }
-
- private final class FakeApnData extends ApnData {
- FakeApnData(Object[] data) {
- super(data.length);
- System.arraycopy(data, 0, mData, 0, data.length);
- }
-
- FakeApnData(Object[] data, Uri uri) {
- this(data);
- mUri = uri;
- }
- }
-}
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowAccessibilityManager.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowAccessibilityManager.java
index fcd1e42..7de69a7 100644
--- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowAccessibilityManager.java
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowAccessibilityManager.java
@@ -24,6 +24,8 @@
import android.util.ArrayMap;
import android.view.accessibility.AccessibilityManager;
+import com.android.internal.accessibility.common.ShortcutConstants;
+
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
@@ -71,4 +73,14 @@
@NonNull List<AccessibilityShortcutInfo> installedAccessibilityShortcutList) {
mInstalledAccessibilityShortcutList = installedAccessibilityShortcutList;
}
+
+ /**
+ * Implements the hidden method
+ * {@link AccessibilityManager#getAccessibilityShortcutTargets}.
+ */
+ @Implementation
+ public List<String> getAccessibilityShortcutTargets(
+ @ShortcutConstants.UserShortcutType int shortcutType) {
+ return List.of();
+ }
}
diff --git a/tests/screenshot/src/com/android/settings/tests/screenshot/biometrics/fingerprint/Injector.kt b/tests/screenshot/src/com/android/settings/tests/screenshot/biometrics/fingerprint/Injector.kt
index e7fc3ed..a5d0461 100644
--- a/tests/screenshot/src/com/android/settings/tests/screenshot/biometrics/fingerprint/Injector.kt
+++ b/tests/screenshot/src/com/android/settings/tests/screenshot/biometrics/fingerprint/Injector.kt
@@ -44,6 +44,7 @@
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintScrollViewModel
import com.android.settings.testutils2.FakeFingerprintManagerInteractor
import com.android.systemui.biometrics.shared.model.toFingerprintSensor
+import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
@@ -73,7 +74,10 @@
var accessibilityInteractor =
object : AccessibilityInteractor {
- override val isAccessibilityEnabled: Flow<Boolean> = flowOf(true)
+ override fun isEnabledFlow(scope: CoroutineScope): Flow<Boolean> = flowOf(true)
+ override val isEnabled: Boolean
+ get() = true
+ override fun announce(clazz: Class<*>, announcement: CharSequence?) {}
}
var foldStateInteractor =
diff --git a/tests/unit/src/com/android/settings/fingerprint2/enrollment/viewmodel/FingerprintEnrollFindSensorViewModelV2Test.kt b/tests/unit/src/com/android/settings/fingerprint2/enrollment/viewmodel/FingerprintEnrollFindSensorViewModelV2Test.kt
index 04cece8..a8c5e68 100644
--- a/tests/unit/src/com/android/settings/fingerprint2/enrollment/viewmodel/FingerprintEnrollFindSensorViewModelV2Test.kt
+++ b/tests/unit/src/com/android/settings/fingerprint2/enrollment/viewmodel/FingerprintEnrollFindSensorViewModelV2Test.kt
@@ -39,6 +39,7 @@
import com.android.settings.testutils2.FakeFingerprintManagerInteractor
import com.android.systemui.biometrics.shared.model.toFingerprintSensor
import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
@@ -106,7 +107,10 @@
)
accessibilityInteractor =
object : AccessibilityInteractor {
- override val isAccessibilityEnabled: Flow<Boolean> = flowOf(false)
+ override fun isEnabledFlow(scope: CoroutineScope): Flow<Boolean> = flowOf(true)
+ override val isEnabled: Boolean
+ get() = true
+ override fun announce(clazz: Class<*>, announcement: CharSequence?) {}
}
foldStateInteractor =
object : FoldStateInteractor {