Merge "Refactor Battery Chart View State Controll"
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/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/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/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/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/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/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/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();
+ }
}