Merge "Remove Theme.AlertDialog declaration in accessibility dialog layout"
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 938e33d..2ff62cc 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -132,7 +132,8 @@
android:defaultToDeviceProtectedStorage="true"
android:directBootAware="true"
android:appComponentFactory="androidx.core.app.CoreComponentFactory"
- android:gwpAsanMode="always">
+ android:gwpAsanMode="always"
+ android:enableOnBackInvokedCallback="true">
<uses-library android:name="org.apache.http.legacy" />
diff --git a/res/layout/choose_lock_pattern_common.xml b/res/layout/choose_lock_pattern_common.xml
index 2dd8cd5..761a724 100644
--- a/res/layout/choose_lock_pattern_common.xml
+++ b/res/layout/choose_lock_pattern_common.xml
@@ -37,6 +37,16 @@
android:paddingRight="0dp">
<TextView
+ android:id="@+id/sud_layout_description"
+ android:text="@string/lockpassword_choose_your_pattern_description"
+ style="@style/SudDescription.Glif"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:minLines="4"
+ android:paddingStart="?attr/sudMarginStart"
+ android:paddingEnd="?attr/sudMarginEnd"/>
+
+ <TextView
android:id="@+id/headerText"
style="@style/SudDescription.Glif"
android:layout_width="match_parent"
diff --git a/res/values/bools.xml b/res/values/bools.xml
new file mode 100644
index 0000000..25c3e0d
--- /dev/null
+++ b/res/values/bools.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2022, 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.
+*/
+-->
+<resources>
+ <!-- Referenced outside of Settings to confirm bug fixed - bug involved multiple
+ pending intents with difference only in intent extras, which doesn't work. -->
+ <bool name="config_isSafetyCenterLockScreenPendingIntentFixed">true</bool>
+</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 355b4ba..9c0250a 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -4386,6 +4386,8 @@
<string name="lockpassword_choose_your_profile_pin_header">Set a work PIN</string>
<!-- Header on first screen of choose device pattern flow [CHAR LIMIT=40] -->
<string name="lockpassword_choose_your_pattern_header">Set a pattern</string>
+ <!-- Description on first screen of choose device pattern flow [CHAR LIMIT=NONE] -->
+ <string name="lockpassword_choose_your_pattern_description">For added security, set a pattern to unlock the device</string>
<!-- Header on first screen of choose work profile pattern flow [CHAR LIMIT=40] -->
<string name="lockpassword_choose_your_profile_pattern_header">Set a work pattern</string>
@@ -9421,12 +9423,12 @@
<!-- app summary of notification app list screen [CHAR LIMIT=100] -->
<plurals name="notifications_sent_daily">
- <item quantity="one">~<xliff:g id="number">%d</xliff:g> notification per day</item>
- <item quantity="other">~<xliff:g id="number">%,d</xliff:g> notifications per day</item>
+ <item quantity="one">About <xliff:g id="number">%d</xliff:g> notification per day</item>
+ <item quantity="other">About <xliff:g id="number">%,d</xliff:g> notifications per day</item>
</plurals>
<plurals name="notifications_sent_weekly">
- <item quantity="one">~<xliff:g id="number">%d</xliff:g> notification per week</item>
- <item quantity="other">~<xliff:g id="number">%,d</xliff:g> notifications per week</item>
+ <item quantity="one">About <xliff:g id="number">%d</xliff:g> notification per week</item>
+ <item quantity="other">About <xliff:g id="number">%,d</xliff:g> notifications per week</item>
</plurals>
<!-- app summary of notification app list screen [CHAR LIMIT=100] -->
<string name="notifications_sent_never">Never</string>
diff --git a/src/com/android/settings/accessibility/AccessibilityGestureNavigationTutorial.java b/src/com/android/settings/accessibility/AccessibilityGestureNavigationTutorial.java
index 95469d4..bceed73 100644
--- a/src/com/android/settings/accessibility/AccessibilityGestureNavigationTutorial.java
+++ b/src/com/android/settings/accessibility/AccessibilityGestureNavigationTutorial.java
@@ -24,7 +24,6 @@
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.content.DialogInterface;
-import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.text.Spannable;
import android.text.SpannableString;
@@ -43,7 +42,6 @@
import android.widget.TextView;
import androidx.annotation.AnimRes;
-import androidx.annotation.ColorInt;
import androidx.annotation.DrawableRes;
import androidx.annotation.IntDef;
import androidx.annotation.NonNull;
@@ -51,7 +49,6 @@
import androidx.annotation.RawRes;
import androidx.annotation.VisibleForTesting;
import androidx.appcompat.app.AlertDialog;
-import androidx.core.content.ContextCompat;
import androidx.core.util.Preconditions;
import androidx.core.widget.TextViewCompat;
import androidx.viewpager.widget.PagerAdapter;
@@ -112,17 +109,6 @@
alertDialog.show();
}
- static AlertDialog showAccessibilityButtonTutorialDialog(Context context) {
- final AlertDialog alertDialog = createDialog(context,
- DialogType.LAUNCH_SERVICE_BY_ACCESSIBILITY_BUTTON);
-
- if (!AccessibilityUtil.isGestureNavigateEnabled(context)) {
- updateMessageWithIcon(context, alertDialog);
- }
-
- return alertDialog;
- }
-
static AlertDialog showAccessibilityGestureTutorialDialog(Context context) {
return createDialog(context, DialogType.LAUNCH_SERVICE_BY_ACCESSIBILITY_GESTURE);
}
@@ -218,50 +204,6 @@
return alertDialog;
}
- private static void updateMessageWithIcon(Context context, AlertDialog alertDialog) {
- final TextView gestureTutorialMessage = alertDialog.findViewById(
- R.id.button_tutorial_message);
-
- // Get the textView line height to update [icon] size. Must be called after show()
- final int lineHeight = gestureTutorialMessage.getLineHeight();
- gestureTutorialMessage.setText(getMessageStringWithIcon(context, lineHeight));
- }
-
- private static SpannableString getMessageStringWithIcon(Context context, int lineHeight) {
- final String messageString = context
- .getString(R.string.accessibility_tutorial_dialog_message_button);
- final SpannableString spannableMessage = SpannableString.valueOf(messageString);
-
- // Icon
- final int indexIconStart = messageString.indexOf("%s");
- final int indexIconEnd = indexIconStart + 2;
- final Drawable icon = context.getDrawable(R.drawable.ic_accessibility_new);
- final ImageSpan imageSpan = new ImageSpan(icon);
- imageSpan.setContentDescription("");
- icon.setBounds(0, 0, lineHeight, lineHeight);
- spannableMessage.setSpan(
- imageSpan, indexIconStart, indexIconEnd,
- Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
-
- return spannableMessage;
- }
-
- /** Returns the color associated with the specified attribute in the context's theme. */
- @ColorInt
- private static int getThemeAttrColor(final Context context, final int attributeColor) {
- final int colorResId = getAttrResourceId(context, attributeColor);
- return ContextCompat.getColor(context, colorResId);
- }
-
- /** Returns the identifier of the resolved resource assigned to the given attribute. */
- private static int getAttrResourceId(final Context context, final int attributeColor) {
- final int[] attrs = {attributeColor};
- final TypedArray typedArray = context.obtainStyledAttributes(attrs);
- final int colorResId = typedArray.getResourceId(0, 0);
- typedArray.recycle();
- return colorResId;
- }
-
private static class TutorialPagerAdapter extends PagerAdapter {
private final List<TutorialPage> mTutorialPages;
private TutorialPagerAdapter(List<TutorialPage> tutorialPages) {
diff --git a/src/com/android/settings/accounts/AccountDashboardFragment.java b/src/com/android/settings/accounts/AccountDashboardFragment.java
index a2b6182..5456f0a 100644
--- a/src/com/android/settings/accounts/AccountDashboardFragment.java
+++ b/src/com/android/settings/accounts/AccountDashboardFragment.java
@@ -26,7 +26,6 @@
import android.os.UserManager;
import com.android.settings.R;
-import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.applications.autofill.PasswordsPreferenceController;
import com.android.settings.applications.defaultapps.DefaultAutofillPreferenceController;
import com.android.settings.applications.defaultapps.DefaultWorkAutofillPreferenceController;
@@ -96,7 +95,7 @@
}
private static void buildAccountPreferenceControllers(
- Context context, SettingsPreferenceFragment parent, String[] authorities,
+ Context context, DashboardFragment parent, String[] authorities,
List<AbstractPreferenceController> controllers) {
final AccountPreferenceController accountPrefController =
new AccountPreferenceController(context, parent, authorities,
diff --git a/src/com/android/settings/accounts/AccountPersonalDashboardFragment.java b/src/com/android/settings/accounts/AccountPersonalDashboardFragment.java
index 9ad1206..4661c64 100644
--- a/src/com/android/settings/accounts/AccountPersonalDashboardFragment.java
+++ b/src/com/android/settings/accounts/AccountPersonalDashboardFragment.java
@@ -24,7 +24,6 @@
import android.content.Context;
import com.android.settings.R;
-import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.applications.autofill.PasswordsPreferenceController;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.dashboard.profileselector.ProfileSelectFragment;
@@ -78,7 +77,7 @@
}
private static void buildAccountPreferenceControllers(
- Context context, SettingsPreferenceFragment parent, String[] authorities,
+ Context context, DashboardFragment parent, String[] authorities,
List<AbstractPreferenceController> controllers) {
final AccountPreferenceController accountPrefController =
new AccountPreferenceController(context, parent, authorities,
diff --git a/src/com/android/settings/accounts/AccountPreferenceController.java b/src/com/android/settings/accounts/AccountPreferenceController.java
index 1458988..8c717f0 100644
--- a/src/com/android/settings/accounts/AccountPreferenceController.java
+++ b/src/com/android/settings/accounts/AccountPreferenceController.java
@@ -58,10 +58,10 @@
import com.android.settings.AccessiblePreferenceCategory;
import com.android.settings.R;
-import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.Utils;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settings.core.SubSettingLauncher;
+import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.dashboard.profileselector.ProfileSelectFragment;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.RestrictedPreference;
@@ -101,7 +101,7 @@
private Preference mProfileNotAvailablePreference;
private String[] mAuthorities;
private int mAuthoritiesCount = 0;
- private SettingsPreferenceFragment mFragment;
+ private DashboardFragment mFragment;
private int mAccountProfileOrder = ORDER_ACCOUNT_PROFILES;
private AccountRestrictionHelper mHelper;
private MetricsFeatureProvider mMetricsFeatureProvider;
@@ -145,13 +145,13 @@
public ArrayMap<String, AccountTypePreference> accountPreferences = new ArrayMap<>();
}
- public AccountPreferenceController(Context context, SettingsPreferenceFragment parent,
+ public AccountPreferenceController(Context context, DashboardFragment parent,
String[] authorities, @ProfileSelectFragment.ProfileType int type) {
this(context, parent, authorities, new AccountRestrictionHelper(context), type);
}
@VisibleForTesting
- AccountPreferenceController(Context context, SettingsPreferenceFragment parent,
+ AccountPreferenceController(Context context, DashboardFragment parent,
String[] authorities, AccountRestrictionHelper helper,
@ProfileSelectFragment.ProfileType int type) {
super(context);
@@ -314,6 +314,9 @@
for (int i = 0; i < profilesCount; i++) {
updateAccountTypes(mProfiles.valueAt(i));
}
+
+ // Refresh for the auto-sync preferences
+ mFragment.forceUpdatePreferences();
}
private void updateProfileUi(final UserInfo userInfo) {
@@ -409,7 +412,6 @@
return preference;
}
-
private Preference newManagedProfileSettings() {
Preference preference = new Preference(mFragment.getPreferenceManager().getContext());
preference.setKey(PREF_KEY_WORK_PROFILE_SETTING);
diff --git a/src/com/android/settings/accounts/AccountWorkProfileDashboardFragment.java b/src/com/android/settings/accounts/AccountWorkProfileDashboardFragment.java
index 1fdd3f6..f64e041 100644
--- a/src/com/android/settings/accounts/AccountWorkProfileDashboardFragment.java
+++ b/src/com/android/settings/accounts/AccountWorkProfileDashboardFragment.java
@@ -24,7 +24,6 @@
import android.content.Context;
import com.android.settings.R;
-import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.applications.autofill.PasswordsPreferenceController;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.dashboard.profileselector.ProfileSelectFragment;
@@ -78,7 +77,7 @@
}
private static void buildAccountPreferenceControllers(
- Context context, SettingsPreferenceFragment parent, String[] authorities,
+ Context context, DashboardFragment parent, String[] authorities,
List<AbstractPreferenceController> controllers) {
final AccountPreferenceController accountPrefController =
new AccountPreferenceController(context, parent, authorities,
diff --git a/src/com/android/settings/biometrics/face/FaceSettings.java b/src/com/android/settings/biometrics/face/FaceSettings.java
index dc94376..3710528 100644
--- a/src/com/android/settings/biometrics/face/FaceSettings.java
+++ b/src/com/android/settings/biometrics/face/FaceSettings.java
@@ -203,6 +203,10 @@
if (savedInstanceState != null) {
mToken = savedInstanceState.getByteArray(KEY_TOKEN);
}
+
+ final boolean hasEnrolled = mFaceManager.hasEnrolledTemplates(mUserId);
+ mEnrollButton.setVisible(!hasEnrolled);
+ mRemoveButton.setVisible(hasEnrolled);
}
@Override
@@ -230,10 +234,6 @@
mEnrollController.setToken(mToken);
}
- final boolean hasEnrolled = mFaceManager.hasEnrolledTemplates(mUserId);
- mEnrollButton.setVisible(!hasEnrolled);
- mRemoveButton.setVisible(hasEnrolled);
-
if (!mFaceFeatureProvider.isAttentionSupported(getContext())) {
removePreference(FaceSettingsAttentionPreferenceController.KEY);
}
@@ -261,6 +261,10 @@
mEnrollController.setToken(mToken);
mConfirmingPassword = false;
});
+
+ final boolean hasEnrolled = mFaceManager.hasEnrolledTemplates(mUserId);
+ mEnrollButton.setVisible(!hasEnrolled);
+ mRemoveButton.setVisible(hasEnrolled);
}
} else if (requestCode == ENROLL_REQUEST) {
if (resultCode == RESULT_TIMEOUT) {
diff --git a/src/com/android/settings/dashboard/DashboardFragment.java b/src/com/android/settings/dashboard/DashboardFragment.java
index fb0a09d..9d1ed7c 100644
--- a/src/com/android/settings/dashboard/DashboardFragment.java
+++ b/src/com/android/settings/dashboard/DashboardFragment.java
@@ -415,6 +415,30 @@
updatePreferenceVisibility(mPreferenceControllers);
}
+ /**
+ * Force update all the preferences in this fragment.
+ */
+ public void forceUpdatePreferences() {
+ final PreferenceScreen screen = getPreferenceScreen();
+ if (screen == null || mPreferenceControllers == null) {
+ return;
+ }
+ for (List<AbstractPreferenceController> controllerList : mPreferenceControllers.values()) {
+ for (AbstractPreferenceController controller : controllerList) {
+ final String key = controller.getPreferenceKey();
+ final Preference preference = findPreference(key);
+ if (preference == null) {
+ continue;
+ }
+ final boolean available = controller.isAvailable();
+ if (available) {
+ controller.updateState(preference);
+ }
+ preference.setVisible(available);
+ }
+ }
+ }
+
@VisibleForTesting
void updatePreferenceVisibility(
Map<Class, List<AbstractPreferenceController>> preferenceControllers) {
diff --git a/src/com/android/settings/datetime/DatePreferenceController.java b/src/com/android/settings/datetime/DatePreferenceController.java
index 66026d7..50feca1 100644
--- a/src/com/android/settings/datetime/DatePreferenceController.java
+++ b/src/com/android/settings/datetime/DatePreferenceController.java
@@ -18,15 +18,16 @@
import static android.app.time.Capabilities.CAPABILITY_POSSESSED;
-import android.app.Activity;
import android.app.DatePickerDialog;
import android.app.time.TimeCapabilities;
import android.app.time.TimeManager;
import android.app.timedetector.ManualTimeSuggestion;
import android.app.timedetector.TimeDetector;
+import android.app.timedetector.TimeDetectorHelper;
import android.content.Context;
import android.text.TextUtils;
import android.text.format.DateFormat;
+import android.util.Log;
import android.widget.DatePicker;
import androidx.annotation.VisibleForTesting;
@@ -47,6 +48,7 @@
public static final int DIALOG_DATEPICKER = 0;
+ private static final String TAG = "DatePreferenceController";
private static final String KEY_DATE = "date";
private final DatePreferenceHost mHost;
@@ -96,22 +98,32 @@
mHost.updateTimeAndDateDisplay(mContext);
}
- public DatePickerDialog buildDatePicker(Activity activity) {
+ /**
+ * Builds a {@link DatePickerDialog} that can be used to request the current date from the user.
+ */
+ public DatePickerDialog buildDatePicker(
+ Context parentContext, TimeDetectorHelper timeDetectorHelper) {
final Calendar calendar = Calendar.getInstance();
- final DatePickerDialog d = new DatePickerDialog(
- activity,
+ final DatePickerDialog dialog = new DatePickerDialog(
+ parentContext,
this,
calendar.get(Calendar.YEAR),
calendar.get(Calendar.MONTH),
calendar.get(Calendar.DAY_OF_MONTH));
- // The system clock can't represent dates outside this range.
+
+ // Limit the dates the user can pick to a sensible range.
+ DatePicker datePicker = dialog.getDatePicker();
+
calendar.clear();
- calendar.set(2007, Calendar.JANUARY, 1);
- d.getDatePicker().setMinDate(calendar.getTimeInMillis());
+ int minYear = timeDetectorHelper.getManualDateSelectionYearMin();
+ calendar.set(minYear, Calendar.JANUARY, 1);
+ datePicker.setMinDate(calendar.getTimeInMillis());
+
+ int maxYear = timeDetectorHelper.getManualDateSelectionYearMax();
calendar.clear();
- calendar.set(2037, Calendar.DECEMBER, 31);
- d.getDatePicker().setMaxDate(calendar.getTimeInMillis());
- return d;
+ calendar.set(maxYear, Calendar.DECEMBER, 31);
+ datePicker.setMaxDate(calendar.getTimeInMillis());
+ return dialog;
}
@VisibleForTesting
@@ -121,13 +133,16 @@
c.set(Calendar.YEAR, year);
c.set(Calendar.MONTH, month);
c.set(Calendar.DAY_OF_MONTH, day);
- long when = Math.max(c.getTimeInMillis(), DatePreferenceHost.MIN_DATE);
+ long when = c.getTimeInMillis();
- if (when / 1000 < Integer.MAX_VALUE) {
- TimeDetector timeDetector = mContext.getSystemService(TimeDetector.class);
- ManualTimeSuggestion manualTimeSuggestion =
- TimeDetector.createManualTimeSuggestion(when, "Settings: Set date");
- timeDetector.suggestManualTime(manualTimeSuggestion);
+ TimeDetector timeDetector = mContext.getSystemService(TimeDetector.class);
+ ManualTimeSuggestion manualTimeSuggestion =
+ TimeDetector.createManualTimeSuggestion(when, "Settings: Set date");
+ boolean success = timeDetector.suggestManualTime(manualTimeSuggestion);
+ if (!success) {
+ // This implies the system server is applying tighter bounds than the settings app or
+ // the date/time cannot be set for other reasons, e.g. perhaps "auto time" is turned on.
+ Log.w(TAG, "Unable to set date with suggestion=" + manualTimeSuggestion);
}
}
diff --git a/src/com/android/settings/datetime/DateTimeSettings.java b/src/com/android/settings/datetime/DateTimeSettings.java
index 3da4234..367146b 100644
--- a/src/com/android/settings/datetime/DateTimeSettings.java
+++ b/src/com/android/settings/datetime/DateTimeSettings.java
@@ -19,6 +19,7 @@
import android.app.Activity;
import android.app.Dialog;
import android.app.settings.SettingsEnums;
+import android.app.timedetector.TimeDetectorHelper;
import android.content.Context;
import android.content.Intent;
@@ -104,7 +105,7 @@
switch (id) {
case DatePreferenceController.DIALOG_DATEPICKER:
return use(DatePreferenceController.class)
- .buildDatePicker(getActivity());
+ .buildDatePicker(getActivity(), TimeDetectorHelper.INSTANCE);
case TimePreferenceController.DIALOG_TIMEPICKER:
return use(TimePreferenceController.class)
.buildTimePicker(getActivity());
diff --git a/src/com/android/settings/datetime/TimePreferenceController.java b/src/com/android/settings/datetime/TimePreferenceController.java
index 368f1f2..09950fc 100644
--- a/src/com/android/settings/datetime/TimePreferenceController.java
+++ b/src/com/android/settings/datetime/TimePreferenceController.java
@@ -16,13 +16,13 @@
package com.android.settings.datetime;
-import android.app.Activity;
import android.app.TimePickerDialog;
import android.app.timedetector.ManualTimeSuggestion;
import android.app.timedetector.TimeDetector;
import android.content.Context;
import android.text.TextUtils;
import android.text.format.DateFormat;
+import android.util.Log;
import android.widget.TimePicker;
import androidx.preference.Preference;
@@ -42,6 +42,7 @@
public static final int DIALOG_TIMEPICKER = 1;
+ private static final String TAG = "TimePreferenceController";
private static final String KEY_TIME = "time";
private final DatePreferenceController mDatePreferenceController;
@@ -99,14 +100,17 @@
// SystemClock time.
}
- public TimePickerDialog buildTimePicker(Activity activity) {
+ /**
+ * Builds a {@link TimePickerDialog} that can be used to request the current time from the user.
+ */
+ public TimePickerDialog buildTimePicker(Context parentContext) {
final Calendar calendar = Calendar.getInstance();
return new TimePickerDialog(
- activity,
+ parentContext,
this,
calendar.get(Calendar.HOUR_OF_DAY),
calendar.get(Calendar.MINUTE),
- DateFormat.is24HourFormat(activity));
+ DateFormat.is24HourFormat(parentContext));
}
void setTime(int hourOfDay, int minute) {
@@ -116,13 +120,16 @@
c.set(Calendar.MINUTE, minute);
c.set(Calendar.SECOND, 0);
c.set(Calendar.MILLISECOND, 0);
- long when = Math.max(c.getTimeInMillis(), TimePreferenceHost.MIN_DATE);
+ long when = c.getTimeInMillis();
- if (when / 1000 < Integer.MAX_VALUE) {
- TimeDetector timeDetector = mContext.getSystemService(TimeDetector.class);
- ManualTimeSuggestion manualTimeSuggestion =
- TimeDetector.createManualTimeSuggestion(when, "Settings: Set time");
- timeDetector.suggestManualTime(manualTimeSuggestion);
+ TimeDetector timeDetector = mContext.getSystemService(TimeDetector.class);
+ ManualTimeSuggestion manualTimeSuggestion =
+ TimeDetector.createManualTimeSuggestion(when, "Settings: Set time");
+ boolean success = timeDetector.suggestManualTime(manualTimeSuggestion);
+ if (!success) {
+ // This implies the system server is applying tighter bounds than the settings app or
+ // the date/time cannot be set for other reasons, e.g. perhaps "auto time" is turned on.
+ Log.w(TAG, "Unable to set time with suggestion=" + manualTimeSuggestion);
}
}
}
diff --git a/src/com/android/settings/datetime/UpdateTimeAndDateCallback.java b/src/com/android/settings/datetime/UpdateTimeAndDateCallback.java
index 333b9aa..aa1d64e 100644
--- a/src/com/android/settings/datetime/UpdateTimeAndDateCallback.java
+++ b/src/com/android/settings/datetime/UpdateTimeAndDateCallback.java
@@ -19,8 +19,5 @@
import android.content.Context;
public interface UpdateTimeAndDateCallback {
- // Minimum time is Nov 5, 2007, 0:00.
- long MIN_DATE = 1194220800000L;
-
void updateTimeAndDateDisplay(Context context);
}
diff --git a/src/com/android/settings/deviceinfo/storage/StorageAsyncLoader.java b/src/com/android/settings/deviceinfo/storage/StorageAsyncLoader.java
index 611ee24..54935ec 100644
--- a/src/com/android/settings/deviceinfo/storage/StorageAsyncLoader.java
+++ b/src/com/android/settings/deviceinfo/storage/StorageAsyncLoader.java
@@ -85,13 +85,15 @@
for (UserInfo info : infos) {
final StorageResult result = getAppsAndGamesSize(info.id);
-
+ final Bundle media = new Bundle();
+ media.putString(ContentResolver.QUERY_ARG_SQL_SELECTION, MediaColumns.VOLUME_NAME
+ + "= '" + MediaStore.VOLUME_EXTERNAL_PRIMARY + "'");
result.imagesSize = getFilesSize(info.id, MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
- null /* queryArgs */);
+ media /* queryArgs */);
result.videosSize = getFilesSize(info.id, MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
- null /* queryArgs */);
+ media /* queryArgs */);
result.audioSize = getFilesSize(info.id, MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
- null /* queryArgs */);
+ media /* queryArgs */);
final Bundle documentsAndOtherQueryArgs = new Bundle();
documentsAndOtherQueryArgs.putString(ContentResolver.QUERY_ARG_SQL_SELECTION,
@@ -100,13 +102,14 @@
+ " AND " + FileColumns.MEDIA_TYPE + "!=" + FileColumns.MEDIA_TYPE_AUDIO
+ " AND " + FileColumns.MIME_TYPE + " IS NOT NULL");
result.documentsAndOtherSize = getFilesSize(info.id,
- MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL),
+ MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY),
documentsAndOtherQueryArgs);
final Bundle trashQueryArgs = new Bundle();
trashQueryArgs.putInt(MediaStore.QUERY_ARG_MATCH_TRASHED, MediaStore.MATCH_ONLY);
result.trashSize = getFilesSize(info.id,
- MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL), trashQueryArgs);
+ MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY),
+ trashQueryArgs);
results.put(info.id, result);
}
diff --git a/src/com/android/settings/fuelgauge/OptimizedPreferenceController.java b/src/com/android/settings/fuelgauge/OptimizedPreferenceController.java
index 708ba5e..88241b6 100644
--- a/src/com/android/settings/fuelgauge/OptimizedPreferenceController.java
+++ b/src/com/android/settings/fuelgauge/OptimizedPreferenceController.java
@@ -53,16 +53,16 @@
return;
}
- if (mBatteryOptimizeUtils.isSystemOrDefaultApp()) {
- Log.d(TAG, "is system or default app, disable pref");
- ((SelectorWithWidgetPreference) preference).setChecked(false);
- preference.setEnabled(false);
- } else if (mBatteryOptimizeUtils.getAppOptimizationMode()
+ if (mBatteryOptimizeUtils.getAppOptimizationMode()
== BatteryOptimizeUtils.MODE_OPTIMIZED) {
Log.d(TAG, "is optimized states");
((SelectorWithWidgetPreference) preference).setChecked(true);
} else {
((SelectorWithWidgetPreference) preference).setChecked(false);
+ if (mBatteryOptimizeUtils.isSystemOrDefaultApp()) {
+ Log.d(TAG, "is system or default app, disable pref");
+ preference.setEnabled(false);
+ }
}
}
diff --git a/src/com/android/settings/fuelgauge/RestrictedPreferenceController.java b/src/com/android/settings/fuelgauge/RestrictedPreferenceController.java
index 99e742b..fe896a6 100644
--- a/src/com/android/settings/fuelgauge/RestrictedPreferenceController.java
+++ b/src/com/android/settings/fuelgauge/RestrictedPreferenceController.java
@@ -51,16 +51,16 @@
preference.setEnabled(true);
}
- if (mBatteryOptimizeUtils.isSystemOrDefaultApp()) {
- Log.d(TAG, "is system or default app, disable pref");
- ((SelectorWithWidgetPreference) preference).setChecked(false);
- preference.setEnabled(false);
- } else if (mBatteryOptimizeUtils.getAppOptimizationMode()
+ if (mBatteryOptimizeUtils.getAppOptimizationMode()
== BatteryOptimizeUtils.MODE_RESTRICTED) {
Log.d(TAG, "is restricted states");
((SelectorWithWidgetPreference) preference).setChecked(true);
} else {
((SelectorWithWidgetPreference) preference).setChecked(false);
+ if (mBatteryOptimizeUtils.isSystemOrDefaultApp()) {
+ Log.d(TAG, "is system or default app, disable pref");
+ preference.setEnabled(false);
+ }
}
}
diff --git a/src/com/android/settings/fuelgauge/UnrestrictedPreferenceController.java b/src/com/android/settings/fuelgauge/UnrestrictedPreferenceController.java
index 244a33c..be4091c 100644
--- a/src/com/android/settings/fuelgauge/UnrestrictedPreferenceController.java
+++ b/src/com/android/settings/fuelgauge/UnrestrictedPreferenceController.java
@@ -50,15 +50,16 @@
preference.setEnabled(true);
}
- if (mBatteryOptimizeUtils.isSystemOrDefaultApp()) {
- Log.d(TAG, "is system or default app, unrestricted states only");
- ((SelectorWithWidgetPreference) preference).setChecked(true);
- } else if (mBatteryOptimizeUtils.getAppOptimizationMode()
+ if (mBatteryOptimizeUtils.getAppOptimizationMode()
== BatteryOptimizeUtils.MODE_UNRESTRICTED) {
Log.d(TAG, "is unrestricted states");
((SelectorWithWidgetPreference) preference).setChecked(true);
} else {
((SelectorWithWidgetPreference) preference).setChecked(false);
+ if (mBatteryOptimizeUtils.isSystemOrDefaultApp()) {
+ Log.d(TAG, "is system or default app, disable pref");
+ preference.setEnabled(false);
+ }
}
}
diff --git a/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceControllerV2.java b/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceControllerV2.java
index dc80b84..d549101 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceControllerV2.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceControllerV2.java
@@ -347,6 +347,7 @@
trapezoidIndex, mBatteryIndexedMap.size(), isForce));
mTrapezoidIndex = trapezoidIndex;
+ mBatteryChartView.setSelectedIndex(mTrapezoidIndex);
mHandler.post(() -> {
final long start = System.currentTimeMillis();
removeAndCacheAllPrefs();
diff --git a/src/com/android/settings/fuelgauge/batteryusage/BatteryChartViewV2.java b/src/com/android/settings/fuelgauge/batteryusage/BatteryChartViewV2.java
index 9b6abb0..15a3ca6 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/BatteryChartViewV2.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/BatteryChartViewV2.java
@@ -56,7 +56,6 @@
private static final List<String> ACCESSIBILITY_SERVICE_NAMES =
Arrays.asList("SwitchAccessService", "TalkBackService", "JustSpeakService");
- private static final int DEFAULT_TRAPEZOID_COUNT = 12;
private static final int DEFAULT_AXIS_LABEL_COUNT = 4;
private static final int AXIS_LABEL_GAPS_COUNT = DEFAULT_AXIS_LABEL_COUNT - 1;
private static final int DIVIDER_COLOR = Color.parseColor("#CDCCC5");
@@ -74,7 +73,6 @@
private int mDividerWidth;
private int mDividerHeight;
- private int mTrapezoidCount;
private float mTrapezoidVOffset;
private float mTrapezoidHOffset;
private boolean mIsSlotsClickabled;
@@ -112,9 +110,11 @@
@VisibleForTesting
Paint mTrapezoidCurvePaint = null;
- private TrapezoidSlot[] mTrapezoidSlots;
+ @VisibleForTesting
+ TrapezoidSlot[] mTrapezoidSlots;
// Records the location to calculate selected index.
- private float mTouchUpEventX = Float.MIN_VALUE;
+ @VisibleForTesting
+ float mTouchUpEventX = Float.MIN_VALUE;
private BatteryChartViewV2.OnSelectListener mOnSelectListener;
public BatteryChartViewV2(Context context) {
@@ -127,36 +127,28 @@
// Registers the click event listener.
setOnClickListener(this);
setSelectedIndex(SELECTED_INDEX_ALL);
- setTrapezoidCount(DEFAULT_TRAPEZOID_COUNT);
setClickable(false);
}
- /** Sets the total trapezoid count for drawing. */
- public void setTrapezoidCount(int trapezoidCount) {
- Log.i(TAG, "trapezoidCount:" + trapezoidCount);
- mTrapezoidCount = trapezoidCount;
- mTrapezoidSlots = new TrapezoidSlot[trapezoidCount];
- // Allocates the trapezoid slot array.
- for (int index = 0; index < trapezoidCount; index++) {
- mTrapezoidSlots[index] = new TrapezoidSlot();
- }
- invalidate();
- }
-
/** Sets all levels value to draw the trapezoid shape */
public void setLevels(int[] levels) {
Log.d(TAG, "setLevels() " + (levels == null ? "null" : levels.length));
- if (levels == null) {
+ // At least 2 levels to draw a trapezoid.
+ if (levels == null || levels.length < 2) {
mLevels = null;
+ invalidate();
return;
}
- // We should provide trapezoid count + 1 data to draw all trapezoids.
- mLevels = levels.length == mTrapezoidCount + 1 ? levels : null;
+ mLevels = levels;
+
+ // Initialize trapezoid slots.
+ mTrapezoidSlots = new TrapezoidSlot[mLevels.length - 1];
+ for (int index = 0; index < mTrapezoidSlots.length; index++) {
+ mTrapezoidSlots[index] = new TrapezoidSlot();
+ }
+
setClickable(false);
invalidate();
- if (mLevels == null) {
- return;
- }
// Sets the chart is clickable if there is at least one valid item in it.
for (int index = 0; index < mLevels.length - 1; index++) {
if (mLevels[index] != 0 && mLevels[index + 1] != 0) {
@@ -171,10 +163,6 @@
if (mSelectedIndex != index) {
mSelectedIndex = index;
invalidate();
- // Callbacks to the listener if we have.
- if (mOnSelectListener != null) {
- mOnSelectListener.onSelect(mSelectedIndex);
- }
}
}
@@ -249,7 +237,12 @@
@Override
public void draw(Canvas canvas) {
super.draw(canvas);
+ // Before mLevels initialized, the count of trapezoids is unknown. Only draws the
+ // horizontal percentages and dividers.
drawHorizontalDividers(canvas);
+ if (mLevels == null) {
+ return;
+ }
drawVerticalDividers(canvas);
drawTrapezoids(canvas);
}
@@ -306,11 +299,9 @@
|| !isValidToDraw(trapezoidIndex)) {
return;
}
- // Selects all if users click the same trapezoid item two times.
- if (trapezoidIndex == mSelectedIndex) {
- setSelectedIndex(SELECTED_INDEX_ALL);
- } else {
- setSelectedIndex(trapezoidIndex);
+ if (mOnSelectListener != null) {
+ mOnSelectListener.onSelect(
+ trapezoidIndex == mSelectedIndex ? SELECTED_INDEX_ALL : trapezoidIndex);
}
view.performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK);
}
@@ -440,9 +431,9 @@
private void drawVerticalDividers(Canvas canvas) {
final int width = getWidth() - mIndent.right;
- final int dividerCount = mTrapezoidCount + 1;
+ final int dividerCount = mTrapezoidSlots.length + 1;
final float dividerSpace = dividerCount * mDividerWidth;
- final float unitWidth = (width - dividerSpace) / (float) mTrapezoidCount;
+ final float unitWidth = (width - dividerSpace) / (float) mTrapezoidSlots.length;
final float bottomY = getHeight() - mIndent.bottom;
final float startY = bottomY - mDividerHeight;
final float trapezoidSlotOffset = mTrapezoidHOffset + mDividerWidth * .5f;
@@ -518,7 +509,7 @@
// Draws all trapezoid shapes into the canvas.
final Path trapezoidPath = new Path();
Path trapezoidCurvePath = null;
- for (int index = 0; index < mTrapezoidCount; index++) {
+ for (int index = 0; index < mTrapezoidSlots.length; index++) {
// Not draws the trapezoid for corner or not initialization cases.
if (!isValidToDraw(index)) {
if (mTrapezoidCurvePaint != null && trapezoidCurvePath != null) {
@@ -619,7 +610,8 @@
}
// A container class for each trapezoid left and right location.
- private static final class TrapezoidSlot {
+ @VisibleForTesting
+ static final class TrapezoidSlot {
public float mLeft;
public float mRight;
diff --git a/src/com/android/settings/fuelgauge/batteryusage/BatteryDiffData.java b/src/com/android/settings/fuelgauge/batteryusage/BatteryDiffData.java
new file mode 100644
index 0000000..5743cac
--- /dev/null
+++ b/src/com/android/settings/fuelgauge/batteryusage/BatteryDiffData.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2022 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 java.util.ArrayList;
+import java.util.List;
+
+/** Wraps the battery usage diff data for each entry used for battery usage app list. */
+public class BatteryDiffData {
+ private final List<BatteryDiffEntry> mAppEntries;
+ private final List<BatteryDiffEntry> mSystemEntries;
+
+ public BatteryDiffData(
+ List<BatteryDiffEntry> appDiffEntries, List<BatteryDiffEntry> systemDiffEntries) {
+ mAppEntries = appDiffEntries == null ? new ArrayList<>() : appDiffEntries;
+ mSystemEntries = systemDiffEntries == null ? new ArrayList<>() : systemDiffEntries;
+ }
+
+ public List<BatteryDiffEntry> getAppDiffEntryList() {
+ return mAppEntries;
+ }
+
+ public List<BatteryDiffEntry> getSystemDiffEntryList() {
+ return mSystemEntries;
+ }
+
+ /** Sets total consume power for each entry. */
+ public void setTotalConsumePowerForAllEntries(double totalConsumePower) {
+ mAppEntries.forEach(diffEntry -> diffEntry.setTotalConsumePower(totalConsumePower));
+ mSystemEntries.forEach(diffEntry -> diffEntry.setTotalConsumePower(totalConsumePower));
+ }
+}
diff --git a/src/com/android/settings/notification/AppBubbleListPreferenceController.java b/src/com/android/settings/notification/AppBubbleListPreferenceController.java
index bf7fcc0..6ebb376 100644
--- a/src/com/android/settings/notification/AppBubbleListPreferenceController.java
+++ b/src/com/android/settings/notification/AppBubbleListPreferenceController.java
@@ -51,7 +51,7 @@
private static final String KEY = "bubble_conversations";
public AppBubbleListPreferenceController(Context context, NotificationBackend backend) {
- super(context, backend);
+ super(context, backend, KEY);
}
@Override
@@ -80,25 +80,25 @@
}
@Override
- public boolean isAvailable() {
+ public int getAvailabilityStatus() {
// copy rather than inherit super's isAvailable because apps can link to this page
// as part of onboarding, before they send a valid conversation notification
if (mAppRow == null) {
- return false;
+ return CONDITIONALLY_UNAVAILABLE;
}
if (mAppRow.banned) {
- return false;
+ return CONDITIONALLY_UNAVAILABLE;
}
if (mChannel != null) {
if (mBackend.onlyHasDefaultChannel(mAppRow.pkg, mAppRow.uid)
|| NotificationChannel.DEFAULT_CHANNEL_ID.equals(mChannel.getId())) {
- return false;
+ return CONDITIONALLY_UNAVAILABLE;
}
}
if (mAppRow.bubblePreference == BUBBLE_PREFERENCE_NONE) {
- return false;
+ return CONDITIONALLY_UNAVAILABLE;
}
- return true;
+ return AVAILABLE;
}
@VisibleForTesting
diff --git a/src/com/android/settings/notification/app/AddToHomeScreenPreferenceController.java b/src/com/android/settings/notification/app/AddToHomeScreenPreferenceController.java
index e5afd9d..12b8075 100644
--- a/src/com/android/settings/notification/app/AddToHomeScreenPreferenceController.java
+++ b/src/com/android/settings/notification/app/AddToHomeScreenPreferenceController.java
@@ -32,7 +32,7 @@
private static final String KEY = "add_to_home";
public AddToHomeScreenPreferenceController(Context context, NotificationBackend backend) {
- super(context, backend);
+ super(context, backend, KEY);
}
@Override
@@ -41,11 +41,11 @@
}
@Override
- public boolean isAvailable() {
- if (!super.isAvailable()) {
- return false;
+ public int getAvailabilityStatus() {
+ if (super.getAvailabilityStatus() == CONDITIONALLY_UNAVAILABLE) {
+ return CONDITIONALLY_UNAVAILABLE;
}
- return mConversationInfo != null;
+ return mConversationInfo != null ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
}
@Override
diff --git a/src/com/android/settings/notification/app/AllowSoundPreferenceController.java b/src/com/android/settings/notification/app/AllowSoundPreferenceController.java
index 0664c54..99d0873 100644
--- a/src/com/android/settings/notification/app/AllowSoundPreferenceController.java
+++ b/src/com/android/settings/notification/app/AllowSoundPreferenceController.java
@@ -40,7 +40,7 @@
public AllowSoundPreferenceController(Context context,
NotificationSettings.DependentFieldListener dependentFieldListener,
NotificationBackend backend) {
- super(context, backend);
+ super(context, backend, KEY_IMPORTANCE);
mDependentFieldListener = dependentFieldListener;
}
@@ -50,11 +50,14 @@
}
@Override
- public boolean isAvailable() {
- if (!super.isAvailable()) {
- return false;
+ public int getAvailabilityStatus() {
+ if (super.getAvailabilityStatus() == CONDITIONALLY_UNAVAILABLE) {
+ return CONDITIONALLY_UNAVAILABLE;
}
- return mChannel != null && NotificationChannel.DEFAULT_CHANNEL_ID.equals(mChannel.getId());
+ if (mChannel != null && NotificationChannel.DEFAULT_CHANNEL_ID.equals(mChannel.getId())) {
+ return AVAILABLE;
+ }
+ return CONDITIONALLY_UNAVAILABLE;
}
diff --git a/src/com/android/settings/notification/app/AppChannelsBypassingDndPreferenceController.java b/src/com/android/settings/notification/app/AppChannelsBypassingDndPreferenceController.java
index 92cd911..6c2c0c3 100644
--- a/src/com/android/settings/notification/app/AppChannelsBypassingDndPreferenceController.java
+++ b/src/com/android/settings/notification/app/AppChannelsBypassingDndPreferenceController.java
@@ -64,7 +64,7 @@
public AppChannelsBypassingDndPreferenceController(
Context context,
NotificationBackend backend) {
- super(context, backend);
+ super(context, backend, KEY);
}
@Override
@@ -110,8 +110,8 @@
}
@Override
- public boolean isAvailable() {
- return mAppRow != null;
+ public int getAvailabilityStatus() {
+ return mAppRow != null ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
}
@Override
diff --git a/src/com/android/settings/notification/app/AppConversationListPreferenceController.java b/src/com/android/settings/notification/app/AppConversationListPreferenceController.java
index dd44a13..e7b2378 100644
--- a/src/com/android/settings/notification/app/AppConversationListPreferenceController.java
+++ b/src/com/android/settings/notification/app/AppConversationListPreferenceController.java
@@ -49,7 +49,12 @@
protected PreferenceCategory mPreference;
public AppConversationListPreferenceController(Context context, NotificationBackend backend) {
- super(context, backend);
+ this(context, backend, KEY);
+ }
+
+ public AppConversationListPreferenceController(Context context, NotificationBackend backend,
+ String key) {
+ super(context, backend, key);
}
@Override
@@ -58,21 +63,24 @@
}
@Override
- public boolean isAvailable() {
+ public int getAvailabilityStatus() {
if (mAppRow == null) {
- return false;
+ return CONDITIONALLY_UNAVAILABLE;
}
if (mAppRow.banned) {
- return false;
+ return CONDITIONALLY_UNAVAILABLE;
}
if (mChannel != null) {
if (mBackend.onlyHasDefaultChannel(mAppRow.pkg, mAppRow.uid)
|| NotificationChannel.DEFAULT_CHANNEL_ID.equals(mChannel.getId())) {
- return false;
+ return CONDITIONALLY_UNAVAILABLE;
}
}
- return mBackend.hasSentValidMsg(mAppRow.pkg, mAppRow.uid) || mBackend.isInInvalidMsgState(
- mAppRow.pkg, mAppRow.uid);
+ if (mBackend.hasSentValidMsg(mAppRow.pkg, mAppRow.uid) || mBackend.isInInvalidMsgState(
+ mAppRow.pkg, mAppRow.uid)) {
+ return AVAILABLE;
+ }
+ return CONDITIONALLY_UNAVAILABLE;
}
@Override
diff --git a/src/com/android/settings/notification/app/AppLinkPreferenceController.java b/src/com/android/settings/notification/app/AppLinkPreferenceController.java
index 043ae69..ecf9670 100644
--- a/src/com/android/settings/notification/app/AppLinkPreferenceController.java
+++ b/src/com/android/settings/notification/app/AppLinkPreferenceController.java
@@ -32,7 +32,7 @@
private static final String KEY_APP_LINK = "app_link";
public AppLinkPreferenceController(Context context) {
- super(context, null);
+ super(context, null, KEY_APP_LINK);
}
@Override
@@ -41,11 +41,11 @@
}
@Override
- public boolean isAvailable() {
- if (!super.isAvailable()) {
- return false;
+ public int getAvailabilityStatus() {
+ if (super.getAvailabilityStatus() == CONDITIONALLY_UNAVAILABLE) {
+ return CONDITIONALLY_UNAVAILABLE;
}
- return mAppRow.settingsIntent != null;
+ return mAppRow.settingsIntent != null ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
}
@Override
diff --git a/src/com/android/settings/notification/app/BadgePreferenceController.java b/src/com/android/settings/notification/app/BadgePreferenceController.java
index 108fa1d..f94dfb5 100644
--- a/src/com/android/settings/notification/app/BadgePreferenceController.java
+++ b/src/com/android/settings/notification/app/BadgePreferenceController.java
@@ -38,7 +38,7 @@
public BadgePreferenceController(Context context,
NotificationBackend backend) {
- super(context, backend);
+ super(context, backend, KEY_BADGE);
}
@Override
@@ -47,25 +47,29 @@
}
@Override
- public boolean isAvailable() {
- if (!super.isAvailable()) {
- return false;
+ public int getAvailabilityStatus() {
+ if (super.getAvailabilityStatus() == CONDITIONALLY_UNAVAILABLE) {
+ return CONDITIONALLY_UNAVAILABLE;
}
if (mAppRow == null && mChannel == null) {
- return false;
+ return CONDITIONALLY_UNAVAILABLE;
}
if (Settings.Secure.getInt(mContext.getContentResolver(),
NOTIFICATION_BADGING, SYSTEM_WIDE_ON) == SYSTEM_WIDE_OFF) {
- return false;
+ return CONDITIONALLY_UNAVAILABLE;
}
if (mChannel != null) {
if (isDefaultChannel()) {
- return true;
+ return AVAILABLE;
} else {
- return mAppRow == null ? false : mAppRow.showBadge;
+ return mAppRow == null
+ ? CONDITIONALLY_UNAVAILABLE
+ : mAppRow.showBadge
+ ? AVAILABLE
+ : CONDITIONALLY_UNAVAILABLE;
}
}
- return true;
+ return AVAILABLE;
}
@Override
diff --git a/src/com/android/settings/notification/app/BlockPreferenceController.java b/src/com/android/settings/notification/app/BlockPreferenceController.java
index f4e2132..ea3eaeb 100644
--- a/src/com/android/settings/notification/app/BlockPreferenceController.java
+++ b/src/com/android/settings/notification/app/BlockPreferenceController.java
@@ -42,7 +42,7 @@
public BlockPreferenceController(Context context,
NotificationSettings.DependentFieldListener dependentFieldListener,
NotificationBackend backend) {
- super(context, backend);
+ super(context, backend, KEY_BLOCK);
mDependentFieldListener = dependentFieldListener;
}
@@ -52,14 +52,14 @@
}
@Override
- public boolean isAvailable() {
+ public int getAvailabilityStatus() {
if (mAppRow == null) {
- return false;
+ return CONDITIONALLY_UNAVAILABLE;
}
if (mPreferenceFilter != null && !isIncludedInFilter()) {
- return false;
+ return CONDITIONALLY_UNAVAILABLE;
}
- return true;
+ return AVAILABLE;
}
@Override
diff --git a/src/com/android/settings/notification/app/BubbleCategoryPreferenceController.java b/src/com/android/settings/notification/app/BubbleCategoryPreferenceController.java
index ad3a10c..da67afe 100644
--- a/src/com/android/settings/notification/app/BubbleCategoryPreferenceController.java
+++ b/src/com/android/settings/notification/app/BubbleCategoryPreferenceController.java
@@ -32,15 +32,15 @@
static final int ON = 1;
public BubbleCategoryPreferenceController(Context context) {
- super(context, null);
+ super(context, null, KEY);
}
@Override
- public boolean isAvailable() {
- if (!super.isAvailable()) {
- return false;
+ public int getAvailabilityStatus() {
+ if (super.getAvailabilityStatus() == CONDITIONALLY_UNAVAILABLE) {
+ return CONDITIONALLY_UNAVAILABLE;
}
- return areBubblesEnabled();
+ return areBubblesEnabled() ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
}
@Override
diff --git a/src/com/android/settings/notification/app/BubbleLinkPreferenceController.java b/src/com/android/settings/notification/app/BubbleLinkPreferenceController.java
index 0b9529b..ed1c9b5 100644
--- a/src/com/android/settings/notification/app/BubbleLinkPreferenceController.java
+++ b/src/com/android/settings/notification/app/BubbleLinkPreferenceController.java
@@ -32,15 +32,15 @@
static final int ON = 1;
public BubbleLinkPreferenceController(Context context) {
- super(context, null);
+ super(context, null, KEY);
}
@Override
- public boolean isAvailable() {
- if (!super.isAvailable()) {
- return false;
+ public int getAvailabilityStatus() {
+ if (super.getAvailabilityStatus() == CONDITIONALLY_UNAVAILABLE) {
+ return CONDITIONALLY_UNAVAILABLE;
}
- return areBubblesEnabled();
+ return areBubblesEnabled() ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
}
@Override
diff --git a/src/com/android/settings/notification/app/BubblePreferenceController.java b/src/com/android/settings/notification/app/BubblePreferenceController.java
index 351b463..516a45e 100644
--- a/src/com/android/settings/notification/app/BubblePreferenceController.java
+++ b/src/com/android/settings/notification/app/BubblePreferenceController.java
@@ -56,7 +56,7 @@
public BubblePreferenceController(Context context, @Nullable FragmentManager fragmentManager,
NotificationBackend backend, boolean isAppPage,
@Nullable NotificationSettings.DependentFieldListener listener) {
- super(context, backend);
+ super(context, backend, KEY);
mFragmentManager = fragmentManager;
mIsAppPage = isAppPage;
mListener = listener;
@@ -68,21 +68,24 @@
}
@Override
- public boolean isAvailable() {
- if (!super.isAvailable()) {
- return false;
+ public int getAvailabilityStatus() {
+ if (super.getAvailabilityStatus() == CONDITIONALLY_UNAVAILABLE) {
+ return CONDITIONALLY_UNAVAILABLE;
}
if (!mIsAppPage && !isEnabled()) {
- return false;
+ return CONDITIONALLY_UNAVAILABLE;
}
if (mChannel != null) {
if (isDefaultChannel()) {
- return true;
+ return AVAILABLE;
} else {
- return mAppRow != null && mAppRow.bubblePreference != BUBBLE_PREFERENCE_NONE;
+ if (mAppRow != null && mAppRow.bubblePreference != BUBBLE_PREFERENCE_NONE) {
+ return AVAILABLE;
+ }
+ return CONDITIONALLY_UNAVAILABLE;
}
}
- return true;
+ return AVAILABLE;
}
@Override
diff --git a/src/com/android/settings/notification/app/BubbleSummaryPreferenceController.java b/src/com/android/settings/notification/app/BubbleSummaryPreferenceController.java
index 51370b1..abbe89e 100644
--- a/src/com/android/settings/notification/app/BubbleSummaryPreferenceController.java
+++ b/src/com/android/settings/notification/app/BubbleSummaryPreferenceController.java
@@ -42,28 +42,31 @@
static final int ON = 1;
public BubbleSummaryPreferenceController(Context context, NotificationBackend backend) {
- super(context, backend);
+ super(context, backend, KEY);
}
@Override
- public boolean isAvailable() {
- if (!super.isAvailable()) {
- return false;
+ public int getAvailabilityStatus() {
+ if (super.getAvailabilityStatus() == CONDITIONALLY_UNAVAILABLE) {
+ return CONDITIONALLY_UNAVAILABLE;
}
if (mAppRow == null) {
- return false;
+ return CONDITIONALLY_UNAVAILABLE;
}
if (mChannel != null) {
if (!isGloballyEnabled()) {
- return false;
+ return CONDITIONALLY_UNAVAILABLE;
}
if (isDefaultChannel()) {
- return true;
+ return AVAILABLE;
} else {
- return mAppRow != null;
+ return mAppRow != null ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
}
}
- return isGloballyEnabled() && mBackend.hasSentValidBubble(mAppRow.pkg, mAppRow.uid);
+ if (isGloballyEnabled() && mBackend.hasSentValidBubble(mAppRow.pkg, mAppRow.uid)) {
+ return AVAILABLE;
+ }
+ return CONDITIONALLY_UNAVAILABLE;
}
@Override
diff --git a/src/com/android/settings/notification/app/ChannelListPreferenceController.java b/src/com/android/settings/notification/app/ChannelListPreferenceController.java
index 8db3b21..8d07911 100644
--- a/src/com/android/settings/notification/app/ChannelListPreferenceController.java
+++ b/src/com/android/settings/notification/app/ChannelListPreferenceController.java
@@ -28,6 +28,7 @@
import android.os.Bundle;
import android.provider.Settings;
import android.text.TextUtils;
+import android.util.Slog;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -39,16 +40,19 @@
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.applications.AppInfoBase;
+import com.android.settings.core.BasePreferenceController;
import com.android.settings.core.SubSettingLauncher;
import com.android.settings.notification.NotificationBackend;
import com.android.settingslib.PrimarySwitchPreference;
import com.android.settingslib.RestrictedSwitchPreference;
+import com.android.settingslib.utils.ThreadUtils;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
-public class ChannelListPreferenceController extends NotificationPreferenceController {
+public class ChannelListPreferenceController extends NotificationPreferenceController
+ implements BasePreferenceController.UiBlocker {
private static final String KEY = "channels";
private static final String KEY_GENERAL_CATEGORY = "categories";
@@ -59,7 +63,7 @@
private PreferenceCategory mPreference;
public ChannelListPreferenceController(Context context, NotificationBackend backend) {
- super(context, backend);
+ super(context, backend, KEY);
}
@Override
@@ -68,20 +72,20 @@
}
@Override
- public boolean isAvailable() {
+ public int getAvailabilityStatus() {
if (mAppRow == null) {
- return false;
+ return CONDITIONALLY_UNAVAILABLE;
}
if (mAppRow.banned) {
- return false;
+ return CONDITIONALLY_UNAVAILABLE;
}
if (mChannel != null) {
if (mBackend.onlyHasDefaultChannel(mAppRow.pkg, mAppRow.uid)
|| NotificationChannel.DEFAULT_CHANNEL_ID.equals(mChannel.getId())) {
- return false;
+ return CONDITIONALLY_UNAVAILABLE;
}
}
- return true;
+ return AVAILABLE;
}
@Override
@@ -91,24 +95,17 @@
@Override
public void updateState(Preference preference) {
- mPreference = (PreferenceCategory) preference;
- // Load channel settings
- new AsyncTask<Void, Void, Void>() {
- @Override
- protected Void doInBackground(Void... unused) {
+ mPreference = (PreferenceCategory) preference;
+ // Load channel settings
+ ThreadUtils.postOnBackgroundThread(() -> {
mChannelGroupList = mBackend.getGroups(mAppRow.pkg, mAppRow.uid).getList();
Collections.sort(mChannelGroupList, CHANNEL_GROUP_COMPARATOR);
- return null;
- }
-
- @Override
- protected void onPostExecute(Void unused) {
- if (mContext == null) {
- return;
- }
+ ThreadUtils.getUiThreadHandler().getLooper().prepare();
updateFullList(mPreference, mChannelGroupList);
- }
- }.execute();
+ ThreadUtils.postOnMainThread(() -> {
+ showPreferences();
+ });
+ });
}
/**
@@ -144,6 +141,12 @@
}
}
+ private void showPreferences() {
+ if (mUiBlockListener != null) {
+ mUiBlockListener.onBlockerWorkFinished(this);
+ }
+ }
+
/**
* Looks for the category for the given group's key at the expected index, if that doesn't
* match, it checks all groups, and if it can't find that group anywhere, it creates it.
diff --git a/src/com/android/settings/notification/app/ConversationDemotePreferenceController.java b/src/com/android/settings/notification/app/ConversationDemotePreferenceController.java
index 02f639c..ba7ca35 100644
--- a/src/com/android/settings/notification/app/ConversationDemotePreferenceController.java
+++ b/src/com/android/settings/notification/app/ConversationDemotePreferenceController.java
@@ -37,7 +37,7 @@
public ConversationDemotePreferenceController(Context context,
SettingsPreferenceFragment hostFragment,
NotificationBackend backend) {
- super(context, backend);
+ super(context, backend, KEY);
mHostFragment = hostFragment;
}
@@ -47,14 +47,17 @@
}
@Override
- public boolean isAvailable() {
- if (!super.isAvailable()) {
- return false;
+ public int getAvailabilityStatus() {
+ if (super.getAvailabilityStatus() == CONDITIONALLY_UNAVAILABLE) {
+ return CONDITIONALLY_UNAVAILABLE;
}
if (mAppRow == null || mChannel == null) {
- return false;
+ return CONDITIONALLY_UNAVAILABLE;
}
- return !TextUtils.isEmpty(mChannel.getConversationId()) && !mChannel.isDemoted();
+ if (!TextUtils.isEmpty(mChannel.getConversationId()) && !mChannel.isDemoted()) {
+ return AVAILABLE;
+ }
+ return CONDITIONALLY_UNAVAILABLE;
}
@Override
diff --git a/src/com/android/settings/notification/app/ConversationHeaderPreferenceController.java b/src/com/android/settings/notification/app/ConversationHeaderPreferenceController.java
index f99a56a..56de88b 100644
--- a/src/com/android/settings/notification/app/ConversationHeaderPreferenceController.java
+++ b/src/com/android/settings/notification/app/ConversationHeaderPreferenceController.java
@@ -45,7 +45,7 @@
private boolean mStarted = false;
public ConversationHeaderPreferenceController(Context context, DashboardFragment fragment) {
- super(context, null);
+ super(context, null, PREF_KEY_APP_HEADER);
mFragment = fragment;
}
@@ -55,8 +55,8 @@
}
@Override
- public boolean isAvailable() {
- return mAppRow != null;
+ public int getAvailabilityStatus() {
+ return mAppRow != null ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
}
@Override
diff --git a/src/com/android/settings/notification/app/ConversationPriorityPreferenceController.java b/src/com/android/settings/notification/app/ConversationPriorityPreferenceController.java
index ae16928..46bc3c0 100644
--- a/src/com/android/settings/notification/app/ConversationPriorityPreferenceController.java
+++ b/src/com/android/settings/notification/app/ConversationPriorityPreferenceController.java
@@ -34,7 +34,7 @@
public ConversationPriorityPreferenceController(Context context,
NotificationBackend backend, NotificationSettings.DependentFieldListener listener) {
- super(context, backend);
+ super(context, backend, KEY);
mDependentFieldListener = listener;
}
@@ -44,14 +44,14 @@
}
@Override
- public boolean isAvailable() {
- if (!super.isAvailable()) {
- return false;
+ public int getAvailabilityStatus() {
+ if (super.getAvailabilityStatus() == CONDITIONALLY_UNAVAILABLE) {
+ return CONDITIONALLY_UNAVAILABLE;
}
if (mAppRow == null || mChannel == null) {
- return false;
+ return CONDITIONALLY_UNAVAILABLE;
}
- return true;
+ return AVAILABLE;
}
@Override
diff --git a/src/com/android/settings/notification/app/ConversationPromotePreferenceController.java b/src/com/android/settings/notification/app/ConversationPromotePreferenceController.java
index 24c3d2f..a5ef569 100644
--- a/src/com/android/settings/notification/app/ConversationPromotePreferenceController.java
+++ b/src/com/android/settings/notification/app/ConversationPromotePreferenceController.java
@@ -37,7 +37,7 @@
public ConversationPromotePreferenceController(Context context,
SettingsPreferenceFragment hostFragment,
NotificationBackend backend) {
- super(context, backend);
+ super(context, backend, KEY);
mHostFragment = hostFragment;
}
@@ -47,14 +47,17 @@
}
@Override
- public boolean isAvailable() {
- if (!super.isAvailable()) {
- return false;
+ public int getAvailabilityStatus() {
+ if (super.getAvailabilityStatus() == CONDITIONALLY_UNAVAILABLE) {
+ return CONDITIONALLY_UNAVAILABLE;
}
if (mAppRow == null || mChannel == null) {
- return false;
+ return CONDITIONALLY_UNAVAILABLE;
}
- return !TextUtils.isEmpty(mChannel.getConversationId()) && mChannel.isDemoted();
+ if (!TextUtils.isEmpty(mChannel.getConversationId()) && mChannel.isDemoted()) {
+ return AVAILABLE;
+ }
+ return CONDITIONALLY_UNAVAILABLE;
}
@Override
diff --git a/src/com/android/settings/notification/app/DeletedChannelsPreferenceController.java b/src/com/android/settings/notification/app/DeletedChannelsPreferenceController.java
index 77a692f..cd160df 100644
--- a/src/com/android/settings/notification/app/DeletedChannelsPreferenceController.java
+++ b/src/com/android/settings/notification/app/DeletedChannelsPreferenceController.java
@@ -30,7 +30,7 @@
private static final String KEY_DELETED = "deleted";
public DeletedChannelsPreferenceController(Context context, NotificationBackend backend) {
- super(context, backend);
+ super(context, backend, KEY_DELETED);
}
@Override
@@ -39,16 +39,19 @@
}
@Override
- public boolean isAvailable() {
- if (!super.isAvailable()) {
- return false;
+ public int getAvailabilityStatus() {
+ if (super.getAvailabilityStatus() == CONDITIONALLY_UNAVAILABLE) {
+ return CONDITIONALLY_UNAVAILABLE;
}
// only visible on app screen
if (mChannel != null || hasValidGroup()) {
- return false;
+ return CONDITIONALLY_UNAVAILABLE;
}
- return mBackend.getDeletedChannelCount(mAppRow.pkg, mAppRow.uid) > 0;
+ if (mBackend.getDeletedChannelCount(mAppRow.pkg, mAppRow.uid) > 0) {
+ return AVAILABLE;
+ }
+ return CONDITIONALLY_UNAVAILABLE;
}
@Override
diff --git a/src/com/android/settings/notification/app/DescriptionPreferenceController.java b/src/com/android/settings/notification/app/DescriptionPreferenceController.java
index 0a5bb2f..413a876 100644
--- a/src/com/android/settings/notification/app/DescriptionPreferenceController.java
+++ b/src/com/android/settings/notification/app/DescriptionPreferenceController.java
@@ -29,7 +29,7 @@
private static final String KEY_DESC = "desc";
public DescriptionPreferenceController(Context context) {
- super(context, null);
+ super(context, null, KEY_DESC);
}
@Override
@@ -38,20 +38,20 @@
}
@Override
- public boolean isAvailable() {
- if (!super.isAvailable()) {
- return false;
+ public int getAvailabilityStatus() {
+ if (super.getAvailabilityStatus() == CONDITIONALLY_UNAVAILABLE) {
+ return CONDITIONALLY_UNAVAILABLE;
}
if (mChannel == null && !hasValidGroup()) {
- return false;
+ return CONDITIONALLY_UNAVAILABLE;
}
if (mChannel != null && !TextUtils.isEmpty(mChannel.getDescription())) {
- return true;
+ return AVAILABLE;
}
if (hasValidGroup() && !TextUtils.isEmpty(mChannelGroup.getDescription())) {
- return true;
+ return AVAILABLE;
}
- return false;
+ return CONDITIONALLY_UNAVAILABLE;
}
@Override
diff --git a/src/com/android/settings/notification/app/DndPreferenceController.java b/src/com/android/settings/notification/app/DndPreferenceController.java
index b65928a..811eeb4 100644
--- a/src/com/android/settings/notification/app/DndPreferenceController.java
+++ b/src/com/android/settings/notification/app/DndPreferenceController.java
@@ -31,7 +31,7 @@
private static final String KEY_BYPASS_DND = "bypass_dnd";
public DndPreferenceController(Context context, NotificationBackend backend) {
- super(context, backend);
+ super(context, backend, KEY_BYPASS_DND);
}
@Override
@@ -40,11 +40,11 @@
}
@Override
- public boolean isAvailable() {
- if (!super.isAvailable() || mChannel == null) {
- return false;
+ public int getAvailabilityStatus() {
+ if (super.getAvailabilityStatus() == CONDITIONALLY_UNAVAILABLE || mChannel == null) {
+ return CONDITIONALLY_UNAVAILABLE;
}
- return true;
+ return AVAILABLE;
}
@Override
diff --git a/src/com/android/settings/notification/app/HeaderPreferenceController.java b/src/com/android/settings/notification/app/HeaderPreferenceController.java
index 7379d55..c4b0e59 100644
--- a/src/com/android/settings/notification/app/HeaderPreferenceController.java
+++ b/src/com/android/settings/notification/app/HeaderPreferenceController.java
@@ -45,7 +45,7 @@
private boolean mStarted = false;
public HeaderPreferenceController(Context context, DashboardFragment fragment) {
- super(context, null);
+ super(context, null, PREF_KEY_APP_HEADER);
mFragment = fragment;
}
@@ -55,8 +55,8 @@
}
@Override
- public boolean isAvailable() {
- return mAppRow != null;
+ public int getAvailabilityStatus() {
+ return mAppRow != null ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
}
@Override
diff --git a/src/com/android/settings/notification/app/HighImportancePreferenceController.java b/src/com/android/settings/notification/app/HighImportancePreferenceController.java
index d60668b..98dc8a7 100644
--- a/src/com/android/settings/notification/app/HighImportancePreferenceController.java
+++ b/src/com/android/settings/notification/app/HighImportancePreferenceController.java
@@ -37,7 +37,7 @@
public HighImportancePreferenceController(Context context,
NotificationSettings.DependentFieldListener dependentFieldListener,
NotificationBackend backend) {
- super(context, backend);
+ super(context, backend, KEY_IMPORTANCE);
mDependentFieldListener = dependentFieldListener;
}
@@ -47,17 +47,19 @@
}
@Override
- public boolean isAvailable() {
- if (!super.isAvailable()) {
- return false;
+ public int getAvailabilityStatus() {
+ if (super.getAvailabilityStatus() == CONDITIONALLY_UNAVAILABLE) {
+ return CONDITIONALLY_UNAVAILABLE;
}
if (mChannel == null) {
- return false;
+ return CONDITIONALLY_UNAVAILABLE;
}
if (isDefaultChannel()) {
- return false;
+ return CONDITIONALLY_UNAVAILABLE;
}
- return mChannel.getImportance() >= IMPORTANCE_DEFAULT;
+ return mChannel.getImportance() >= IMPORTANCE_DEFAULT
+ ? AVAILABLE
+ : CONDITIONALLY_UNAVAILABLE;
}
@Override
diff --git a/src/com/android/settings/notification/app/ImportancePreferenceController.java b/src/com/android/settings/notification/app/ImportancePreferenceController.java
index 3c32ca4..31ddac3 100644
--- a/src/com/android/settings/notification/app/ImportancePreferenceController.java
+++ b/src/com/android/settings/notification/app/ImportancePreferenceController.java
@@ -38,7 +38,7 @@
public ImportancePreferenceController(Context context,
NotificationSettings.DependentFieldListener dependentFieldListener,
NotificationBackend backend) {
- super(context, backend);
+ super(context, backend, KEY_IMPORTANCE);
mDependentFieldListener = dependentFieldListener;
}
@@ -48,14 +48,14 @@
}
@Override
- public boolean isAvailable() {
- if (!super.isAvailable()) {
- return false;
+ public int getAvailabilityStatus() {
+ if (super.getAvailabilityStatus() == CONDITIONALLY_UNAVAILABLE) {
+ return CONDITIONALLY_UNAVAILABLE;
}
if (mChannel == null) {
- return false;
+ return CONDITIONALLY_UNAVAILABLE;
}
- return !isDefaultChannel();
+ return !isDefaultChannel() ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
}
@Override
diff --git a/src/com/android/settings/notification/app/InvalidConversationInfoPreferenceController.java b/src/com/android/settings/notification/app/InvalidConversationInfoPreferenceController.java
index b937e80..bb2c58b 100644
--- a/src/com/android/settings/notification/app/InvalidConversationInfoPreferenceController.java
+++ b/src/com/android/settings/notification/app/InvalidConversationInfoPreferenceController.java
@@ -31,7 +31,7 @@
public InvalidConversationInfoPreferenceController(Context context,
NotificationBackend backend) {
- super(context, backend);
+ super(context, backend, KEY);
}
@Override
@@ -40,17 +40,19 @@
}
@Override
- public boolean isAvailable() {
+ public int getAvailabilityStatus() {
if (mAppRow == null) {
- return false;
+ return CONDITIONALLY_UNAVAILABLE;
}
if (mAppRow.banned) {
- return false;
+ return CONDITIONALLY_UNAVAILABLE;
}
if (mPreferenceFilter != null && !isIncludedInFilter()) {
- return false;
+ return CONDITIONALLY_UNAVAILABLE;
}
- return mBackend.isInInvalidMsgState(mAppRow.pkg, mAppRow.uid);
+ return mBackend.isInInvalidMsgState(mAppRow.pkg, mAppRow.uid)
+ ? AVAILABLE
+ : CONDITIONALLY_UNAVAILABLE;
}
@Override
diff --git a/src/com/android/settings/notification/app/InvalidConversationPreferenceController.java b/src/com/android/settings/notification/app/InvalidConversationPreferenceController.java
index 5c502dc..219ccbc 100644
--- a/src/com/android/settings/notification/app/InvalidConversationPreferenceController.java
+++ b/src/com/android/settings/notification/app/InvalidConversationPreferenceController.java
@@ -31,7 +31,7 @@
private static final String KEY = "invalid_conversation_switch";
public InvalidConversationPreferenceController(Context context, NotificationBackend backend) {
- super(context, backend);
+ super(context, backend, KEY);
}
@Override
@@ -40,17 +40,19 @@
}
@Override
- public boolean isAvailable() {
+ public int getAvailabilityStatus() {
if (mAppRow == null) {
- return false;
+ return CONDITIONALLY_UNAVAILABLE;
}
if (mAppRow.banned) {
- return false;
+ return CONDITIONALLY_UNAVAILABLE;
}
if (mPreferenceFilter != null && !isIncludedInFilter()) {
- return false;
+ return CONDITIONALLY_UNAVAILABLE;
}
- return mBackend.isInInvalidMsgState(mAppRow.pkg, mAppRow.uid);
+ return mBackend.isInInvalidMsgState(mAppRow.pkg, mAppRow.uid)
+ ? AVAILABLE
+ : CONDITIONALLY_UNAVAILABLE;
}
@Override
diff --git a/src/com/android/settings/notification/app/LightsPreferenceController.java b/src/com/android/settings/notification/app/LightsPreferenceController.java
index d096922..f7f9244 100644
--- a/src/com/android/settings/notification/app/LightsPreferenceController.java
+++ b/src/com/android/settings/notification/app/LightsPreferenceController.java
@@ -33,7 +33,7 @@
private static final String KEY_LIGHTS = "lights";
public LightsPreferenceController(Context context, NotificationBackend backend) {
- super(context, backend);
+ super(context, backend, KEY_LIGHTS);
}
@Override
@@ -42,16 +42,18 @@
}
@Override
- public boolean isAvailable() {
- if (!super.isAvailable()) {
- return false;
+ public int getAvailabilityStatus() {
+ if (super.getAvailabilityStatus() == CONDITIONALLY_UNAVAILABLE) {
+ return CONDITIONALLY_UNAVAILABLE;
}
if (mChannel == null) {
- return false;
+ return CONDITIONALLY_UNAVAILABLE;
}
- return checkCanBeVisible(NotificationManager.IMPORTANCE_DEFAULT)
- && canPulseLight()
- && !isDefaultChannel();
+ if (checkCanBeVisible(NotificationManager.IMPORTANCE_DEFAULT) && canPulseLight()
+ && !isDefaultChannel()) {
+ return AVAILABLE;
+ }
+ return CONDITIONALLY_UNAVAILABLE;
}
@Override
diff --git a/src/com/android/settings/notification/app/MinImportancePreferenceController.java b/src/com/android/settings/notification/app/MinImportancePreferenceController.java
index f825763..b2c0862 100644
--- a/src/com/android/settings/notification/app/MinImportancePreferenceController.java
+++ b/src/com/android/settings/notification/app/MinImportancePreferenceController.java
@@ -37,7 +37,7 @@
public MinImportancePreferenceController(Context context,
NotificationSettings.DependentFieldListener dependentFieldListener,
NotificationBackend backend) {
- super(context, backend);
+ super(context, backend, KEY_IMPORTANCE);
mDependentFieldListener = dependentFieldListener;
}
@@ -47,17 +47,17 @@
}
@Override
- public boolean isAvailable() {
- if (!super.isAvailable()) {
- return false;
+ public int getAvailabilityStatus() {
+ if (super.getAvailabilityStatus() == CONDITIONALLY_UNAVAILABLE) {
+ return CONDITIONALLY_UNAVAILABLE;
}
if (mChannel == null) {
- return false;
+ return CONDITIONALLY_UNAVAILABLE;
}
if (isDefaultChannel()) {
- return false;
+ return CONDITIONALLY_UNAVAILABLE;
}
- return mChannel.getImportance() <= IMPORTANCE_LOW;
+ return mChannel.getImportance() <= IMPORTANCE_LOW ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
}
@Override
diff --git a/src/com/android/settings/notification/app/NotificationPreferenceController.java b/src/com/android/settings/notification/app/NotificationPreferenceController.java
index fb19d9d..271a83d 100644
--- a/src/com/android/settings/notification/app/NotificationPreferenceController.java
+++ b/src/com/android/settings/notification/app/NotificationPreferenceController.java
@@ -17,26 +17,24 @@
package com.android.settings.notification.app;
import static android.app.NotificationManager.IMPORTANCE_NONE;
-import static android.os.UserHandle.USER_SYSTEM;
import android.annotation.Nullable;
import android.app.NotificationChannel;
import android.app.NotificationChannelGroup;
import android.app.NotificationManager;
import android.content.Context;
-import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ShortcutInfo;
import android.graphics.drawable.Drawable;
import android.os.UserManager;
-import android.provider.Settings;
import android.util.Log;
+import android.util.Slog;
import androidx.preference.Preference;
+import com.android.settings.core.BasePreferenceController;
import com.android.settings.notification.NotificationBackend;
import com.android.settingslib.RestrictedLockUtils;
-import com.android.settingslib.core.AbstractPreferenceController;
import java.util.Comparator;
import java.util.List;
@@ -46,7 +44,7 @@
* Parent class for preferences appearing on notification setting pages at the app,
* notification channel group, or notification channel level.
*/
-public abstract class NotificationPreferenceController extends AbstractPreferenceController {
+public abstract class NotificationPreferenceController extends BasePreferenceController {
private static final String TAG = "ChannelPrefContr";
@Nullable
protected NotificationChannel mChannel;
@@ -71,8 +69,11 @@
boolean overrideCanBlockValue;
boolean overrideCanConfigureValue;
- public NotificationPreferenceController(Context context, NotificationBackend backend) {
- super(context);
+ boolean mLoadedChannelState;
+
+ public NotificationPreferenceController(Context context, NotificationBackend backend,
+ String key) {
+ super(context, key);
mContext = context;
mNm = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
mBackend = backend;
@@ -81,28 +82,30 @@
}
/**
- * Returns true if field's parent object is not blocked.
+ * Returns available if field's parent object is not blocked.
*/
@Override
- public boolean isAvailable() {
+ public int getAvailabilityStatus() {
if (mAppRow == null) {
- return false;
+ return CONDITIONALLY_UNAVAILABLE;
}
if (mAppRow.banned) {
- return false;
+ return CONDITIONALLY_UNAVAILABLE;
}
if (mChannelGroup != null) {
if (mChannelGroup.isBlocked()) {
- return false;
+ return CONDITIONALLY_UNAVAILABLE;
}
}
if (mChannel != null) {
if (mPreferenceFilter != null && !isIncludedInFilter()) {
- return false;
+ return CONDITIONALLY_UNAVAILABLE;
}
- return mChannel.getImportance() != IMPORTANCE_NONE;
+ if(mChannel.getImportance() == IMPORTANCE_NONE) {
+ return CONDITIONALLY_UNAVAILABLE;
+ }
}
- return true;
+ return AVAILABLE;
}
protected void onResume(NotificationBackend.AppRow appRow,
diff --git a/src/com/android/settings/notification/app/NotificationSettings.java b/src/com/android/settings/notification/app/NotificationSettings.java
index 192a0ee..5750167 100644
--- a/src/com/android/settings/notification/app/NotificationSettings.java
+++ b/src/com/android/settings/notification/app/NotificationSettings.java
@@ -41,6 +41,7 @@
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
+import android.util.Slog;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
@@ -129,15 +130,52 @@
}
}
+ mUserId = UserHandle.getUserId(mUid);
mPkgInfo = findPackageInfo(mPkg, mUid);
+ }
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ if (mIntent == null && mArgs == null) {
+ toastAndFinish("no intent");
+ return;
+ }
+
+ if (mUid < 0 || TextUtils.isEmpty(mPkg) || mPkgInfo == null) {
+ toastAndFinish("Missing package or uid or packageinfo");
+ return;
+ }
+
+ startListeningToPackageRemove();
+ }
+
+ @Override
+ public void onDestroy() {
+ stopListeningToPackageRemove();
+ super.onDestroy();
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ if (mUid < 0 || TextUtils.isEmpty(mPkg) || mPkgInfo == null) {
+ toastAndFinish("Missing package or uid or packageinfo");
+ return;
+ }
+ mPkgInfo = findPackageInfo(mPkg, mUid);
if (mPkgInfo != null) {
- mUserId = UserHandle.getUserId(mUid);
mSuspendedAppsAdmin = RestrictedLockUtilsInternal.checkIfApplicationIsSuspended(
mContext, mPkg, mUserId);
- loadChannel();
loadAppRow();
+ if (mAppRow == null) {
+ toastAndFinish("Can't load package");
+ return;
+ }
+ loadChannel();
+ loadConversation();
loadChannelGroup();
loadPreferencesFilter();
collectConfigActivities();
@@ -157,55 +195,6 @@
}
}
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- if (mIntent == null && mArgs == null) {
- Log.w(TAG, "No intent");
- toastAndFinish();
- return;
- }
-
- if (mUid < 0 || TextUtils.isEmpty(mPkg) || mPkgInfo == null) {
- Log.w(TAG, "Missing package or uid or packageinfo");
- toastAndFinish();
- return;
- }
-
- startListeningToPackageRemove();
- }
-
- @Override
- public void onDestroy() {
- stopListeningToPackageRemove();
- super.onDestroy();
- }
-
- @Override
- public void onResume() {
- super.onResume();
- if (mUid < 0 || TextUtils.isEmpty(mPkg) || mPkgInfo == null || mAppRow == null) {
- Log.w(TAG, "Missing package or uid or packageinfo");
- finish();
- return;
- }
- // Reload app, channel, etc onResume in case they've changed. A little wasteful if we've
- // just done onAttach but better than making every preference controller reload all
- // the data
- loadAppRow();
- if (mAppRow == null) {
- Log.w(TAG, "Can't load package");
- finish();
- return;
- }
- loadChannel();
- loadConversation();
- loadChannelGroup();
- loadPreferencesFilter();
- collectConfigActivities();
- }
-
protected void animatePanel() {
if (mPreferenceFilter != null) {
mLayoutView = getActivity().findViewById(R.id.main_content);
@@ -307,7 +296,8 @@
}
}
- protected void toastAndFinish() {
+ protected void toastAndFinish(String msg) {
+ Log.w(TAG, msg);
Toast.makeText(mContext, R.string.app_not_found_dlg_text, Toast.LENGTH_SHORT).show();
getActivity().finish();
}
diff --git a/src/com/android/settings/notification/app/NotificationsOffPreferenceController.java b/src/com/android/settings/notification/app/NotificationsOffPreferenceController.java
index 0c7cd23..46625c3 100644
--- a/src/com/android/settings/notification/app/NotificationsOffPreferenceController.java
+++ b/src/com/android/settings/notification/app/NotificationsOffPreferenceController.java
@@ -30,7 +30,7 @@
private static final String KEY_BLOCKED_DESC = "block_desc";
public NotificationsOffPreferenceController(Context context) {
- super(context, null);
+ super(context, null, KEY_BLOCKED_DESC);
}
@Override
@@ -39,16 +39,20 @@
}
@Override
- public boolean isAvailable() {
+ public int getAvailabilityStatus() {
if (mAppRow == null) {
- return false;
+ return CONDITIONALLY_UNAVAILABLE;
}
if (mPreferenceFilter != null && !isIncludedInFilter()) {
- return false;
+ return CONDITIONALLY_UNAVAILABLE;
}
// Available only when other controllers are unavailable - this UI replaces the UI that
// would give more detailed notification controls.
- return !super.isAvailable();
+ if (super.getAvailabilityStatus() == AVAILABLE) {
+ return CONDITIONALLY_UNAVAILABLE;
+ } else {
+ return AVAILABLE;
+ }
}
@Override
diff --git a/src/com/android/settings/notification/app/SoundPreferenceController.java b/src/com/android/settings/notification/app/SoundPreferenceController.java
index b23b4fc..335b442 100644
--- a/src/com/android/settings/notification/app/SoundPreferenceController.java
+++ b/src/com/android/settings/notification/app/SoundPreferenceController.java
@@ -47,7 +47,7 @@
public SoundPreferenceController(Context context, SettingsPreferenceFragment hostFragment,
NotificationSettings.DependentFieldListener dependentFieldListener,
NotificationBackend backend) {
- super(context, backend);
+ super(context, backend, KEY_SOUND);
mFragment = hostFragment;
mListener = dependentFieldListener;
}
@@ -58,14 +58,17 @@
}
@Override
- public boolean isAvailable() {
- if (!super.isAvailable()) {
- return false;
+ public int getAvailabilityStatus() {
+ if (super.getAvailabilityStatus() == CONDITIONALLY_UNAVAILABLE) {
+ return CONDITIONALLY_UNAVAILABLE;
}
if (mChannel == null) {
- return false;
+ return CONDITIONALLY_UNAVAILABLE;
}
- return checkCanBeVisible(NotificationManager.IMPORTANCE_DEFAULT) && !isDefaultChannel();
+ if (checkCanBeVisible(NotificationManager.IMPORTANCE_DEFAULT) && !isDefaultChannel()) {
+ return AVAILABLE;
+ }
+ return CONDITIONALLY_UNAVAILABLE;
}
@Override
diff --git a/src/com/android/settings/notification/app/VibrationPreferenceController.java b/src/com/android/settings/notification/app/VibrationPreferenceController.java
index 34d1a54..f91999f 100644
--- a/src/com/android/settings/notification/app/VibrationPreferenceController.java
+++ b/src/com/android/settings/notification/app/VibrationPreferenceController.java
@@ -34,7 +34,7 @@
private final Vibrator mVibrator;
public VibrationPreferenceController(Context context, NotificationBackend backend) {
- super(context, backend);
+ super(context, backend, KEY_VIBRATE);
mVibrator = context.getSystemService(Vibrator.class);
}
@@ -44,14 +44,15 @@
}
@Override
- public boolean isAvailable() {
- if (!super.isAvailable() || mChannel == null) {
- return false;
- }
- return checkCanBeVisible(NotificationManager.IMPORTANCE_DEFAULT)
- && !isDefaultChannel()
- && mVibrator != null
- && mVibrator.hasVibrator();
+ public int getAvailabilityStatus() {
+ if (super.getAvailabilityStatus() == CONDITIONALLY_UNAVAILABLE || mChannel == null) {
+ return CONDITIONALLY_UNAVAILABLE;
+ }
+ if (checkCanBeVisible(NotificationManager.IMPORTANCE_DEFAULT) && !isDefaultChannel()
+ && mVibrator != null && mVibrator.hasVibrator()) {
+ return AVAILABLE;
+ }
+ return CONDITIONALLY_UNAVAILABLE;
}
@Override
diff --git a/src/com/android/settings/notification/app/VisibilityPreferenceController.java b/src/com/android/settings/notification/app/VisibilityPreferenceController.java
index a2a1d76..3f33267 100644
--- a/src/com/android/settings/notification/app/VisibilityPreferenceController.java
+++ b/src/com/android/settings/notification/app/VisibilityPreferenceController.java
@@ -48,7 +48,7 @@
public VisibilityPreferenceController(Context context, LockPatternUtils utils,
NotificationBackend backend) {
- super(context, backend);
+ super(context, backend, KEY_VISIBILITY_OVERRIDE);
mLockPatternUtils = utils;
}
@@ -58,14 +58,18 @@
}
@Override
- public boolean isAvailable() {
- if (!super.isAvailable()) {
- return false;
+ public int getAvailabilityStatus() {
+ if (super.getAvailabilityStatus() == CONDITIONALLY_UNAVAILABLE) {
+ return CONDITIONALLY_UNAVAILABLE;
}
if (mChannel == null || mAppRow.banned) {
- return false;
+ return CONDITIONALLY_UNAVAILABLE;
}
- return checkCanBeVisible(NotificationManager.IMPORTANCE_LOW) && isLockScreenSecure();
+ if (checkCanBeVisible(NotificationManager.IMPORTANCE_LOW) && isLockScreenSecure()) {
+ return AVAILABLE;
+ }
+
+ return CONDITIONALLY_UNAVAILABLE;
}
@Override
diff --git a/src/com/android/settings/users/AutoSyncWorkDataPreferenceController.java b/src/com/android/settings/users/AutoSyncWorkDataPreferenceController.java
index fb57173..9ac1b87 100644
--- a/src/com/android/settings/users/AutoSyncWorkDataPreferenceController.java
+++ b/src/com/android/settings/users/AutoSyncWorkDataPreferenceController.java
@@ -22,7 +22,8 @@
import com.android.settings.Utils;
-public class AutoSyncWorkDataPreferenceController extends AutoSyncPersonalDataPreferenceController {
+/** An account sync data preference controller for work */
+public class AutoSyncWorkDataPreferenceController extends AutoSyncDataPreferenceController {
private static final String KEY_AUTO_SYNC_WORK_ACCOUNT = "auto_sync_work_account_data";
@@ -38,6 +39,7 @@
@Override
public boolean isAvailable() {
+ mUserHandle = Utils.getManagedProfileWithDisabled(mUserManager);
return mUserHandle != null && !mUserManager.isManagedProfile() && !mUserManager.isLinkedUser()
&& mUserManager.getProfiles(UserHandle.myUserId()).size() > 1;
}
diff --git a/src/com/android/settings/wifi/WifiDialogActivity.java b/src/com/android/settings/wifi/WifiDialogActivity.java
index 8a46c9d..e3e77e8 100644
--- a/src/com/android/settings/wifi/WifiDialogActivity.java
+++ b/src/com/android/settings/wifi/WifiDialogActivity.java
@@ -19,6 +19,7 @@
import static android.Manifest.permission.ACCESS_FINE_LOCATION;
import static android.os.UserManager.DISALLOW_CONFIG_WIFI;
+import android.app.KeyguardManager;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
@@ -51,6 +52,7 @@
import com.google.android.setupcompat.util.WizardManagerHelper;
import com.google.android.setupdesign.util.ThemeHelper;
+import java.lang.ref.WeakReference;
import java.time.Clock;
import java.time.ZoneOffset;
@@ -96,10 +98,12 @@
// Interval between initiating NetworkDetailsTracker scans.
private static final long SCAN_INTERVAL_MILLIS = 10_000;
- private WifiDialog mDialog;
+ @VisibleForTesting
+ WifiDialog mDialog;
private AccessPoint mAccessPoint;
- private WifiDialog2 mDialog2;
+ @VisibleForTesting
+ WifiDialog2 mDialog2;
// The received intent supports a key of WifiTrackerLib or SettingsLib.
private boolean mIsWifiTrackerLib;
@@ -108,6 +112,7 @@
private NetworkDetailsTracker mNetworkDetailsTracker;
private HandlerThread mWorkerThread;
private WifiManager mWifiManager;
+ private LockScreenMonitor mLockScreenMonitor;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -184,6 +189,10 @@
mDialog.setOnDismissListener(this);
}
}
+
+ if (mDialog2 != null || mDialog != null) {
+ mLockScreenMonitor = new LockScreenMonitor(this);
+ }
}
@VisibleForTesting
@@ -221,6 +230,10 @@
}
}
+ if (mLockScreenMonitor != null) {
+ mLockScreenMonitor.release();
+ mLockScreenMonitor = null;
+ }
super.onDestroy();
}
@@ -411,4 +424,45 @@
}
return false;
}
+
+ void dismissDialog() {
+ if (mDialog != null) {
+ mDialog.dismiss();
+ mDialog = null;
+ }
+ if (mDialog2 != null) {
+ mDialog2.dismiss();
+ mDialog2 = null;
+ }
+ }
+
+ @VisibleForTesting
+ static final class LockScreenMonitor implements KeyguardManager.KeyguardLockedStateListener {
+ private final WeakReference<WifiDialogActivity> mWifiDialogActivity;
+ private KeyguardManager mKeyguardManager;
+
+ LockScreenMonitor(WifiDialogActivity activity) {
+ mWifiDialogActivity = new WeakReference<>(activity);
+ mKeyguardManager = activity.getSystemService(KeyguardManager.class);
+ mKeyguardManager.addKeyguardLockedStateListener(activity.getMainExecutor(), this);
+ }
+
+ void release() {
+ if (mKeyguardManager == null) return;
+ mKeyguardManager.removeKeyguardLockedStateListener(this);
+ mKeyguardManager = null;
+ }
+
+ @Override
+ public void onKeyguardLockedStateChanged(boolean isKeyguardLocked) {
+ if (!isKeyguardLocked) return;
+ WifiDialogActivity activity = mWifiDialogActivity.get();
+ if (activity == null) return;
+ activity.dismissDialog();
+
+ Log.e(TAG, "Dismiss Wi-Fi dialog to prevent leaking user data on lock screen!");
+ EventLog.writeEvent(0x534e4554, "231583603", -1 /* UID */,
+ "Leak Wi-Fi dialog on lock screen");
+ }
+ }
}
diff --git a/tests/robotests/src/com/android/settings/accounts/AccountPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accounts/AccountPreferenceControllerTest.java
index b22b156..89e00e1 100644
--- a/tests/robotests/src/com/android/settings/accounts/AccountPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/accounts/AccountPreferenceControllerTest.java
@@ -45,7 +45,7 @@
import com.android.settings.AccessiblePreferenceCategory;
import com.android.settings.R;
-import com.android.settings.SettingsPreferenceFragment;
+import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.dashboard.profileselector.ProfileSelectFragment;
import com.android.settings.testutils.shadow.ShadowAccountManager;
import com.android.settings.testutils.shadow.ShadowContentResolver;
@@ -77,7 +77,7 @@
@Mock(answer = RETURNS_DEEP_STUBS)
private UserManager mUserManager;
@Mock(answer = RETURNS_DEEP_STUBS)
- private SettingsPreferenceFragment mFragment;
+ private DashboardFragment mFragment;
@Mock(answer = RETURNS_DEEP_STUBS)
private AccountManager mAccountManager;
@Mock(answer = RETURNS_DEEP_STUBS)
diff --git a/tests/robotests/src/com/android/settings/dashboard/DashboardFragmentTest.java b/tests/robotests/src/com/android/settings/dashboard/DashboardFragmentTest.java
index 894a6c5..fd6689a 100644
--- a/tests/robotests/src/com/android/settings/dashboard/DashboardFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/dashboard/DashboardFragmentTest.java
@@ -298,6 +298,14 @@
}
@Test
+ public void forceUpdatePreferences_prefKeyNull_shouldNotCrash() {
+ mTestFragment.addPreferenceController(new TestPreferenceController(mContext));
+
+ // Should not crash
+ mTestFragment.forceUpdatePreferences();
+ }
+
+ @Test
public void checkUiBlocker_noUiBlocker_controllerIsNull() {
mTestFragment.mBlockerController = null;
mControllers.add(new TestPreferenceController(mContext));
diff --git a/tests/robotests/src/com/android/settings/datetime/DatePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/datetime/DatePreferenceControllerTest.java
index 1b8148b..c7357ad 100644
--- a/tests/robotests/src/com/android/settings/datetime/DatePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/datetime/DatePreferenceControllerTest.java
@@ -18,15 +18,19 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.app.DatePickerDialog;
import android.app.time.Capabilities;
import android.app.time.TimeCapabilities;
import android.app.time.TimeCapabilitiesAndConfig;
import android.app.time.TimeConfiguration;
import android.app.time.TimeManager;
import android.app.timedetector.TimeDetector;
+import android.app.timedetector.TimeDetectorHelper;
import android.content.Context;
import android.os.UserHandle;
@@ -40,17 +44,20 @@
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
+import java.util.Calendar;
+import java.util.GregorianCalendar;
+
@RunWith(RobolectricTestRunner.class)
public class DatePreferenceControllerTest {
@Mock
private Context mContext;
@Mock
- private TimeDetector mTimeDetector;
+ private DatePreferenceController.DatePreferenceHost mHost;
@Mock
private TimeManager mTimeManager;
@Mock
- private DatePreferenceController.DatePreferenceHost mHost;
+ private TimeDetector mTimeDetector;
private RestrictedPreference mPreference;
private DatePreferenceController mController;
@@ -114,6 +121,26 @@
verify(mHost).showDatePicker();
}
+ @Test
+ public void testBuildDatePicker() {
+ TimeDetectorHelper timeDetectorHelper = mock(TimeDetectorHelper.class);
+ when(timeDetectorHelper.getManualDateSelectionYearMin()).thenReturn(2015);
+ when(timeDetectorHelper.getManualDateSelectionYearMax()).thenReturn(2020);
+
+ Context context = RuntimeEnvironment.application;
+ DatePickerDialog dialog = mController.buildDatePicker(context, timeDetectorHelper);
+
+ GregorianCalendar calendar = new GregorianCalendar();
+
+ long minDate = dialog.getDatePicker().getMinDate();
+ calendar.setTimeInMillis(minDate);
+ assertEquals(2015, calendar.get(Calendar.YEAR));
+
+ long maxDate = dialog.getDatePicker().getMaxDate();
+ calendar.setTimeInMillis(maxDate);
+ assertEquals(2020, calendar.get(Calendar.YEAR));
+ }
+
private static TimeCapabilitiesAndConfig createCapabilitiesAndConfig(
boolean suggestManualAllowed) {
int suggestManualCapability = suggestManualAllowed ? Capabilities.CAPABILITY_POSSESSED
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/OptimizedPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/OptimizedPreferenceControllerTest.java
index 1b5ded0..1fec92a 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/OptimizedPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/OptimizedPreferenceControllerTest.java
@@ -61,6 +61,18 @@
}
@Test
+ public void testUpdateState_isSystemOrDefaultAppAndOptimizeStates_prefChecked() {
+ when(mockBatteryOptimizeUtils.isValidPackageName()).thenReturn(true);
+ when(mockBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true);
+ when(mockBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(
+ BatteryOptimizeUtils.MODE_OPTIMIZED);
+
+ mController.updateState(mPreference);
+
+ assertThat(mPreference.isChecked()).isTrue();
+ }
+
+ @Test
public void testUpdateState_isSystemOrDefaultApp_prefUnchecked() {
when(mockBatteryOptimizeUtils.isValidPackageName()).thenReturn(true);
when(mockBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true);
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/RestrictedPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/RestrictedPreferenceControllerTest.java
index bacfb1a..944376c 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/RestrictedPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/RestrictedPreferenceControllerTest.java
@@ -69,7 +69,19 @@
}
@Test
- public void testUpdateState_isSystemOrDefaultApp_prefChecked() {
+ public void testUpdateState_isSystemOrDefaultAppAndRestrictedStates_prefChecked() {
+ when(mockBatteryOptimizeUtils.isValidPackageName()).thenReturn(true);
+ when(mockBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true);
+ when(mockBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(
+ BatteryOptimizeUtils.MODE_RESTRICTED);
+
+ mController.updateState(mPreference);
+
+ assertThat(mPreference.isChecked()).isTrue();
+ }
+
+ @Test
+ public void testUpdateState_isSystemOrDefaultApp_prefUnchecked() {
when(mockBatteryOptimizeUtils.isValidPackageName()).thenReturn(true);
when(mockBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true);
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/UnrestrictedPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/UnrestrictedPreferenceControllerTest.java
index d5500fa..c5642df 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/UnrestrictedPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/UnrestrictedPreferenceControllerTest.java
@@ -70,13 +70,26 @@
}
@Test
- public void testUpdateState_isSystemOrDefaultApp_prefChecked() {
+ public void testUpdateState_isSystemOrDefaultAppAndUnrestrictedStates_prefChecked() {
+ when(mockBatteryOptimizeUtils.isValidPackageName()).thenReturn(true);
+ when(mockBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true);
+ when(mockBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(
+ BatteryOptimizeUtils.MODE_UNRESTRICTED);
+
+ mController.updateState(mPreference);
+
+ assertThat(mPreference.isChecked()).isTrue();
+ }
+
+ @Test
+ public void testUpdateState_isSystemOrDefaultApp_prefUnchecked() {
when(mockBatteryOptimizeUtils.isValidPackageName()).thenReturn(true);
when(mockBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true);
mController.updateState(mPreference);
- assertThat(mPreference.isChecked()).isTrue();
+ assertThat(mPreference.isChecked()).isFalse();
+ assertThat(mPreference.isEnabled()).isFalse();
}
@Test
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryChartViewV2Test.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryChartViewV2Test.java
index 111019f..34ba2eb 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryChartViewV2Test.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryChartViewV2Test.java
@@ -26,6 +26,7 @@
import android.accessibilityservice.AccessibilityServiceInfo;
import android.content.Context;
import android.os.LocaleList;
+import android.view.View;
import android.view.accessibility.AccessibilityManager;
import com.android.settings.fuelgauge.PowerUsageFeatureProvider;
@@ -55,6 +56,8 @@
private AccessibilityServiceInfo mMockAccessibilityServiceInfo;
@Mock
private AccessibilityManager mMockAccessibilityManager;
+ @Mock
+ private View mMockView;
@Before
public void setUp() {
@@ -74,13 +77,13 @@
}
@Test
- public void testIsAccessibilityEnabled_disable_returnFalse() {
+ public void isAccessibilityEnabled_disable_returnFalse() {
doReturn(false).when(mMockAccessibilityManager).isEnabled();
assertThat(BatteryChartViewV2.isAccessibilityEnabled(mContext)).isFalse();
}
@Test
- public void testIsAccessibilityEnabled_emptyInfo_returnFalse() {
+ public void isAccessibilityEnabled_emptyInfo_returnFalse() {
doReturn(true).when(mMockAccessibilityManager).isEnabled();
doReturn(new ArrayList<AccessibilityServiceInfo>())
.when(mMockAccessibilityManager)
@@ -90,45 +93,41 @@
}
@Test
- public void testIsAccessibilityEnabled_validServiceId_returnTrue() {
+ public void isAccessibilityEnabled_validServiceId_returnTrue() {
doReturn(true).when(mMockAccessibilityManager).isEnabled();
assertThat(BatteryChartViewV2.isAccessibilityEnabled(mContext)).isTrue();
}
@Test
- public void testSetSelectedIndex_invokesCallback() {
+ public void onClick_invokesCallback() {
+ mBatteryChartView.setLevels(new int[] {90, 80, 70, 60});
+ for (int i = 0; i < mBatteryChartView.mTrapezoidSlots.length; i++) {
+ mBatteryChartView.mTrapezoidSlots[i] = new BatteryChartViewV2.TrapezoidSlot();
+ mBatteryChartView.mTrapezoidSlots[i].mLeft = i;
+ mBatteryChartView.mTrapezoidSlots[i].mRight = i + 0.5f;
+ }
+ mBatteryChartView.mSelectedIndex = 2;
final int[] selectedIndex = new int[1];
- final int expectedIndex = 2;
- mBatteryChartView.mSelectedIndex = 1;
mBatteryChartView.setOnSelectListener(
trapezoidIndex -> {
selectedIndex[0] = trapezoidIndex;
});
- mBatteryChartView.setSelectedIndex(expectedIndex);
+ // Verify onClick() a different index 1.
+ mBatteryChartView.mTouchUpEventX = 1;
+ selectedIndex[0] = Integer.MIN_VALUE;
+ mBatteryChartView.onClick(mMockView);
+ assertThat(selectedIndex[0]).isEqualTo(1);
- assertThat(mBatteryChartView.mSelectedIndex)
- .isEqualTo(expectedIndex);
- assertThat(selectedIndex[0]).isEqualTo(expectedIndex);
+ // Verify onClick() the same index 2.
+ mBatteryChartView.mTouchUpEventX = 2;
+ selectedIndex[0] = Integer.MIN_VALUE;
+ mBatteryChartView.onClick(mMockView);
+ assertThat(selectedIndex[0]).isEqualTo(BatteryChartViewV2.SELECTED_INDEX_ALL);
}
@Test
- public void testSetSelectedIndex_sameIndex_notInvokesCallback() {
- final int[] selectedIndex = new int[1];
- final int expectedIndex = 1;
- mBatteryChartView.mSelectedIndex = expectedIndex;
- mBatteryChartView.setOnSelectListener(
- trapezoidIndex -> {
- selectedIndex[0] = trapezoidIndex;
- });
-
- mBatteryChartView.setSelectedIndex(expectedIndex);
-
- assertThat(selectedIndex[0]).isNotEqualTo(expectedIndex);
- }
-
- @Test
- public void testClickable_isChartGraphSlotsEnabledIsFalse_notClickable() {
+ public void clickable_isChartGraphSlotsEnabledIsFalse_notClickable() {
mBatteryChartView.setClickableForce(true);
when(mPowerUsageFeatureProvider.isChartGraphSlotsEnabled(mContext))
.thenReturn(false);
@@ -139,7 +138,7 @@
}
@Test
- public void testClickable_accessibilityIsDisabled_clickable() {
+ public void clickable_accessibilityIsDisabled_clickable() {
mBatteryChartView.setClickableForce(true);
when(mPowerUsageFeatureProvider.isChartGraphSlotsEnabled(mContext))
.thenReturn(true);
@@ -151,7 +150,7 @@
}
@Test
- public void testClickable_accessibilityIsEnabledWithoutValidId_clickable() {
+ public void clickable_accessibilityIsEnabledWithoutValidId_clickable() {
mBatteryChartView.setClickableForce(true);
when(mPowerUsageFeatureProvider.isChartGraphSlotsEnabled(mContext))
.thenReturn(true);
@@ -166,7 +165,7 @@
}
@Test
- public void testClickable_accessibilityIsEnabledWithValidId_notClickable() {
+ public void clickable_accessibilityIsEnabledWithValidId_notClickable() {
mBatteryChartView.setClickableForce(true);
when(mPowerUsageFeatureProvider.isChartGraphSlotsEnabled(mContext))
.thenReturn(true);
@@ -178,12 +177,11 @@
}
@Test
- public void testClickable_restoreFromNonClickableState() {
+ public void clickable_restoreFromNonClickableState() {
final int[] levels = new int[13];
for (int index = 0; index < levels.length; index++) {
levels[index] = index + 1;
}
- mBatteryChartView.setTrapezoidCount(12);
mBatteryChartView.setLevels(levels);
mBatteryChartView.setClickableForce(true);
when(mPowerUsageFeatureProvider.isChartGraphSlotsEnabled(mContext))
@@ -201,14 +199,14 @@
}
@Test
- public void testOnAttachedToWindow_addAccessibilityStateChangeListener() {
+ public void onAttachedToWindow_addAccessibilityStateChangeListener() {
mBatteryChartView.onAttachedToWindow();
verify(mMockAccessibilityManager)
.addAccessibilityStateChangeListener(mBatteryChartView);
}
@Test
- public void testOnDetachedFromWindow_removeAccessibilityStateChangeListener() {
+ public void onDetachedFromWindow_removeAccessibilityStateChangeListener() {
mBatteryChartView.onAttachedToWindow();
mBatteryChartView.mHandler.postDelayed(
mBatteryChartView.mUpdateClickableStateRun, 1000);
@@ -223,7 +221,7 @@
}
@Test
- public void testOnAccessibilityStateChanged_postUpdateStateRunnable() {
+ public void onAccessibilityStateChanged_postUpdateStateRunnable() {
mBatteryChartView.mHandler = spy(mBatteryChartView.mHandler);
mBatteryChartView.onAccessibilityStateChanged(/*enabled=*/ true);
diff --git a/tests/robotests/src/com/android/settings/notification/app/NotificationPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/app/NotificationPreferenceControllerTest.java
index b2f1673..bf529e6 100644
--- a/tests/robotests/src/com/android/settings/notification/app/NotificationPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/app/NotificationPreferenceControllerTest.java
@@ -426,7 +426,7 @@
private final class TestPreferenceController extends NotificationPreferenceController {
private TestPreferenceController(Context context, NotificationBackend backend) {
- super(context, backend);
+ super(context, backend, "key");
}
@Override
diff --git a/tests/robotests/src/com/android/settings/wifi/WifiDialogActivityTest.java b/tests/robotests/src/com/android/settings/wifi/WifiDialogActivityTest.java
index 28b7ecb..c9cc02e 100644
--- a/tests/robotests/src/com/android/settings/wifi/WifiDialogActivityTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/WifiDialogActivityTest.java
@@ -33,6 +33,7 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.app.KeyguardManager;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.wifi.WifiConfiguration;
@@ -46,7 +47,6 @@
import com.google.android.setupcompat.util.WizardManagerHelper;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@@ -82,6 +82,8 @@
Intent mResultData;
@Mock
WifiConfigController mController;
+ @Mock
+ KeyguardManager mKeyguardManager;
WifiDialogActivity mActivity;
@@ -99,6 +101,7 @@
mActivity = spy(Robolectric.setupActivity(WifiDialogActivity.class));
when(mActivity.getSystemService(UserManager.class)).thenReturn(mUserManager);
when(mActivity.getSystemService(WifiManager.class)).thenReturn(mWifiManager);
+ when(mActivity.getSystemService(KeyguardManager.class)).thenReturn(mKeyguardManager);
}
@Test
@@ -294,4 +297,35 @@
assertThat(result).isTrue();
}
+
+ @Test
+ public void dismissDialog_hasDialog_dialogDismiss() {
+ mActivity.mDialog = mWifiDialog;
+ mActivity.mDialog2 = mWifiDialog2;
+
+ mActivity.dismissDialog();
+
+ verify(mWifiDialog).dismiss();
+ verify(mWifiDialog2).dismiss();
+ }
+
+ @Test
+ public void onKeyguardLockedStateChanged_keyguardIsNotLocked_doNotDismissDialog() {
+ WifiDialogActivity.LockScreenMonitor lockScreenMonitor =
+ new WifiDialogActivity.LockScreenMonitor(mActivity);
+
+ lockScreenMonitor.onKeyguardLockedStateChanged(false /* isKeyguardLocked */);
+
+ verify(mActivity, never()).dismissDialog();
+ }
+
+ @Test
+ public void onKeyguardLockedStateChanged_keyguardIsLocked_dismissDialog() {
+ WifiDialogActivity.LockScreenMonitor lockScreenMonitor =
+ new WifiDialogActivity.LockScreenMonitor(mActivity);
+
+ lockScreenMonitor.onKeyguardLockedStateChanged(true /* isKeyguardLocked */);
+
+ verify(mActivity).dismissDialog();
+ }
}