diff --git a/res/drawable/baseline_near_me.xml b/res/drawable/baseline_near_me.xml
deleted file mode 100644
index 343f97041ed..00000000000
--- a/res/drawable/baseline_near_me.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
-
-
-
diff --git a/res/layout/apps_filter_spinner.xml b/res/layout/apps_filter_spinner.xml
index 13d80786db2..1de570528be 100644
--- a/res/layout/apps_filter_spinner.xml
+++ b/res/layout/apps_filter_spinner.xml
@@ -36,7 +36,7 @@
android:layout_width="56dp"
android:layout_height="56dp"
android:layout_marginTop="12dp"
- android:layout_toRightOf="@id/filter_spinner"
+ android:layout_toEndOf="@id/filter_spinner"
android:contentDescription="@string/configure"
android:scaleType="center"
android:src="@drawable/ic_apps_filter_settings_24dp"
diff --git a/res/layout/settings_collapsing_base_layout.xml b/res/layout/settings_collapsing_base_layout.xml
deleted file mode 100644
index 97d249c00ac..00000000000
--- a/res/layout/settings_collapsing_base_layout.xml
+++ /dev/null
@@ -1,68 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 6047092f8d3..304feb82021 100755
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -446,12 +446,4 @@
2dp
1dp
2dp
-
-
- 226dp
- 270dp
- 314dp
- 174dp
- 24dp
- 24dp
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 6134100c59f..c2ba35f3d6e 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -4121,7 +4121,7 @@
Allow apps and services to scan for nearby devices at any time, even when Bluetooth is off. This can be used, for example, to improve location-based features and services.
- Manage location services
+ Location services
Location Services
@@ -6255,8 +6255,39 @@
Since full charge
Manage battery usage
+
^1 total • ^2 background for past 24 hr
+
+ ^1 total • ^2 background for ^3
+
+
+ Total less than a minute for past 24 hr
+
+ Total less than a minute for ^1
+
+
+ Background less than a minute for past 24 hr
+
+ Background less than a minute for ^1
+
+
+ ^1 total for past 24 hr
+
+ ^1 total for ^2
+
+
+ ^1 background for past 24 hr
+
+ ^1 background for ^2
+
+
+ ^1 total • background less than a minute for past 24 hr
+
+ ^1 total • background less than a minute for ^2
+
+
+ No usage for past 24 hr
Battery left estimate is based on your device usage
@@ -13187,4 +13218,13 @@
Don\u2019t allow
+
+
+ Ultra-WideBand (UWB)
+
+
+ Helps identify the relative position of nearby devices that have UWB
+
+
+ Turn off Airplane mode to use UWB.
diff --git a/res/values/styles.xml b/res/values/styles.xml
index e91ddcbccf1..b27cc5de530 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -787,7 +787,7 @@
- @*android:string/config_headlineFontFamily
-
-
-
-
-
diff --git a/res/values/styles_preference.xml b/res/values/styles_preference.xml
index c162fc46b5b..5ad553a4ee4 100644
--- a/res/values/styles_preference.xml
+++ b/res/values/styles_preference.xml
@@ -30,7 +30,6 @@
diff --git a/res/xml/app_notification_settings.xml b/res/xml/app_notification_settings.xml
index a801ae17980..edf8cb9ecc1 100644
--- a/res/xml/app_notification_settings.xml
+++ b/res/xml/app_notification_settings.xml
@@ -26,7 +26,7 @@
-
@@ -96,11 +96,11 @@
-
-
diff --git a/res/xml/channel_notification_settings.xml b/res/xml/channel_notification_settings.xml
index 95f794458a9..97dcc269220 100644
--- a/res/xml/channel_notification_settings.xml
+++ b/res/xml/channel_notification_settings.xml
@@ -116,11 +116,11 @@
android:title="@string/app_settings_link"
settings:allowDividerAbove="true"/>
-
-
diff --git a/res/xml/connected_devices_advanced.xml b/res/xml/connected_devices_advanced.xml
index 3ff7d9975f8..85e4a762429 100644
--- a/res/xml/connected_devices_advanced.xml
+++ b/res/xml/connected_devices_advanced.xml
@@ -65,6 +65,13 @@
android:icon="@drawable/ic_folder_vd_theme_24"
android:title="@string/bluetooth_show_files_received_via_bluetooth"/>
+
+
diff --git a/res/xml/conversation_notification_settings.xml b/res/xml/conversation_notification_settings.xml
index ea555c293f7..7e475be7ebe 100644
--- a/res/xml/conversation_notification_settings.xml
+++ b/res/xml/conversation_notification_settings.xml
@@ -58,7 +58,7 @@
android:summary="@string/demote_conversation_summary"
settings:allowDividerAbove="true"/>
-
diff --git a/res/xml/location_settings.xml b/res/xml/location_settings.xml
index cae128ba645..dc176d9592c 100644
--- a/res/xml/location_settings.xml
+++ b/res/xml/location_settings.xml
@@ -65,7 +65,7 @@
diff --git a/res/xml/notification_group_settings.xml b/res/xml/notification_group_settings.xml
index cbe23c655f4..e714759aed3 100644
--- a/res/xml/notification_group_settings.xml
+++ b/res/xml/notification_group_settings.xml
@@ -31,9 +31,9 @@
android:title="@string/app_settings_link"
settings:allowDividerAbove="true"/>
-
-
diff --git a/src/com/android/settings/accessibility/AccessibilityEditDialogUtils.java b/src/com/android/settings/accessibility/AccessibilityEditDialogUtils.java
index 5402a9bc9e9..26c23137729 100644
--- a/src/com/android/settings/accessibility/AccessibilityEditDialogUtils.java
+++ b/src/com/android/settings/accessibility/AccessibilityEditDialogUtils.java
@@ -26,6 +26,7 @@ import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.text.Spannable;
import android.text.SpannableString;
+import android.text.SpannableStringBuilder;
import android.text.TextUtils;
import android.text.method.LinkMovementMethod;
import android.text.style.ImageSpan;
@@ -320,8 +321,13 @@ public class AccessibilityEditDialogUtils {
}
private static CharSequence retrieveSummary(Context context, int lineHeight) {
- return AccessibilityUtil.isFloatingMenuEnabled(context)
- ? getSummaryStringWithLink(context) : getSummaryStringWithIcon(context, lineHeight);
+ final SpannableStringBuilder sb = new SpannableStringBuilder();
+ if (!AccessibilityUtil.isFloatingMenuEnabled(context)) {
+ sb.append(getSummaryStringWithIcon(context, lineHeight));
+ sb.append("\n\n");
+ }
+ sb.append(getCustomizeAccessibilityButtonLink(context));
+ return sb;
}
private static int retrieveSoftwareShortcutImageResId(Context context) {
@@ -330,7 +336,7 @@ public class AccessibilityEditDialogUtils {
: R.drawable.accessibility_shortcut_type_software;
}
- private static CharSequence getSummaryStringWithLink(Context context) {
+ private static CharSequence getCustomizeAccessibilityButtonLink(Context context) {
final View.OnClickListener linkListener = v -> new SubSettingLauncher(context)
.setDestination(AccessibilityButtonFragment.class.getName())
.setSourceMetricsCategory(
diff --git a/src/com/android/settings/biometrics/BiometricEnrollActivity.java b/src/com/android/settings/biometrics/BiometricEnrollActivity.java
index cede6a02351..0a2e5fe804d 100644
--- a/src/com/android/settings/biometrics/BiometricEnrollActivity.java
+++ b/src/com/android/settings/biometrics/BiometricEnrollActivity.java
@@ -16,6 +16,9 @@
package com.android.settings.biometrics;
+import static android.provider.Settings.ACTION_BIOMETRIC_ENROLL;
+import static android.provider.Settings.EXTRA_BIOMETRIC_AUTHENTICATORS_ALLOWED;
+
import android.annotation.NonNull;
import android.app.admin.DevicePolicyManager;
import android.app.settings.SettingsEnums;
@@ -24,6 +27,7 @@ import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.hardware.biometrics.BiometricManager;
import android.hardware.biometrics.BiometricManager.Authenticators;
+import android.hardware.biometrics.BiometricManager.BiometricError;
import android.hardware.face.FaceManager;
import android.hardware.face.FaceSensorPropertiesInternal;
import android.hardware.fingerprint.FingerprintManager;
@@ -31,11 +35,11 @@ import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
import android.os.Bundle;
import android.os.UserHandle;
import android.os.UserManager;
-import android.provider.Settings;
import android.util.Log;
import androidx.annotation.Nullable;
+import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.widget.LockPatternUtils;
import com.android.settings.R;
import com.android.settings.SetupWizardUtils;
@@ -68,12 +72,14 @@ public class BiometricEnrollActivity extends InstrumentedActivity {
public static final String EXTRA_SKIP_INTRO = "skip_intro";
private static final String SAVED_STATE_CONFIRMING_CREDENTIALS = "confirming_credentials";
+ private static final String SAVED_STATE_ENROLL_ACTION_LOGGED = "enroll_action_logged";
private static final String SAVED_STATE_GK_PW_HANDLE = "gk_pw_handle";
public static final class InternalActivity extends BiometricEnrollActivity {}
private int mUserId = UserHandle.myUserId();
private boolean mConfirmingCredentials;
+ private boolean mIsEnrollActionLogged;
private boolean mIsFaceEnrollable;
private boolean mIsFingerprintEnrollable;
@Nullable private Long mGkPwHandle;
@@ -91,15 +97,44 @@ public class BiometricEnrollActivity extends InstrumentedActivity {
}
if (savedInstanceState != null) {
- mConfirmingCredentials = savedInstanceState
- .getBoolean(SAVED_STATE_CONFIRMING_CREDENTIALS, false);
+ mConfirmingCredentials = savedInstanceState.getBoolean(
+ SAVED_STATE_CONFIRMING_CREDENTIALS, false);
+ mIsEnrollActionLogged = savedInstanceState.getBoolean(
+ SAVED_STATE_ENROLL_ACTION_LOGGED, false);
if (savedInstanceState.containsKey(SAVED_STATE_GK_PW_HANDLE)) {
mGkPwHandle = savedInstanceState.getLong(SAVED_STATE_GK_PW_HANDLE);
}
}
- // Put the theme in the intent so it gets propagated to other activities in the flow
+ // Log a framework stats event if this activity was launched via intent action.
final Intent intent = getIntent();
+ if (!mIsEnrollActionLogged && ACTION_BIOMETRIC_ENROLL.equals(intent.getAction())) {
+ mIsEnrollActionLogged = true;
+
+ // Get the current status for each authenticator type.
+ @BiometricError final int strongBiometricStatus;
+ @BiometricError final int weakBiometricStatus;
+ @BiometricError final int deviceCredentialStatus;
+ final BiometricManager bm = getSystemService(BiometricManager.class);
+ if (bm != null) {
+ strongBiometricStatus = bm.canAuthenticate(Authenticators.BIOMETRIC_STRONG);
+ weakBiometricStatus = bm.canAuthenticate(Authenticators.BIOMETRIC_WEAK);
+ deviceCredentialStatus = bm.canAuthenticate(Authenticators.DEVICE_CREDENTIAL);
+ } else {
+ strongBiometricStatus = BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE;
+ weakBiometricStatus = BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE;
+ deviceCredentialStatus = BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE;
+ }
+
+ FrameworkStatsLog.write(FrameworkStatsLog.AUTH_ENROLL_ACTION_INVOKED,
+ strongBiometricStatus == BiometricManager.BIOMETRIC_SUCCESS,
+ weakBiometricStatus == BiometricManager.BIOMETRIC_SUCCESS,
+ deviceCredentialStatus == BiometricManager.BIOMETRIC_SUCCESS,
+ intent.hasExtra(EXTRA_BIOMETRIC_AUTHENTICATORS_ALLOWED),
+ intent.getIntExtra(EXTRA_BIOMETRIC_AUTHENTICATORS_ALLOWED, 0));
+ }
+
+ // Put the theme in the intent so it gets propagated to other activities in the flow
if (intent.getStringExtra(WizardManagerHelper.EXTRA_THEME) == null) {
intent.putExtra(
WizardManagerHelper.EXTRA_THEME,
@@ -108,7 +143,7 @@ public class BiometricEnrollActivity extends InstrumentedActivity {
// Default behavior is to enroll BIOMETRIC_WEAK or above. See ACTION_BIOMETRIC_ENROLL.
final int authenticators = intent.getIntExtra(
- Settings.EXTRA_BIOMETRIC_AUTHENTICATORS_ALLOWED, Authenticators.BIOMETRIC_WEAK);
+ EXTRA_BIOMETRIC_AUTHENTICATORS_ALLOWED, Authenticators.BIOMETRIC_WEAK);
Log.d(TAG, "Authenticators: " + authenticators);
@@ -132,7 +167,7 @@ public class BiometricEnrollActivity extends InstrumentedActivity {
} else {
// If the caller is not setup wizard, and the user has something enrolled, finish.
final BiometricManager bm = getSystemService(BiometricManager.class);
- final @BiometricManager.BiometricError int result = bm.canAuthenticate(authenticators);
+ final @BiometricError int result = bm.canAuthenticate(authenticators);
if (result != BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED) {
Log.e(TAG, "Unexpected result: " + result);
finish();
@@ -159,6 +194,7 @@ public class BiometricEnrollActivity extends InstrumentedActivity {
protected void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean(SAVED_STATE_CONFIRMING_CREDENTIALS, mConfirmingCredentials);
+ outState.putBoolean(SAVED_STATE_ENROLL_ACTION_LOGGED, mIsEnrollActionLogged);
if (mGkPwHandle != null) {
outState.putLong(SAVED_STATE_GK_PW_HANDLE, mGkPwHandle);
}
diff --git a/src/com/android/settings/core/SettingsBaseActivity.java b/src/com/android/settings/core/SettingsBaseActivity.java
index 569e4805b8d..e0e41dee2d2 100644
--- a/src/com/android/settings/core/SettingsBaseActivity.java
+++ b/src/com/android/settings/core/SettingsBaseActivity.java
@@ -49,8 +49,6 @@ import com.android.settingslib.drawer.Tile;
import com.google.android.material.appbar.CollapsingToolbarLayout;
import com.google.android.setupcompat.util.WizardManagerHelper;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@@ -61,7 +59,6 @@ public class SettingsBaseActivity extends FragmentActivity {
protected static final boolean DEBUG_TIMING = false;
private static final String TAG = "SettingsBaseActivity";
private static final String DATA_SCHEME_PKG = "package";
- private static final int TOOLBAR_MAX_LINE_NUMBER = 2;
// Serves as a temporary list of tiles to ignore until we heard back from the PM that they
// are disabled.
@@ -95,7 +92,7 @@ public class SettingsBaseActivity extends FragmentActivity {
if (FeatureFlagUtils.isEnabled(this, FeatureFlags.SILKY_HOME)
&& isToolbarEnabled() && !isAnySetupWizard) {
- super.setContentView(R.layout.settings_collapsing_base_layout);
+ super.setContentView(R.layout.collapsing_toolbar_base_layout);
mCollapsingToolbarLayout = findViewById(R.id.collapsing_toolbar);
} else {
super.setContentView(R.layout.settings_base_layout);
@@ -108,7 +105,6 @@ public class SettingsBaseActivity extends FragmentActivity {
return;
}
setActionBar(toolbar);
- initCollapsingToolbar();
if (DEBUG_TIMING) {
Log.d(TAG, "onCreate took " + (System.currentTimeMillis() - startTime) + " ms");
@@ -207,50 +203,6 @@ public class SettingsBaseActivity extends FragmentActivity {
return true;
}
- private void initCollapsingToolbar() {
- if (mCollapsingToolbarLayout == null) {
- return;
- }
- mCollapsingToolbarLayout.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
- @Override
- public void onLayoutChange(View v, int left, int top, int right, int bottom,
- int oldLeft, int oldTop, int oldRight, int oldBottom) {
- v.removeOnLayoutChangeListener(this);
- final int count = getLineCount();
- if (count > TOOLBAR_MAX_LINE_NUMBER) {
- ViewGroup.LayoutParams lp = mCollapsingToolbarLayout.getLayoutParams();
- lp.height = getResources()
- .getDimensionPixelSize(R.dimen.toolbar_three_lines_height);
- mCollapsingToolbarLayout.setLayoutParams(lp);
- } else if (count == TOOLBAR_MAX_LINE_NUMBER) {
- ViewGroup.LayoutParams lp = mCollapsingToolbarLayout.getLayoutParams();
- lp.height =
- getResources().getDimensionPixelSize(R.dimen.toolbar_two_lines_height);
- mCollapsingToolbarLayout.setLayoutParams(lp);
- }
- }
- });
- }
-
- private int getLineCount() {
- try {
- final Class> toolbarClazz = mCollapsingToolbarLayout.getClass();
- final Field textHelperField = toolbarClazz.getDeclaredField("collapsingTextHelper");
- textHelperField.setAccessible(true);
- final Object textHelperObj = textHelperField.get(mCollapsingToolbarLayout);
-
- final Field layoutField = textHelperObj.getClass().getDeclaredField("textLayout");
- layoutField.setAccessible(true);
- final Object layoutObj = layoutField.get(textHelperObj);
-
- final Method method = layoutObj.getClass().getDeclaredMethod("getLineCount");
- return (int) method.invoke(layoutObj);
- } catch (Exception e) {
- return 0;
- }
- }
-
-
private void onCategoriesChanged(Set categories) {
final int N = mCategoryListeners.size();
for (int i = 0; i < N; i++) {
diff --git a/src/com/android/settings/development/qstile/DevelopmentTiles.java b/src/com/android/settings/development/qstile/DevelopmentTiles.java
index 16084c080ce..c55d0cb354d 100644
--- a/src/com/android/settings/development/qstile/DevelopmentTiles.java
+++ b/src/com/android/settings/development/qstile/DevelopmentTiles.java
@@ -371,7 +371,7 @@ public abstract class DevelopmentTiles extends TileService {
mContext = getApplicationContext();
mSensorPrivacyManager = (SensorPrivacyManager) mContext.getSystemService(
Context.SENSOR_PRIVACY_SERVICE);
- mIsEnabled = mSensorPrivacyManager.isSensorPrivacyEnabled();
+ mIsEnabled = mSensorPrivacyManager.isAllSensorPrivacyEnabled();
mMetricsFeatureProvider = FeatureFactory.getFactory(
mContext).getMetricsFeatureProvider();
mKeyguardManager = (KeyguardManager) mContext.getSystemService(
@@ -392,7 +392,7 @@ public abstract class DevelopmentTiles extends TileService {
mMetricsFeatureProvider.action(getApplicationContext(), SettingsEnums.QS_SENSOR_PRIVACY,
isEnabled);
mIsEnabled = isEnabled;
- mSensorPrivacyManager.setSensorPrivacy(isEnabled);
+ mSensorPrivacyManager.setAllSensorPrivacy(isEnabled);
}
}
diff --git a/src/com/android/settings/display/AdaptiveSleepCameraStatePreferenceController.java b/src/com/android/settings/display/AdaptiveSleepCameraStatePreferenceController.java
index 72a1c66a431..ba7a3aba752 100644
--- a/src/com/android/settings/display/AdaptiveSleepCameraStatePreferenceController.java
+++ b/src/com/android/settings/display/AdaptiveSleepCameraStatePreferenceController.java
@@ -43,7 +43,7 @@ public class AdaptiveSleepCameraStatePreferenceController {
mPreference.setPositiveButtonText(R.string.allow);
mPrivacyManager = SensorPrivacyManager.getInstance(context);
mPrivacyManager.addSensorPrivacyListener(CAMERA,
- enabled -> updateVisibility());
+ (sensor, enabled) -> updateVisibility());
mPreference.setPositiveButtonOnClickListener(p -> {
mPrivacyManager.setSensorPrivacy(CAMERA, false);
});
diff --git a/src/com/android/settings/display/ScreenTimeoutSettings.java b/src/com/android/settings/display/ScreenTimeoutSettings.java
index 444f8ef8de2..27e1e1bfc45 100644
--- a/src/com/android/settings/display/ScreenTimeoutSettings.java
+++ b/src/com/android/settings/display/ScreenTimeoutSettings.java
@@ -111,9 +111,7 @@ public class ScreenTimeoutSettings extends RadioButtonPickerFragment implements
mPrivacyPreference.setLayoutResource(R.layout.preference_footer);
mPrivacyManager = SensorPrivacyManager.getInstance(context);
mPrivacyManager.addSensorPrivacyListener(CAMERA,
- enabled -> {
- mAdaptiveSleepController.updatePreference();
- });
+ (sensor, enabled) -> mAdaptiveSleepController.updatePreference());
}
@Override
diff --git a/src/com/android/settings/display/SmartAutoRotateCameraStateController.java b/src/com/android/settings/display/SmartAutoRotateCameraStateController.java
index 14807855521..9e2a7848d81 100644
--- a/src/com/android/settings/display/SmartAutoRotateCameraStateController.java
+++ b/src/com/android/settings/display/SmartAutoRotateCameraStateController.java
@@ -43,7 +43,7 @@ public class SmartAutoRotateCameraStateController extends BasePreferenceControll
public SmartAutoRotateCameraStateController(Context context, String key) {
super(context, key);
mPrivacyManager = SensorPrivacyManager.getInstance(context);
- mPrivacyManager.addSensorPrivacyListener(CAMERA, enabled -> {
+ mPrivacyManager.addSensorPrivacyListener(CAMERA, (sensor, enabled) -> {
mPreference.setVisible(enabled);
updateState(mPreference);
});
diff --git a/src/com/android/settings/display/SmartAutoRotateController.java b/src/com/android/settings/display/SmartAutoRotateController.java
index e3b2665195b..cf2a9a60567 100644
--- a/src/com/android/settings/display/SmartAutoRotateController.java
+++ b/src/com/android/settings/display/SmartAutoRotateController.java
@@ -52,7 +52,8 @@ public class SmartAutoRotateController extends TogglePreferenceController implem
super(context, preferenceKey);
mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
mPrivacyManager = SensorPrivacyManager.getInstance(context);
- mPrivacyManager.addSensorPrivacyListener(CAMERA, enabled -> updateState(mPreference));
+ mPrivacyManager
+ .addSensorPrivacyListener(CAMERA, (sensor, enabled) -> updateState(mPreference));
}
@Override
diff --git a/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java b/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java
index 432224d537a..3ef7c455302 100644
--- a/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java
+++ b/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java
@@ -27,6 +27,7 @@ import android.os.Bundle;
import android.os.UserHandle;
import android.text.Html;
import android.text.TextUtils;
+import android.text.format.DateUtils;
import android.util.Log;
import android.view.View;
@@ -282,20 +283,8 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements
final long foregroundTimeMs = bundle.getLong(EXTRA_FOREGROUND_TIME);
final long backgroundTimeMs = bundle.getLong(EXTRA_BACKGROUND_TIME);
- final long totalTimeMs = foregroundTimeMs + backgroundTimeMs;
- //TODO(b/178197718) Refine the layout
- controller.setSummary(TextUtils.expandTemplate(
- getText(R.string.battery_total_and_background_usage),
- StringUtil.formatElapsedTime(
- getContext(),
- totalTimeMs,
- /* withSeconds */ false,
- /* collapseTimeUnit */ false),
- StringUtil.formatElapsedTime(
- getContext(),
- backgroundTimeMs,
- /* withSeconds */ false,
- /* collapseTimeUnit */ false)));
+ //TODO(b/178197718) Update layout to support multiple lines
+ controller.setSummary(getAppActiveTime(foregroundTimeMs, backgroundTimeMs));
controller.done(context, true /* rebindActions */);
}
@@ -388,4 +377,53 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements
private void updatePreferenceState(RadioButtonPreference preference, String selectedKey) {
preference.setChecked(selectedKey.equals(preference.getKey()));
}
+
+ //TODO(b/178197718) Update method to support time period
+ private CharSequence getAppActiveTime(long foregroundTimeMs, long backgroundTimeMs) {
+ final long totalTimeMs = foregroundTimeMs + backgroundTimeMs;
+ final CharSequence usageTimeSummary;
+
+ if (totalTimeMs == 0) {
+ usageTimeSummary = getText(R.string.battery_not_usage);
+ // Shows background summary only if we don't have foreground usage time.
+ } else if (foregroundTimeMs == 0 && backgroundTimeMs != 0) {
+ usageTimeSummary = backgroundTimeMs < DateUtils.MINUTE_IN_MILLIS ?
+ getText(R.string.battery_background_usage_less_minute) :
+ TextUtils.expandTemplate(getText(R.string.battery_background_usage),
+ StringUtil.formatElapsedTime(
+ getContext(),
+ backgroundTimeMs,
+ /* withSeconds */ false,
+ /* collapseTimeUnit */ false));
+ // Shows total usage summary only if total usage time is small.
+ } else if (totalTimeMs < DateUtils.MINUTE_IN_MILLIS) {
+ usageTimeSummary = getText(R.string.battery_total_usage_less_minute);
+ // Shows different total usage summary when background usage time is small.
+ } else if (backgroundTimeMs < DateUtils.MINUTE_IN_MILLIS) {
+ usageTimeSummary = TextUtils.expandTemplate(
+ getText(backgroundTimeMs == 0 ?
+ R.string.battery_total_usage :
+ R.string.battery_total_usage_and_background_less_minute_usage),
+ StringUtil.formatElapsedTime(
+ getContext(),
+ totalTimeMs,
+ /* withSeconds */ false,
+ /* collapseTimeUnit */ false));
+ // Shows default summary.
+ } else {
+ usageTimeSummary = TextUtils.expandTemplate(
+ getText(R.string.battery_total_and_background_usage),
+ StringUtil.formatElapsedTime(
+ getContext(),
+ totalTimeMs,
+ /* withSeconds */ false,
+ /* collapseTimeUnit */ false),
+ StringUtil.formatElapsedTime(
+ getContext(),
+ backgroundTimeMs,
+ /* withSeconds */ false,
+ /* collapseTimeUnit */ false));
+ }
+ return usageTimeSummary;
+ }
}
diff --git a/src/com/android/settings/fuelgauge/BatteryChartPreferenceController.java b/src/com/android/settings/fuelgauge/BatteryChartPreferenceController.java
index f12de01df4a..4cafbc7b693 100644
--- a/src/com/android/settings/fuelgauge/BatteryChartPreferenceController.java
+++ b/src/com/android/settings/fuelgauge/BatteryChartPreferenceController.java
@@ -12,7 +12,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- *
*/
package com.android.settings.fuelgauge;
@@ -51,7 +50,7 @@ import java.util.Map;
/** Controls the update for chart graph and the list items. */
public class BatteryChartPreferenceController extends AbstractPreferenceController
implements PreferenceControllerMixin, LifecycleObserver, OnPause, OnDestroy,
- BatteryChartView.OnSelectListener {
+ BatteryChartView.OnSelectListener, ExpandDividerPreference.OnExpandListener {
private static final String TAG = "BatteryChartPreferenceController";
private static final int CHART_KEY_ARRAY_SIZE = 25;
private static final int CHART_LEVEL_ARRAY_SIZE = 13;
@@ -65,6 +64,7 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
@VisibleForTesting BatteryUtils mBatteryUtils;
@VisibleForTesting PreferenceGroup mAppListPrefGroup;
@VisibleForTesting BatteryChartView mBatteryChartView;
+ @VisibleForTesting ExpandDividerPreference mExpandDividerPreference;
@VisibleForTesting int[] mBatteryHistoryLevels;
@VisibleForTesting long[] mBatteryHistoryKeys;
@@ -76,9 +76,13 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
private final Handler mHandler = new Handler(Looper.getMainLooper());
private final CharSequence[] mNotAllowShowSummaryPackages;
+ private boolean mIsExpanded = false;
+
// Preference cache to avoid create new instance each time.
@VisibleForTesting
final Map mPreferenceCache = new HashMap<>();
+ @VisibleForTesting
+ final List mSystemEntries = new ArrayList<>();
public BatteryChartPreferenceController(
Context context, String preferenceKey,
@@ -163,6 +167,12 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
refreshUi(trapezoidIndex, /*isForce=*/ false);
}
+ @Override
+ public void onExpand(boolean isExpanded) {
+ mIsExpanded = isExpanded;
+ refreshExpandUi();
+ }
+
void setBatteryHistoryMap(
final Map> batteryHistoryMap) {
mHandler.post(() -> setBatteryHistoryMapInner(batteryHistoryMap));
@@ -266,10 +276,10 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
}
// Separates data into two groups and sort them individually.
final List appEntries = new ArrayList<>();
- final List systemEntries = new ArrayList<>();
+ mSystemEntries.clear();
entries.forEach(entry -> {
if (entry.isSystemEntry()) {
- systemEntries.add(entry);
+ mSystemEntries.add(entry);
} else {
appEntries.add(entry);
}
@@ -279,11 +289,25 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
}
});
Collections.sort(appEntries, BatteryDiffEntry.COMPARATOR);
- Collections.sort(systemEntries, BatteryDiffEntry.COMPARATOR);
+ Collections.sort(mSystemEntries, BatteryDiffEntry.COMPARATOR);
Log.d(TAG, String.format("addAllPreferences() app=%d system=%d",
- appEntries.size(), systemEntries.size()));
- addPreferenceToScreen(appEntries);
- addPreferenceToScreen(systemEntries);
+ appEntries.size(), mSystemEntries.size()));
+
+ // Adds app entries to the list if it is not empty.
+ if (!appEntries.isEmpty()) {
+ addPreferenceToScreen(appEntries);
+ }
+ // Adds the expabable divider if we have two sections data.
+ if (!appEntries.isEmpty() && !mSystemEntries.isEmpty()) {
+ if (mExpandDividerPreference == null) {
+ mExpandDividerPreference = new ExpandDividerPreference(mPrefContext);
+ mExpandDividerPreference.setOnExpandListener(this);
+ }
+ mExpandDividerPreference.setOrder(
+ mAppListPrefGroup.getPreferenceCount());
+ mAppListPrefGroup.addPreference(mExpandDividerPreference);
+ }
+ refreshExpandUi();
}
@VisibleForTesting
@@ -337,6 +361,22 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
mAppListPrefGroup.removeAll();
}
+ private void refreshExpandUi() {
+ if (mIsExpanded) {
+ addPreferenceToScreen(mSystemEntries);
+ } else {
+ // Removes and recycles all system entries to hide all of them.
+ for (BatteryDiffEntry entry : mSystemEntries) {
+ final String prefKey = entry.mBatteryHistEntry.getKey();
+ final Preference pref = mAppListPrefGroup.findPreference(prefKey);
+ if (pref != null) {
+ mAppListPrefGroup.removePreference(pref);
+ mPreferenceCache.put(pref.getKey(), pref);
+ }
+ }
+ }
+ }
+
@VisibleForTesting
void setPreferenceSummary(
PowerGaugePreference preference, BatteryDiffEntry entry) {
diff --git a/src/com/android/settings/network/telephony/Enable2gPreferenceController.java b/src/com/android/settings/network/telephony/Enable2gPreferenceController.java
index cf08d107528..d336cb47e47 100644
--- a/src/com/android/settings/network/telephony/Enable2gPreferenceController.java
+++ b/src/com/android/settings/network/telephony/Enable2gPreferenceController.java
@@ -72,7 +72,7 @@ public class Enable2gPreferenceController extends TelephonyTogglePreferenceContr
public int getAvailabilityStatus(int subId) {
final PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(subId);
boolean visible =
- subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID
+ SubscriptionManager.isUsableSubscriptionId(subId)
&& carrierConfig != null
&& !carrierConfig.getBoolean(CarrierConfigManager.KEY_HIDE_ENABLE_2G)
&& mTelephonyManager.isRadioInterfaceCapabilitySupported(
@@ -89,6 +89,9 @@ public class Enable2gPreferenceController extends TelephonyTogglePreferenceContr
@Override
public boolean setChecked(boolean isChecked) {
+ if (!SubscriptionManager.isUsableSubscriptionId(mSubId)) {
+ return false;
+ }
long currentlyAllowedNetworkTypes = mTelephonyManager.getAllowedNetworkTypesForReason(
mTelephonyManager.ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G);
boolean enabled = (currentlyAllowedNetworkTypes & BITMASK_2G) != 0;
diff --git a/src/com/android/settings/notification/NotificationAssistantPreferenceController.java b/src/com/android/settings/notification/NotificationAssistantPreferenceController.java
index 6237326f4e4..a46f1646113 100644
--- a/src/com/android/settings/notification/NotificationAssistantPreferenceController.java
+++ b/src/com/android/settings/notification/NotificationAssistantPreferenceController.java
@@ -77,11 +77,7 @@ public class NotificationAssistantPreferenceController extends TogglePreferenceC
protected void setNotificationAssistantGranted(ComponentName cn) {
if (Settings.Secure.getIntForUser(mContext.getContentResolver(),
Settings.Secure.NAS_SETTINGS_UPDATED, 0, mUserId) == 0) {
- for (int profileId : mUserManager.getProfileIds(mUserId, false)) {
- Settings.Secure.putIntForUser(mContext.getContentResolver(),
- Settings.Secure.NAS_SETTINGS_UPDATED, 1, profileId);
- }
- mNotificationBackend.resetDefaultNotificationAssistant(cn != null);
+ mNotificationBackend.setNASMigrationDoneAndResetDefault(mUserId, cn != null);
}
mNotificationBackend.setNotificationAssistantGranted(cn);
}
diff --git a/src/com/android/settings/notification/NotificationBackend.java b/src/com/android/settings/notification/NotificationBackend.java
index b08d02cef26..e448dda20aa 100644
--- a/src/com/android/settings/notification/NotificationBackend.java
+++ b/src/com/android/settings/notification/NotificationBackend.java
@@ -570,9 +570,9 @@ public class NotificationBackend {
}
}
- public void resetDefaultNotificationAssistant(boolean loadFromConfig) {
+ public void setNASMigrationDoneAndResetDefault(int userId, boolean loadFromConfig) {
try {
- sINM.resetDefaultNotificationAssistant(loadFromConfig);
+ sINM.setNASMigrationDoneAndResetDefault(userId, loadFromConfig);
} catch (Exception e) {
Log.w(TAG, "Error calling NoMan", e);
}
diff --git a/src/com/android/settings/notification/app/NotificationFooterPreference.java b/src/com/android/settings/notification/app/NotificationFooterPreference.java
deleted file mode 100644
index 6f34cdd5c90..00000000000
--- a/src/com/android/settings/notification/app/NotificationFooterPreference.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2017 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.notification.app;
-
-import android.content.Context;
-import android.text.method.LinkMovementMethod;
-import android.util.AttributeSet;
-import android.widget.TextView;
-
-import androidx.core.content.res.TypedArrayUtils;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceViewHolder;
-
-import com.android.settingslib.R;
-
-/**
- * FooterPreference that can have any key or ordering.
- */
-public class NotificationFooterPreference extends Preference {
-
- public NotificationFooterPreference(Context context, AttributeSet attrs) {
- super(context, attrs, TypedArrayUtils.getAttr(
- context, R.attr.footerPreferenceStyle, android.R.attr.preferenceStyle));
- init();
- }
-
- public NotificationFooterPreference(Context context) {
- this(context, null);
- }
-
- @Override
- public void onBindViewHolder(PreferenceViewHolder holder) {
- super.onBindViewHolder(holder);
- TextView title = holder.itemView.findViewById(android.R.id.title);
- title.setMovementMethod(new LinkMovementMethod());
- title.setClickable(false);
- title.setLongClickable(false);
- }
-
- private void init() {
- setIcon(R.drawable.ic_info_outline_24dp);
- setSelectable(false);
- }
-}
diff --git a/src/com/android/settings/uwb/UwbPreferenceController.java b/src/com/android/settings/uwb/UwbPreferenceController.java
new file mode 100644
index 00000000000..daadb63b8dd
--- /dev/null
+++ b/src/com/android/settings/uwb/UwbPreferenceController.java
@@ -0,0 +1,168 @@
+/*
+ * 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.uwb;
+
+import static androidx.lifecycle.Lifecycle.Event.ON_START;
+import static androidx.lifecycle.Lifecycle.Event.ON_STOP;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.provider.Settings;
+import android.uwb.UwbManager;
+import android.uwb.UwbManager.AdapterStateCallback;
+
+import androidx.lifecycle.LifecycleObserver;
+import androidx.lifecycle.OnLifecycleEvent;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.settings.R;
+import com.android.settings.core.TogglePreferenceController;
+
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+
+/** Controller for "UWB" toggle. */
+public class UwbPreferenceController extends TogglePreferenceController implements
+ AdapterStateCallback, LifecycleObserver {
+ @VisibleForTesting
+ static final String KEY_UWB_SETTINGS = "uwb_settings";
+ @VisibleForTesting
+ UwbManager mUwbManager;
+ @VisibleForTesting
+ boolean mAirplaneModeOn;
+ @VisibleForTesting
+ private final BroadcastReceiver mAirplaneModeChangedReceiver;
+ private final Executor mExecutor;
+ private boolean mIsChecked = true;
+ boolean mRegisteredAdapterStateCallback = false;
+ private Preference mPreference;
+
+ public UwbPreferenceController(Context context, String key) {
+ super(context, key);
+ mExecutor = Executors.newSingleThreadExecutor();
+ mUwbManager = context.getSystemService(UwbManager.class);
+ mAirplaneModeOn = Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.AIRPLANE_MODE_ON, 0) == 1;
+ mAirplaneModeChangedReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ updateState(mPreference);
+ }
+ };
+ }
+
+ @VisibleForTesting
+ boolean isUwbSupportedOnDevice() {
+ return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_UWB);
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ if (!isUwbSupportedOnDevice()) {
+ return UNSUPPORTED_ON_DEVICE;
+ } else if (mAirplaneModeOn) {
+ return DISABLED_DEPENDENT_SETTING;
+ } else {
+ return AVAILABLE;
+ }
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ super.displayPreference(screen);
+ mPreference = screen.findPreference(getPreferenceKey());
+ }
+
+ @Override
+ public boolean isChecked() {
+ //TODO(b/186075119): Update toggle state by assigning to the real value by default.
+ return mIsChecked;
+ }
+
+ @Override
+ public boolean setChecked(boolean isChecked) {
+ mIsChecked = isChecked;
+ mUwbManager.setUwbEnabled(isChecked);
+ return true;
+ }
+
+ @Override
+ public void onStateChanged(int state, int reason) {
+ // Only update toggle state from service the first time. Otherwise toggle state is
+ // changed from controller. For example, UWB is disabled if airplane mode is on but we do
+ // not want to change the preference for the user in this case.
+ if (!mRegisteredAdapterStateCallback) {
+ mIsChecked = state == STATE_ENABLED_ACTIVE || state == STATE_ENABLED_INACTIVE;
+ mRegisteredAdapterStateCallback = true;
+ }
+ }
+
+ /** Called when activity starts being displayed to user. */
+ @OnLifecycleEvent(ON_START)
+ public void onStart() {
+ if (isUwbSupportedOnDevice()) {
+ mUwbManager.registerAdapterStateCallback(mExecutor, this);
+ }
+ if (mAirplaneModeChangedReceiver != null) {
+ mContext.registerReceiver(mAirplaneModeChangedReceiver,
+ new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED));
+ }
+ refreshSummary(mPreference);
+ }
+
+ /** Called when activity stops being displayed to user. */
+ @OnLifecycleEvent(ON_STOP)
+ public void onStop() {
+ if (isUwbSupportedOnDevice()) {
+ mUwbManager.unregisterAdapterStateCallback(this);
+ }
+ if (mAirplaneModeChangedReceiver != null) {
+ mContext.unregisterReceiver(mAirplaneModeChangedReceiver);
+ }
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ super.updateState(preference);
+ mAirplaneModeOn = Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.AIRPLANE_MODE_ON, 0) == 1;
+ preference.setEnabled(!mAirplaneModeOn);
+ if (isUwbSupportedOnDevice()) {
+ if (mAirplaneModeOn) {
+ mUwbManager.setUwbEnabled(false);
+ } else {
+ mUwbManager.setUwbEnabled(mIsChecked);
+ }
+ }
+ refreshSummary(preference);
+ }
+
+ @Override
+ public CharSequence getSummary() {
+ if (mAirplaneModeOn) {
+ return mContext.getResources().getString(R.string.uwb_settings_summary_airplane_mode);
+ } else {
+ return mContext.getResources().getString(R.string.uwb_settings_summary);
+ }
+ }
+}
+
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java b/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java
index a288c3a84c2..dd10a9e1556 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java
@@ -249,14 +249,122 @@ public class AdvancedPowerUsageDetailTest {
}
@Test
- public void testInitHeader_hasCorrectSummary() {
- mFragment.mAppEntry = null;
+ public void testInitHeader_noUsageTime_hasCorrectSummary() {
+ Bundle bundle = new Bundle(2);
+ bundle.putLong(AdvancedPowerUsageDetail.EXTRA_BACKGROUND_TIME, /* value */ 0);
+ bundle.putLong(AdvancedPowerUsageDetail.EXTRA_FOREGROUND_TIME, /* value */ 0);
+ when(mFragment.getArguments()).thenReturn(bundle);
+
mFragment.initHeader();
ArgumentCaptor captor = ArgumentCaptor.forClass(CharSequence.class);
verify(mEntityHeaderController).setSummary(captor.capture());
assertThat(captor.getValue().toString())
- .isEqualTo("0 min total • 0 min background for past 24 hr");
+ .isEqualTo("No usage for past 24 hr");
+ }
+
+ @Test
+ public void testInitHeader_backgroundTwoMinutesForegroundZero_hasCorrectSummary() {
+ final long backgroundTimeTwoMinutes = 120000;
+ final long foregroundTimeZero = 0;
+ Bundle bundle = new Bundle(2);
+ bundle.putLong(AdvancedPowerUsageDetail.EXTRA_BACKGROUND_TIME, backgroundTimeTwoMinutes);
+ bundle.putLong(AdvancedPowerUsageDetail.EXTRA_FOREGROUND_TIME, foregroundTimeZero);
+ when(mFragment.getArguments()).thenReturn(bundle);
+
+ mFragment.initHeader();
+
+ ArgumentCaptor captor = ArgumentCaptor.forClass(CharSequence.class);
+ verify(mEntityHeaderController).setSummary(captor.capture());
+ assertThat(captor.getValue().toString())
+ .isEqualTo("2 min background for past 24 hr");
+ }
+
+ @Test
+ public void testInitHeader_backgroundLessThanAMinutesForegroundZero_hasCorrectSummary() {
+ final long backgroundTimeLessThanAMinute = 59999;
+ final long foregroundTimeZero = 0;
+ Bundle bundle = new Bundle(2);
+ bundle.putLong(
+ AdvancedPowerUsageDetail.EXTRA_BACKGROUND_TIME, backgroundTimeLessThanAMinute);
+ bundle.putLong(AdvancedPowerUsageDetail.EXTRA_FOREGROUND_TIME, foregroundTimeZero);
+ when(mFragment.getArguments()).thenReturn(bundle);
+
+ mFragment.initHeader();
+
+ ArgumentCaptor captor = ArgumentCaptor.forClass(CharSequence.class);
+ verify(mEntityHeaderController).setSummary(captor.capture());
+ assertThat(captor.getValue().toString())
+ .isEqualTo("Background less than a minute for past 24 hr");
+ }
+
+ @Test
+ public void testInitHeader_totalUsageLessThanAMinutes_hasCorrectSummary() {
+ final long backgroundTimeLessThanHalfMinute = 20000;
+ final long foregroundTimeLessThanHalfMinute = 20000;
+ Bundle bundle = new Bundle(2);
+ bundle.putLong(
+ AdvancedPowerUsageDetail.EXTRA_BACKGROUND_TIME, backgroundTimeLessThanHalfMinute);
+ bundle.putLong(
+ AdvancedPowerUsageDetail.EXTRA_FOREGROUND_TIME, foregroundTimeLessThanHalfMinute);
+ when(mFragment.getArguments()).thenReturn(bundle);
+
+ mFragment.initHeader();
+
+ ArgumentCaptor captor = ArgumentCaptor.forClass(CharSequence.class);
+ verify(mEntityHeaderController).setSummary(captor.capture());
+ assertThat(captor.getValue().toString())
+ .isEqualTo("Total less than a minute for past 24 hr");
+ }
+
+ @Test
+ public void testInitHeader_TotalAMinutesBackgroundLessThanAMinutes_hasCorrectSummary() {
+ final long backgroundTimeZero = 59999;
+ final long foregroundTimeTwoMinutes = 1;
+ Bundle bundle = new Bundle(2);
+ bundle.putLong(AdvancedPowerUsageDetail.EXTRA_BACKGROUND_TIME, backgroundTimeZero);
+ bundle.putLong(AdvancedPowerUsageDetail.EXTRA_FOREGROUND_TIME, foregroundTimeTwoMinutes);
+ when(mFragment.getArguments()).thenReturn(bundle);
+
+ mFragment.initHeader();
+
+ ArgumentCaptor captor = ArgumentCaptor.forClass(CharSequence.class);
+ verify(mEntityHeaderController).setSummary(captor.capture());
+ assertThat(captor.getValue().toString())
+ .isEqualTo("1 min total • background less than a minute for past 24 hr");
+ }
+
+ @Test
+ public void testInitHeader_TotalAMinutesBackgroundZero_hasCorrectSummary() {
+ final long backgroundTimeZero = 0;
+ final long foregroundTimeAMinutes = 60000;
+ Bundle bundle = new Bundle(2);
+ bundle.putLong(AdvancedPowerUsageDetail.EXTRA_BACKGROUND_TIME, backgroundTimeZero);
+ bundle.putLong(AdvancedPowerUsageDetail.EXTRA_FOREGROUND_TIME, foregroundTimeAMinutes);
+ when(mFragment.getArguments()).thenReturn(bundle);
+
+ mFragment.initHeader();
+
+ ArgumentCaptor captor = ArgumentCaptor.forClass(CharSequence.class);
+ verify(mEntityHeaderController).setSummary(captor.capture());
+ assertThat(captor.getValue().toString())
+ .isEqualTo("1 min total for past 24 hr");
+ }
+
+ @Test
+ public void testInitHeader_foregroundTwoMinutesBackgroundFourMinutes_hasCorrectSummary() {
+ final long backgroundTimeFourMinute = 240000;
+ final long foregroundTimeTwoMinutes = 120000;
+ Bundle bundle = new Bundle(2);
+ bundle.putLong(AdvancedPowerUsageDetail.EXTRA_BACKGROUND_TIME, backgroundTimeFourMinute);
+ bundle.putLong(AdvancedPowerUsageDetail.EXTRA_FOREGROUND_TIME, foregroundTimeTwoMinutes);
+ when(mFragment.getArguments()).thenReturn(bundle);
+ mFragment.initHeader();
+
+ ArgumentCaptor captor = ArgumentCaptor.forClass(CharSequence.class);
+ verify(mEntityHeaderController).setSummary(captor.capture());
+ assertThat(captor.getValue().toString())
+ .isEqualTo("6 min total • 4 min background for past 24 hr");
}
@Test
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryChartPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryChartPreferenceControllerTest.java
index c8bbba3623c..a70a109330c 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryChartPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryChartPreferenceControllerTest.java
@@ -43,6 +43,7 @@ import com.android.settings.testutils.FakeFeatureFactory;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
@@ -416,23 +417,56 @@ public final class BatteryChartPreferenceControllerTest {
@Test
public void testValidateSlotTimestamp_returnExpectedResult() {
- final List slotTimestampList =
+ final ArrayList slotTimestampList = new ArrayList(
Arrays.asList(
Long.valueOf(0),
Long.valueOf(DateUtils.HOUR_IN_MILLIS),
Long.valueOf(DateUtils.HOUR_IN_MILLIS * 2 + DateUtils.MINUTE_IN_MILLIS),
- Long.valueOf(DateUtils.HOUR_IN_MILLIS * 3 + DateUtils.MINUTE_IN_MILLIS * 2));
+ Long.valueOf(DateUtils.HOUR_IN_MILLIS * 3 + DateUtils.MINUTE_IN_MILLIS * 2)));
// Verifies the testing data is correct before we added invalid data into it.
assertThat(BatteryChartPreferenceController.validateSlotTimestamp(slotTimestampList))
.isTrue();
// Insert invalid timestamp into the list.
slotTimestampList.add(
- Long.valueOf(DateUtils.HOUR_IN_MILLIS * 4 + DateUtils.MINUTE_IN_MILLIS * 3));
+ Long.valueOf(DateUtils.HOUR_IN_MILLIS * 4 + DateUtils.MINUTE_IN_MILLIS * 6));
assertThat(BatteryChartPreferenceController.validateSlotTimestamp(slotTimestampList))
.isFalse();
}
+ @Test
+ public void testOnExpand_expandedIsTrue_addSystemEntriesToPreferenceGroup() {
+ final String prefKey = "preference_key";
+ doReturn(1).when(mAppListGroup).getPreferenceCount();
+ mBatteryChartPreferenceController.mSystemEntries.add(mBatteryDiffEntry);
+ doReturn("label").when(mBatteryDiffEntry).getAppLabel();
+ doReturn(mDrawable).when(mBatteryDiffEntry).getAppIcon();
+ doReturn(prefKey).when(mBatteryHistEntry).getKey();
+
+ mBatteryChartPreferenceController.onExpand(/*isExpanded=*/ true);
+
+ final ArgumentCaptor captor = ArgumentCaptor.forClass(Preference.class);
+ verify(mAppListGroup).addPreference(captor.capture());
+ // Verifies the added preference.
+ assertThat(captor.getValue().getKey()).isEqualTo(prefKey);
+ }
+
+ @Test
+ public void testOnExpand_expandedIsFalse_removeSystemEntriesFromPreferenceGroup() {
+ final String prefKey = "preference_key";
+ doReturn(prefKey).when(mBatteryHistEntry).getKey();
+ doReturn(mPowerGaugePreference).when(mAppListGroup).findPreference(prefKey);
+ mBatteryChartPreferenceController.mSystemEntries.add(mBatteryDiffEntry);
+ // Verifies the cache is empty first.
+ assertThat(mBatteryChartPreferenceController.mPreferenceCache).isEmpty();
+
+ mBatteryChartPreferenceController.onExpand(/*isExpanded=*/ false);
+
+ verify(mAppListGroup).findPreference(prefKey);
+ verify(mAppListGroup).removePreference(mPowerGaugePreference);
+ assertThat(mBatteryChartPreferenceController.mPreferenceCache).hasSize(1);
+ }
+
private static Map> createBatteryHistoryMap(int size) {
final Map> batteryHistoryMap = new HashMap<>();
for (int index = 0; index < size; index++) {
diff --git a/tests/robotests/src/com/android/settings/notification/NotificationAssistantPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/NotificationAssistantPreferenceControllerTest.java
index f6b72d963bc..9b45a9808eb 100644
--- a/tests/robotests/src/com/android/settings/notification/NotificationAssistantPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/NotificationAssistantPreferenceControllerTest.java
@@ -122,13 +122,13 @@ public class NotificationAssistantPreferenceControllerTest {
assertEquals(1, Settings.Secure.getIntForUser(mContext.getContentResolver(),
Settings.Secure.NAS_SETTINGS_UPDATED, 0, 10));
verify(mBackend, times(1))
- .resetDefaultNotificationAssistant(eq(true));
+ .setNASMigrationDoneAndResetDefault(eq(0), eq(true));
//Test user enable again, migration should not happen
mPreferenceController.setNotificationAssistantGranted(mNASComponent);
//Number of invocations should not increase
verify(mBackend, times(1))
- .resetDefaultNotificationAssistant(eq(true));
+ .setNASMigrationDoneAndResetDefault(eq(0), eq(true));
}
@Test
@@ -146,13 +146,13 @@ public class NotificationAssistantPreferenceControllerTest {
assertEquals(0, Settings.Secure.getIntForUser(mContext.getContentResolver(),
Settings.Secure.NAS_SETTINGS_UPDATED, 0, 20));
verify(mBackend, times(1))
- .resetDefaultNotificationAssistant(eq(true));
+ .setNASMigrationDoneAndResetDefault(eq(0), eq(true));
//Test user enable again, migration should not happen
mPreferenceController.setNotificationAssistantGranted(mNASComponent);
//Number of invocations should not increase
verify(mBackend, times(1))
- .resetDefaultNotificationAssistant(eq(true));
+ .setNASMigrationDoneAndResetDefault(eq(0), eq(true));
}
@Test
@@ -170,13 +170,13 @@ public class NotificationAssistantPreferenceControllerTest {
assertEquals(1, Settings.Secure.getIntForUser(mContext.getContentResolver(),
Settings.Secure.NAS_SETTINGS_UPDATED, 0, 10));
verify(mBackend, times(1))
- .resetDefaultNotificationAssistant(eq(false));
+ .setNASMigrationDoneAndResetDefault(eq(0), eq(false));
//Test user disable again, migration should not happen
mPreferenceController.setChecked(false);
//Number of invocations should not increase
verify(mBackend, times(1))
- .resetDefaultNotificationAssistant(eq(false));
+ .setNASMigrationDoneAndResetDefault(eq(0), eq(false));
}
}
diff --git a/tests/robotests/src/com/android/settings/uwb/UwbPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/uwb/UwbPreferenceControllerTest.java
new file mode 100644
index 00000000000..00dc4dff4ae
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/uwb/UwbPreferenceControllerTest.java
@@ -0,0 +1,176 @@
+/*
+ * 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.uwb;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.clearInvocations;
+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 android.content.pm.PackageManager;
+import android.uwb.UwbManager;
+
+import com.android.settings.core.BasePreferenceController;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+/** Unit tests for UWB preference toggle. */
+@RunWith(RobolectricTestRunner.class)
+public class UwbPreferenceControllerTest {
+ @Rule
+ public MockitoRule rule = MockitoJUnit.rule();
+
+ private Context mContext;
+ private PackageManager mPackageManager;
+ private UwbPreferenceController mController;
+
+ @Mock
+ private UwbManager mUwbManager;
+
+ @Before
+ public void setUp() {
+ mContext = spy(RuntimeEnvironment.application);
+ mPackageManager = spy(mContext.getPackageManager());
+ mController = new UwbPreferenceController(mContext, "uwb_settings");
+ mController.mUwbManager = mUwbManager;
+ }
+
+ @Test
+ public void getAvailabilityStatus_uwbDisabled_shouldReturnDisabled() {
+ doReturn(mPackageManager).when(mContext).getPackageManager();
+ doReturn(true).when(mPackageManager)
+ .hasSystemFeature(PackageManager.FEATURE_UWB);
+ mController.mAirplaneModeOn = true;
+
+ assertThat(mController.getAvailabilityStatus())
+ .isEqualTo(BasePreferenceController.DISABLED_DEPENDENT_SETTING);
+ }
+
+ @Test
+ public void getAvailabilityStatus_uwbShown_shouldReturnAvailable() {
+ doReturn(mPackageManager).when(mContext).getPackageManager();
+ doReturn(true).when(mPackageManager)
+ .hasSystemFeature(PackageManager.FEATURE_UWB);
+ mController.mAirplaneModeOn = false;
+
+ assertThat(mController.getAvailabilityStatus())
+ .isEqualTo(BasePreferenceController.AVAILABLE);
+ }
+
+ @Test
+ public void getAvailabilityStatus_uwbNotShown_shouldReturnUnsupported() {
+ doReturn(mPackageManager).when(mContext).getPackageManager();
+ doReturn(false).when(mPackageManager)
+ .hasSystemFeature(PackageManager.FEATURE_UWB);
+
+ assertThat(mController.getAvailabilityStatus())
+ .isEqualTo(BasePreferenceController.UNSUPPORTED_ON_DEVICE);
+ }
+
+ @Test
+ public void onStateChanged_stateNotRegistered_shouldUpdate() {
+ mController.mRegisteredAdapterStateCallback = false;
+ mController.onStateChanged(UwbManager.AdapterStateCallback.STATE_DISABLED,
+ UwbManager.AdapterStateCallback.STATE_CHANGED_REASON_SYSTEM_POLICY);
+
+ assertThat(mController.isChecked()).isFalse();
+ }
+
+ @Test
+ public void onStateChanged_stateRegistered_shouldNotUpdate() {
+ mController.mRegisteredAdapterStateCallback = true;
+ mController.onStateChanged(UwbManager.AdapterStateCallback.STATE_ENABLED_INACTIVE,
+ UwbManager.AdapterStateCallback.STATE_CHANGED_REASON_SYSTEM_POLICY);
+
+ assertThat(mController.isChecked()).isTrue();
+ }
+
+ @Test
+ public void isChecked_uwbEnabledInactive_shouldReturnTrue() {
+ doReturn(mPackageManager).when(mContext).getPackageManager();
+ doReturn(true).when(mPackageManager)
+ .hasSystemFeature(PackageManager.FEATURE_UWB);
+ mController.mRegisteredAdapterStateCallback = false;
+ mController.onStateChanged(UwbManager.AdapterStateCallback.STATE_ENABLED_INACTIVE,
+ UwbManager.AdapterStateCallback.STATE_CHANGED_REASON_SYSTEM_POLICY);
+
+ assertThat(mController.isChecked()).isTrue();
+ }
+
+ @Test
+ public void isChecked_uwbEnabledActive_shouldReturnTrue() {
+ doReturn(mPackageManager).when(mContext).getPackageManager();
+ doReturn(true).when(mPackageManager)
+ .hasSystemFeature(PackageManager.FEATURE_UWB);
+ mController.mRegisteredAdapterStateCallback = false;
+ mController.onStateChanged(UwbManager.AdapterStateCallback.STATE_ENABLED_ACTIVE,
+ UwbManager.AdapterStateCallback.STATE_CHANGED_REASON_SYSTEM_POLICY);
+
+ assertThat(mController.isChecked()).isTrue();
+ }
+
+ @Test
+ public void isChecked_uwbDisabled_shouldReturnFalse() {
+ doReturn(mPackageManager).when(mContext).getPackageManager();
+ doReturn(true).when(mPackageManager)
+ .hasSystemFeature(PackageManager.FEATURE_UWB);
+ mController.mRegisteredAdapterStateCallback = false;
+ mController.onStateChanged(UwbManager.AdapterStateCallback.STATE_DISABLED,
+ UwbManager.AdapterStateCallback.STATE_CHANGED_REASON_SYSTEM_POLICY);
+
+ assertThat(mController.isChecked()).isFalse();
+ }
+
+ @Test
+ public void setChecked_uwbDisabled_shouldEnableUwb() {
+ clearInvocations(mUwbManager);
+ doReturn(mPackageManager).when(mContext).getPackageManager();
+ doReturn(true).when(mPackageManager)
+ .hasSystemFeature(PackageManager.FEATURE_UWB);
+
+ mController.setChecked(true);
+
+ verify(mUwbManager).setUwbEnabled(true);
+ verify(mUwbManager, never()).setUwbEnabled(false);
+ }
+
+ @Test
+ public void setChecked_uwbEnabled_shouldDisableUwb() {
+ clearInvocations(mUwbManager);
+ doReturn(mPackageManager).when(mContext).getPackageManager();
+ doReturn(true).when(mPackageManager)
+ .hasSystemFeature(PackageManager.FEATURE_UWB);
+
+ mController.setChecked(false);
+
+ verify(mUwbManager).setUwbEnabled(false);
+ verify(mUwbManager, never()).setUwbEnabled(true);
+ }
+}
+
diff --git a/tests/unit/src/com/android/settings/network/telephony/Enable2gPreferenceControllerTest.java b/tests/unit/src/com/android/settings/network/telephony/Enable2gPreferenceControllerTest.java
index 293a19dad09..5ade97953e0 100644
--- a/tests/unit/src/com/android/settings/network/telephony/Enable2gPreferenceControllerTest.java
+++ b/tests/unit/src/com/android/settings/network/telephony/Enable2gPreferenceControllerTest.java
@@ -48,6 +48,8 @@ public final class Enable2gPreferenceControllerTest {
@Mock
private TelephonyManager mTelephonyManager;
@Mock
+ private TelephonyManager mInvalidTelephonyManager;
+ @Mock
private CarrierConfigManager mCarrierConfigManager;
private PersistableBundle mPersistableBundle;
@@ -65,6 +67,8 @@ public final class Enable2gPreferenceControllerTest {
.thenReturn(mCarrierConfigManager);
doReturn(mTelephonyManager).when(mTelephonyManager).createForSubscriptionId(SUB_ID);
+ doReturn(mInvalidTelephonyManager).when(mTelephonyManager).createForSubscriptionId(
+ SubscriptionManager.INVALID_SUBSCRIPTION_ID);
mPersistableBundle = new PersistableBundle();
doReturn(mPersistableBundle).when(mCarrierConfigManager).getConfigForSubId(SUB_ID);
@@ -120,6 +124,18 @@ public final class Enable2gPreferenceControllerTest {
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
}
+ @Test
+ public void setChecked_invalidSubIdAndIsCheckedTrue_returnFalse() {
+ mController.init(SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+ assertThat(mController.setChecked(true)).isFalse();
+ }
+
+ @Test
+ public void setChecked_invalidSubIdAndIsCheckedFalse_returnFalse() {
+ mController.init(SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+ assertThat(mController.setChecked(false)).isFalse();
+ }
+
@Test
public void onPreferenceChange_update() {
// Set "Enable 2G" flag to "on"