Merge "Settings crashes on opening Wi-Fi Add network"
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index c1e0c60..ccdc2dc 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -726,7 +726,6 @@
android:label="@string/zen_mode_settings_title"
android:icon="@drawable/ic_notifications"
android:exported="true"
- android:taskAffinity="com.android.settings"
android:parentActivityName="Settings">
<intent-filter android:priority="1">
<action android:name="android.settings.ZEN_MODE_SETTINGS" />
@@ -897,7 +896,6 @@
android:label="@string/night_display_title"
android:enabled="@*android:bool/config_nightDisplayAvailable"
android:icon="@drawable/ic_settings_night_display"
- android:taskAffinity="com.android.settings"
android:parentActivityName="Settings">
<intent-filter android:priority="32">
<action android:name="android.intent.action.MAIN" />
@@ -1919,7 +1917,7 @@
<activity android:name=".bluetooth.BluetoothPairingDialog"
android:excludeFromRecents="true"
android:windowSoftInputMode="stateVisible|adjustResize"
- android:theme="@*android:style/Theme.DeviceDefault.Settings.Dialog.NoActionBar">
+ android:theme="@style/Theme.AlertDialog">
<intent-filter android:priority="1">
<action android:name="android.bluetooth.device.action.PAIRING_REQUEST" />
<category android:name="android.intent.category.DEFAULT" />
@@ -1966,7 +1964,7 @@
android:excludeFromRecents="true"
android:exported="true"
android:permission="android.permission.DUMP"
- android:theme="@*android:style/Theme.DeviceDefault.Settings.Dialog.NoActionBar">
+ android:theme="@style/Theme.AlertDialog">
<intent-filter>
<action android:name="android.settings.SHOW_REMOTE_BUGREPORT_DIALOG" />
<category android:name="android.intent.category.DEFAULT" />
@@ -2662,7 +2660,7 @@
</activity>
<activity android:name=".sim.SimPreferenceDialog"
- android:theme="@*android:style/Theme.DeviceDefault.Settings.Dialog.NoActionBar"
+ android:theme="@style/Theme.AlertDialog"
android:excludeFromRecents="true" />
<activity
@@ -2692,7 +2690,7 @@
</activity>
<activity android:name=".sim.SimDialogActivity"
- android:theme="@*android:style/Theme.DeviceDefault.Settings.Dialog.NoActionBar"
+ android:theme="@style/Theme.AlertDialog"
android:label="@string/sim_settings_title"
android:excludeFromRecents="true">
<intent-filter>
diff --git a/res/values/arrays.xml b/res/values/arrays.xml
index 0a058d5..e57cbfa 100644
--- a/res/values/arrays.xml
+++ b/res/values/arrays.xml
@@ -1119,4 +1119,18 @@
<item>0</item>
</string-array>
+ <!-- Titles for autofill logging level preference. [CHAR LIMIT=50] -->
+ <string-array name="autofill_logging_level_entries">
+ <item>Off</item>
+ <item>Debug</item>
+ <item>Verbose</item>
+ </string-array>
+
+ <!-- Values for autofill logging level preference. -->
+ <string-array name="autofill_logging_level_values" translatable="false" >
+ <item>0</item> <!-- AutofillManager.NO_LOGGING -->
+ <item>2</item> <!-- AutofillManager.FLAG_ADD_CLIENT_DEBUG -->
+ <item>4</item> <!-- AutofillManager.FLAG_ADD_CLIENT_VERBOSE -->
+ </string-array>
+
</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 2bef192..06f4123 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -5091,6 +5091,9 @@
<item quantity="other">Limiting battery usage for %1$d apps</item>
</plurals>
+ <!-- Summary for restricted app to show the restriction time [CHAR LIMIT=NONE] -->
+ <string name="restricted_app_time_summary">Restricted <xliff:g id="time" example="5 days ago">%1$s</xliff:g></string>
+
<!-- Footer message for restrict app details page -->
<string name="restricted_app_detail_footer">These apps have been using battery in the background. Restricted apps may not work properly and notifications may be delayed.</string>
@@ -9861,6 +9864,24 @@
]]>
</string>
+ <!-- Preference category for autofill debugging development settings. [CHAR LIMIT=25] -->
+ <string name="debug_autofill_category">Autofill</string>
+
+ <!-- UI debug setting: logging level for Android Autofill [CHAR LIMIT=25] -->
+ <string name="autofill_logging_level_title">Logging level</string>
+
+ <!-- Title of developer options to set the maximum number of partitions per session [CHAR LIMIT=60]-->
+ <string name="autofill_max_partitions">Max partitions</string>
+
+ <!-- Title of developer options to set the maximum number of visible datasets in the autofill UX [CHAR LIMIT=60]-->
+ <string name="autofill_max_visible_datasets">Max visible datasets</string>
+
+ <!-- Reset all autofill developer options to their default values.[CHAR_LIMIT=60] -->
+ <string name="autofill_reset_developer_options">Reset to default values</string>
+
+ <!-- Toast message shown when autofill_reset_developer_options has been performed. [CHAR_LIMIT=none] -->
+ <string name="autofill_reset_developer_options_complete">Autofill developer options have been reset</string>
+
<!-- Name of setting for switching device theme [CHAR LIMIT=60] -->
<string name="device_theme">Device theme</string>
<!-- Name of default device theme [CHAR LIMIT=60] -->
diff --git a/res/values/themes_suw.xml b/res/values/themes_suw.xml
index 11ef373..f09b2b1 100644
--- a/res/values/themes_suw.xml
+++ b/res/values/themes_suw.xml
@@ -18,8 +18,8 @@
<!-- SUW related themes -->
<resources>
<style name="GlifTheme" parent="SuwThemeGlif">
- <!-- For all Alert Dialogs -->
- <item name="android:alertDialogTheme">@style/ThemeOverlay.AlertDialog</item>
+ <!-- For all AndroidX Alert Dialogs -->
+ <item name="alertDialogTheme">@style/ThemeOverlay.AlertDialog</item>
<item name="android:windowBackground">?android:attr/colorBackground</item>
<item name="*android:preferencePanelStyle">@*android:style/PreferencePanel.Dialog</item>
<item name="fingerprint_layout_theme">@style/FingerprintLayoutTheme</item>
@@ -37,8 +37,8 @@
</style>
<style name="GlifTheme.Light" parent="SuwThemeGlif.Light">
- <!-- For all Alert Dialogs -->
- <item name="android:alertDialogTheme">@style/ThemeOverlay.AlertDialog</item>
+ <!-- For all AndroidX Alert Dialogs -->
+ <item name="alertDialogTheme">@style/ThemeOverlay.AlertDialog</item>
<item name="android:windowBackground">?android:attr/colorBackground</item>
<item name="*android:preferencePanelStyle">@*android:style/PreferencePanel.Dialog</item>
<item name="fingerprint_layout_theme">@style/FingerprintLayoutTheme</item>
@@ -56,8 +56,8 @@
</style>
<style name="GlifV2Theme" parent="SuwThemeGlifV2">
- <!-- For all Alert Dialogs -->
- <item name="android:alertDialogTheme">@style/GlifV2ThemeAlertDialog</item>
+ <!-- For all AndroidX Alert Dialogs -->
+ <item name="alertDialogTheme">@style/GlifV2ThemeAlertDialog</item>
<item name="android:windowBackground">?android:attr/colorBackground</item>
<item name="*android:preferencePanelStyle">@*android:style/PreferencePanel.Dialog</item>
<item name="fingerprint_layout_theme">@style/FingerprintLayoutTheme</item>
@@ -75,8 +75,8 @@
</style>
<style name="GlifV2Theme.Light" parent="SuwThemeGlifV2.Light">
- <!-- For all Alert Dialogs -->
- <item name="android:alertDialogTheme">@style/GlifV2ThemeAlertDialog.Light</item>
+ <!-- For all AndroidX Alert Dialogs -->
+ <item name="alertDialogTheme">@style/GlifV2ThemeAlertDialog.Light</item>
<item name="android:windowBackground">?android:attr/colorBackground</item>
<item name="*android:preferencePanelStyle">@*android:style/PreferencePanel.Dialog</item>
<item name="fingerprint_layout_theme">@style/FingerprintLayoutTheme</item>
@@ -94,8 +94,8 @@
</style>
<style name="GlifV3Theme" parent="SuwThemeGlifV3">
- <!-- For all Alert Dialogs -->
- <item name="android:alertDialogTheme">@style/GlifV2ThemeAlertDialog</item>
+ <!-- For all AndroidX Alert Dialogs -->
+ <item name="alertDialogTheme">@style/GlifV2ThemeAlertDialog</item>
<item name="android:windowBackground">?android:attr/colorBackground</item>
<item name="*android:preferencePanelStyle">@*android:style/PreferencePanel.Dialog</item>
<item name="fingerprint_layout_theme">@style/FingerprintLayoutTheme</item>
@@ -113,8 +113,8 @@
</style>
<style name="GlifV3Theme.Light" parent="SuwThemeGlifV3.Light">
- <!-- For all Alert Dialogs -->
- <item name="android:alertDialogTheme">@style/GlifV2ThemeAlertDialog.Light</item>
+ <!-- For all AndroidX Alert Dialogs -->
+ <item name="alertDialogTheme">@style/GlifV2ThemeAlertDialog.Light</item>
<item name="android:windowBackground">?android:attr/colorBackground</item>
<item name="*android:preferencePanelStyle">@*android:style/PreferencePanel.Dialog</item>
<item name="fingerprint_layout_theme">@style/FingerprintLayoutTheme</item>
@@ -145,11 +145,11 @@
<item name="android:windowAnimationStyle">@null</item>
</style>
- <style name="GlifV2ThemeAlertDialog" parent="SuwAlertDialogTheme">
+ <style name="GlifV2ThemeAlertDialog" parent="SuwAlertDialogThemeCompat">
<item name="android:windowSoftInputMode">adjustResize</item>
</style>
- <style name="GlifV2ThemeAlertDialog.Light" parent="SuwAlertDialogTheme.Light">
+ <style name="GlifV2ThemeAlertDialog.Light" parent="SuwAlertDialogThemeCompat.Light">
<item name="android:windowSoftInputMode">adjustResize</item>
</style>
@@ -190,4 +190,16 @@
<item name="preferenceTheme">@style/PreferenceTheme</item>
<item name="switchBarTheme">@style/ThemeOverlay.SwitchBar.Settings</item>
</style>
+
+ <style name="SuwAlertDialogThemeCompat" parent="@style/Theme.AppCompat.Dialog.Alert">
+ <!-- copied from Theme.DeviceDefault.Light.Dialog.Alert -->
+ <item name="colorAccent">@*android:color/accent_device_default_light</item>
+ <item name="dialogCornerRadius">@*android:dimen/config_dialogCornerRadius</item>
+ </style>
+
+ <style name="SuwAlertDialogThemeCompat.Light" parent="@style/Theme.AppCompat.Light.Dialog.Alert">
+ <!-- copied from Theme.DeviceDefault.Light.Dialog.Alert -->
+ <item name="colorAccent">@*android:color/accent_device_default_light</item>
+ <item name="dialogCornerRadius">@*android:dimen/config_dialogCornerRadius</item>
+ </style>
</resources>
\ No newline at end of file
diff --git a/res/xml/development_settings.xml b/res/xml/development_settings.xml
index 3d5f198..b0c7c9c 100644
--- a/res/xml/development_settings.xml
+++ b/res/xml/development_settings.xml
@@ -506,4 +506,29 @@
android:title="@string/reset_shortcut_manager_throttling" />
</PreferenceCategory>
+ <com.android.settings.development.autofill.AutofillPreferenceCategory
+ android:key="debug_autofill_category"
+ android:title="@string/debug_autofill_category"
+ android:order="1100">
+
+ <ListPreference
+ android:key="autofill_logging_level"
+ android:title="@string/autofill_logging_level_title"
+ android:entries="@array/autofill_logging_level_entries"
+ android:entryValues="@array/autofill_logging_level_values" />
+
+ <com.android.settings.development.autofill.AutofillMaxPartitionsPreference
+ android:key="autofill_max_partitions"
+ android:title="@string/autofill_max_partitions" />
+
+ <com.android.settings.development.autofill.AutofillVisibleDatasetsPreference
+ android:key="autofill_visible_datasets"
+ android:title="@string/autofill_max_visible_datasets" />
+
+ <Preference
+ android:key="autofill_reset_developer_options"
+ android:title="@string/autofill_reset_developer_options" />
+
+ </com.android.settings.development.autofill.AutofillPreferenceCategory>
+
</PreferenceScreen>
diff --git a/res/xml/power_usage_summary.xml b/res/xml/power_usage_summary.xml
index 4ff67b7..b4db4ed 100644
--- a/res/xml/power_usage_summary.xml
+++ b/res/xml/power_usage_summary.xml
@@ -23,12 +23,16 @@
<com.android.settings.applications.LayoutPreference
android:key="battery_header"
+ android:title="@string/summary_placeholder"
android:selectable="false"
- android:layout="@layout/battery_header" />
+ android:layout="@layout/battery_header"
+ settings:controller="com.android.settings.fuelgauge.BatteryHeaderPreferenceController" />
<PreferenceCategory
android:key="battery_tip"
- android:layout="@layout/preference_category_no_label" />
+ android:title="@string/summary_placeholder"
+ android:layout="@layout/preference_category_no_label"
+ settings:controller="com.android.settings.fuelgauge.batterytip.BatteryTipPreferenceController" />
<Preference
android:fragment="com.android.settings.fuelgauge.batterysaver.BatterySaverSettings"
@@ -47,7 +51,8 @@
<SwitchPreference
android:key="battery_percentage"
android:title="@string/battery_percentage"
- android:summary="@string/battery_percentage_description" />
+ android:summary="@string/battery_percentage_description"
+ settings:controller="com.android.settings.display.BatteryPercentagePreferenceController" />
<com.android.settings.fuelgauge.PowerGaugePreference
diff --git a/src/com/android/settings/FallbackHome.java b/src/com/android/settings/FallbackHome.java
index 7d5948e..59347ad 100644
--- a/src/com/android/settings/FallbackHome.java
+++ b/src/com/android/settings/FallbackHome.java
@@ -19,6 +19,7 @@
import android.app.Activity;
import android.app.WallpaperColors;
import android.app.WallpaperManager;
+import android.app.WallpaperManager.OnColorsChangedListener;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -44,6 +45,7 @@
private static final int PROGRESS_TIMEOUT = 2000;
private boolean mProvisioned;
+ private WallpaperManager mWallManager;
private final Runnable mProgressTimeoutRunnable = () -> {
View v = getLayoutInflater().inflate(
@@ -59,6 +61,18 @@
getWindow().addFlags(LayoutParams.FLAG_KEEP_SCREEN_ON);
};
+ private final OnColorsChangedListener mColorsChangedListener = new OnColorsChangedListener() {
+ @Override
+ public void onColorsChanged(WallpaperColors colors, int which) {
+ if (colors != null) {
+ View decorView = getWindow().getDecorView();
+ decorView.setSystemUiVisibility(
+ updateVisibilityFlagsFromColors(colors, decorView.getSystemUiVisibility()));
+ mWallManager.removeOnColorsChangedListener(this);
+ }
+ }
+ };
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -78,13 +92,17 @@
}
// Set the system ui flags to light status bar if the wallpaper supports dark text to match
- // current system ui color tints.
- final WallpaperColors colors = getSystemService(WallpaperManager.class)
- .getWallpaperColors(WallpaperManager.FLAG_SYSTEM);
- if (colors != null
- && (colors.getColorHints() & WallpaperColors.HINT_SUPPORTS_DARK_TEXT) != 0) {
- flags |= View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
- | View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
+ // current system ui color tints. Use a listener to wait for colors if not ready yet.
+ mWallManager = getSystemService(WallpaperManager.class);
+ if (mWallManager == null) {
+ Log.w(TAG, "Wallpaper manager isn't ready, can't listen to color changes!");
+ } else {
+ WallpaperColors colors = mWallManager.getWallpaperColors(WallpaperManager.FLAG_SYSTEM);
+ if (colors == null) {
+ mWallManager.addOnColorsChangedListener(mColorsChangedListener, null /* handler */);
+ } else {
+ flags = updateVisibilityFlagsFromColors(colors, flags);
+ }
}
getWindow().getDecorView().setSystemUiVisibility(flags);
@@ -109,6 +127,9 @@
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(mReceiver);
+ if (mWallManager != null) {
+ mWallManager.removeOnColorsChangedListener(mColorsChangedListener);
+ }
}
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
@@ -141,6 +162,15 @@
}
}
+ private int updateVisibilityFlagsFromColors(WallpaperColors colors, int flags) {
+ if ((colors.getColorHints() & WallpaperColors.HINT_SUPPORTS_DARK_TEXT) != 0) {
+ return flags | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
+ | View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
+ }
+ return flags & ~(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR)
+ & ~(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR);
+ }
+
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
diff --git a/src/com/android/settings/dashboard/DashboardAdapter.java b/src/com/android/settings/dashboard/DashboardAdapter.java
index d93f2ed..b278f60 100644
--- a/src/com/android/settings/dashboard/DashboardAdapter.java
+++ b/src/com/android/settings/dashboard/DashboardAdapter.java
@@ -315,7 +315,7 @@
@VisibleForTesting
void onBindTile(DashboardItemHolder holder, Tile tile) {
- Icon tileIcon = tile.getIcon();
+ Icon tileIcon = tile.getIcon(mContext);
Drawable icon = mCache.getIcon(tileIcon);
if (!TextUtils.equals(tileIcon.getResPackage(), mContext.getPackageName())
&& !(icon instanceof RoundedHomepageIcon)) {
diff --git a/src/com/android/settings/dashboard/DashboardFeatureProviderImpl.java b/src/com/android/settings/dashboard/DashboardFeatureProviderImpl.java
index 1f7a011..a3410bd 100644
--- a/src/com/android/settings/dashboard/DashboardFeatureProviderImpl.java
+++ b/src/com/android/settings/dashboard/DashboardFeatureProviderImpl.java
@@ -34,6 +34,9 @@
import android.util.Log;
import android.util.Pair;
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.Preference;
+
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
@@ -50,9 +53,6 @@
import java.util.List;
import java.util.Map;
-import androidx.annotation.VisibleForTesting;
-import androidx.preference.Preference;
-
/**
* Impl for {@code DashboardFeatureProvider}.
*/
@@ -238,7 +238,7 @@
@VisibleForTesting
void bindIcon(Preference preference, Tile tile) {
- final Icon tileIcon = tile.getIcon();
+ final Icon tileIcon = tile.getIcon(mContext);
if (tileIcon != null) {
preference.setIcon(tileIcon.loadDrawable(preference.getContext()));
} else if (tile.metaData != null
diff --git a/src/com/android/settings/dashboard/DashboardFragment.java b/src/com/android/settings/dashboard/DashboardFragment.java
index aa91b2f..fceec3b 100644
--- a/src/com/android/settings/dashboard/DashboardFragment.java
+++ b/src/com/android/settings/dashboard/DashboardFragment.java
@@ -24,6 +24,11 @@
import android.util.ArraySet;
import android.util.Log;
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceManager;
+import androidx.preference.PreferenceScreen;
+
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.core.PreferenceControllerListHelper;
@@ -43,11 +48,6 @@
import java.util.Map;
import java.util.Set;
-import androidx.annotation.VisibleForTesting;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceManager;
-import androidx.preference.PreferenceScreen;
-
/**
* Base fragment for dashboard style UI containing a list of static and dynamic setting items.
*/
@@ -256,7 +256,8 @@
@VisibleForTesting
boolean tintTileIcon(Tile tile) {
- if (tile.getIcon() == null) {
+ final Context context = getContext();
+ if (tile.getIcon(context) == null) {
return false;
}
// First check if the tile has set the icon tintable metadata.
@@ -265,7 +266,7 @@
&& metadata.containsKey(TileUtils.META_DATA_PREFERENCE_ICON_TINTABLE)) {
return metadata.getBoolean(TileUtils.META_DATA_PREFERENCE_ICON_TINTABLE);
}
- final String pkgName = getContext().getPackageName();
+ final String pkgName = context.getPackageName();
// If this drawable is coming from outside Settings, tint it to match the color.
return pkgName != null && tile.intent != null
&& !pkgName.equals(tile.intent.getComponent().getPackageName());
@@ -370,7 +371,7 @@
continue;
}
if (tintTileIcon(tile)) {
- tile.getIcon().setTint(tintColor);
+ tile.getIcon(context).setTint(tintColor);
}
if (mDashboardTilePrefKeys.contains(key)) {
// Have the key already, will rebind.
diff --git a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
index 82ca54b..5be381a 100644
--- a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
+++ b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
@@ -39,6 +39,8 @@
import com.android.settings.SettingsActivity;
import com.android.settings.Utils;
import com.android.settings.dashboard.RestrictedDashboardFragment;
+import com.android.settings.development.autofill.AutofillLoggingLevelPreferenceController;
+import com.android.settings.development.autofill.AutofillResetOptionsPreferenceController;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.Indexable;
import com.android.settings.widget.SwitchBar;
@@ -466,6 +468,8 @@
controllers.add(new DefaultLaunchPreferenceController(context, "density"));
controllers.add(new DefaultLaunchPreferenceController(context, "background_check"));
controllers.add(new DefaultLaunchPreferenceController(context, "inactive_apps"));
+ controllers.add(new AutofillLoggingLevelPreferenceController(context));
+ controllers.add(new AutofillResetOptionsPreferenceController(context));
return controllers;
}
diff --git a/src/com/android/settings/development/autofill/AbstractGlobalSettingsPreference.java b/src/com/android/settings/development/autofill/AbstractGlobalSettingsPreference.java
new file mode 100644
index 0000000..080c387
--- /dev/null
+++ b/src/com/android/settings/development/autofill/AbstractGlobalSettingsPreference.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.settings.development.autofill;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.provider.Settings;
+import android.text.BidiFormatter;
+import android.text.InputType;
+import android.util.AttributeSet;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.util.Slog;
+import android.view.Display;
+import android.view.View;
+import android.view.autofill.AutofillManager;
+import android.widget.EditText;
+
+import com.android.settings.R;
+import com.android.settings.Utils;
+import com.android.settingslib.CustomEditTextPreferenceCompat;
+
+import java.text.NumberFormat;
+
+/**
+ * Base class for Autofill integer properties that are backed by
+ * {@link android.provider.Settings.Global}.
+ */
+abstract class AbstractGlobalSettingsPreference extends CustomEditTextPreferenceCompat {
+
+ private static final String TAG = "AbstractGlobalSettingsPreference";
+
+ private final String mKey;
+ private final int mDefaultValue;
+
+ private final AutofillDeveloperSettingsObserver mObserver;
+
+ protected AbstractGlobalSettingsPreference(Context context, AttributeSet attrs,
+ String key, int defaultValue) {
+ super(context, attrs);
+
+ mKey = key;
+ mDefaultValue = defaultValue;
+ mObserver = new AutofillDeveloperSettingsObserver(context, () -> updateSummary());
+ }
+
+ @Override
+ public void onAttached() {
+ super.onAttached();
+
+ mObserver.register();
+ updateSummary();
+ }
+
+ @Override
+ public void onDetached() {
+ mObserver.unregister();
+
+ super.onDetached();
+ }
+
+ private String getCurrentValue() {
+ final int value = Settings.Global.getInt(getContext().getContentResolver(),
+ mKey, mDefaultValue);
+
+ return Integer.toString(value);
+ }
+
+ private void updateSummary() {
+ setSummary(getCurrentValue());
+
+ }
+
+ @Override
+ protected void onBindDialogView(View view) {
+ super.onBindDialogView(view);
+
+ EditText editText = view.findViewById(android.R.id.edit);
+ if (editText != null) {
+ editText.setInputType(InputType.TYPE_CLASS_NUMBER);
+ editText.setText(getCurrentValue());
+ Utils.setEditTextCursorPosition(editText);
+ }
+ }
+
+ @Override
+ protected void onDialogClosed(boolean positiveResult) {
+ if (positiveResult) {
+ final String stringValue = getText();
+ int newValue = mDefaultValue;
+ try {
+ newValue = Integer.parseInt(stringValue);
+ } catch (Exception e) {
+ Log.e(TAG, "Error converting '" + stringValue + "' to integer. Using "
+ + mDefaultValue + " instead");
+ }
+ Settings.Global.putInt(getContext().getContentResolver(), mKey, newValue);
+ }
+ }
+}
diff --git a/src/com/android/settings/development/autofill/AutofillDeveloperSettingsObserver.java b/src/com/android/settings/development/autofill/AutofillDeveloperSettingsObserver.java
new file mode 100644
index 0000000..ae8e246
--- /dev/null
+++ b/src/com/android/settings/development/autofill/AutofillDeveloperSettingsObserver.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.development.autofill;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.UserHandle;
+import android.provider.Settings;
+
+final class AutofillDeveloperSettingsObserver extends ContentObserver {
+
+ private final Runnable mChangeCallback;
+ private final ContentResolver mResolver;
+
+ public AutofillDeveloperSettingsObserver(Context context, Runnable changeCallback) {
+ super(new Handler());
+
+ mResolver = context.getContentResolver();
+ mChangeCallback = changeCallback;
+ }
+
+ public void register() {
+ mResolver.registerContentObserver(Settings.Global.getUriFor(
+ Settings.Global.AUTOFILL_LOGGING_LEVEL), false, this,
+ UserHandle.USER_ALL);
+ mResolver.registerContentObserver(Settings.Global.getUriFor(
+ Settings.Global.AUTOFILL_MAX_PARTITIONS_SIZE), false, this,
+ UserHandle.USER_ALL);
+ mResolver.registerContentObserver(Settings.Global.getUriFor(
+ Settings.Global.AUTOFILL_MAX_VISIBLE_DATASETS), false, this,
+ UserHandle.USER_ALL);
+ }
+
+ public void unregister() {
+ mResolver.unregisterContentObserver(this);
+ }
+
+ @Override
+ public void onChange(boolean selfChange, Uri uri, int userId) {
+ mChangeCallback.run(); // Run Forrest, Run!
+ }
+}
diff --git a/src/com/android/settings/development/autofill/AutofillLoggingLevelPreferenceController.java b/src/com/android/settings/development/autofill/AutofillLoggingLevelPreferenceController.java
new file mode 100644
index 0000000..a22295c
--- /dev/null
+++ b/src/com/android/settings/development/autofill/AutofillLoggingLevelPreferenceController.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.development.autofill;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.provider.Settings;
+import android.view.autofill.AutofillManager;
+
+import com.android.settings.R;
+import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settingslib.development.DeveloperOptionsPreferenceController;
+
+import androidx.preference.ListPreference;
+import androidx.preference.Preference;
+
+public final class AutofillLoggingLevelPreferenceController
+ extends DeveloperOptionsPreferenceController
+ implements PreferenceControllerMixin, Preference.OnPreferenceChangeListener {
+
+ private static final String AUTOFILL_LOGGING_LEVEL_KEY = "autofill_logging_level";
+
+ private final String[] mListValues;
+ private final String[] mListSummaries;
+ private final AutofillDeveloperSettingsObserver mObserver;
+
+ public AutofillLoggingLevelPreferenceController(Context context) {
+ super(context);
+
+ Resources resources = context.getResources();
+ mListValues = resources.getStringArray(R.array.autofill_logging_level_values);
+ mListSummaries = resources.getStringArray(R.array.autofill_logging_level_entries);
+ mObserver = new AutofillDeveloperSettingsObserver(mContext, () -> updateOptions());
+ mObserver.register();
+ // TODO: there should be a hook on AbstractPreferenceController where we could unregister it
+ }
+
+ @Override
+ public String getPreferenceKey() {
+ return AUTOFILL_LOGGING_LEVEL_KEY;
+ }
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ writeLevel(newValue);
+ updateOptions();
+ return true;
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ updateOptions();
+ }
+
+ @Override
+ protected void onDeveloperOptionsSwitchDisabled() {
+ super.onDeveloperOptionsSwitchDisabled();
+ writeLevel(null);
+ }
+
+ private void updateOptions() {
+ final int level = Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.AUTOFILL_LOGGING_LEVEL, AutofillManager.DEFAULT_LOGGING_LEVEL);
+
+ final int index;
+ if (level == AutofillManager.FLAG_ADD_CLIENT_DEBUG) {
+ index = 1;
+ } else if (level == AutofillManager.FLAG_ADD_CLIENT_VERBOSE) {
+ index = 2;
+ } else {
+ index = 0;
+ }
+ final ListPreference listPreference = (ListPreference) mPreference;
+ listPreference.setValue(mListValues[index]);
+ listPreference.setSummary(mListSummaries[index]);
+ }
+
+ private void writeLevel(Object newValue) {
+ int level = AutofillManager.NO_LOGGING;
+ if (newValue instanceof String) {
+ level = Integer.parseInt((String) newValue);
+ }
+ Settings.Global.putInt(mContext.getContentResolver(),
+ Settings.Global.AUTOFILL_LOGGING_LEVEL, level);
+ }
+}
diff --git a/src/com/android/settings/development/autofill/AutofillMaxPartitionsPreference.java b/src/com/android/settings/development/autofill/AutofillMaxPartitionsPreference.java
new file mode 100644
index 0000000..ab0cec9
--- /dev/null
+++ b/src/com/android/settings/development/autofill/AutofillMaxPartitionsPreference.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.settings.development.autofill;
+
+import android.content.Context;
+import android.provider.Settings;
+import android.util.AttributeSet;
+import android.view.autofill.AutofillManager;
+
+import java.text.NumberFormat;
+
+public final class AutofillMaxPartitionsPreference extends AbstractGlobalSettingsPreference {
+
+ public AutofillMaxPartitionsPreference(Context context, AttributeSet attrs) {
+ super(context, attrs, Settings.Global.AUTOFILL_MAX_PARTITIONS_SIZE,
+ AutofillManager.DEFAULT_MAX_PARTITIONS_SIZE);
+ }
+}
diff --git a/src/com/android/settings/development/autofill/AutofillPreferenceCategory.java b/src/com/android/settings/development/autofill/AutofillPreferenceCategory.java
new file mode 100644
index 0000000..ed07f62
--- /dev/null
+++ b/src/com/android/settings/development/autofill/AutofillPreferenceCategory.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.settings.development.autofill;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.autofill.AutofillManager;
+
+import androidx.preference.PreferenceCategory;
+
+public final class AutofillPreferenceCategory extends PreferenceCategory {
+
+ private static final String TAG = "AutofillPreferenceCategory";
+
+ private final ContentResolver mContentResolver;
+ private final ContentObserver mSettingsObserver;
+
+ public AutofillPreferenceCategory(Context context, AttributeSet attrs) {
+ super(context, attrs);
+
+ mSettingsObserver = new ContentObserver(new Handler()) {
+ @Override
+ public void onChange(boolean selfChange, Uri uri, int userId) {
+ Log.w(TAG, "Autofill Service changed, but UI cannot be refreshed");
+ // TODO(b/111838239): we cannot update the UI because AFM.isEnabled() will return
+ // the previous value. Once that's fixed, we'll need to call one of the 2 callbacks
+ // below:
+ // notifyChanged();
+ // notifyDependencyChange(shouldDisableDependents());
+ }
+ };
+ mContentResolver = context.getContentResolver();
+ }
+
+ @Override
+ public void onAttached() {
+ super.onAttached();
+
+ mContentResolver.registerContentObserver(
+ Settings.Secure.getUriFor(Settings.Secure.AUTOFILL_SERVICE), false,
+ mSettingsObserver);
+ }
+
+ @Override
+ public void onDetached() {
+ mContentResolver.unregisterContentObserver(mSettingsObserver);
+
+ super.onDetached();
+ }
+
+ // PreferenceCategory.isEnabled() always return false, so we rather not change that logic
+ // decide whether the children should be shown using isAutofillEnabled() instead.
+ private boolean isAutofillEnabled() {
+ final AutofillManager afm = getContext().getSystemService(AutofillManager.class);
+ final boolean enabled = afm != null && afm.isEnabled();
+ Log.v(TAG, "isAutofillEnabled(): " + enabled);
+ return enabled;
+ }
+
+ @Override
+ public boolean shouldDisableDependents() {
+ final boolean shouldIt = !isAutofillEnabled();
+ Log.v(TAG, "shouldDisableDependents(): " + shouldIt);
+ return shouldIt;
+ }
+}
diff --git a/src/com/android/settings/development/autofill/AutofillResetOptionsPreferenceController.java b/src/com/android/settings/development/autofill/AutofillResetOptionsPreferenceController.java
new file mode 100644
index 0000000..42f7a48
--- /dev/null
+++ b/src/com/android/settings/development/autofill/AutofillResetOptionsPreferenceController.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.development.autofill;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.res.Resources;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.view.autofill.AutofillManager;
+import android.widget.Toast;
+
+import com.android.settings.R;
+import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settingslib.development.DeveloperOptionsPreferenceController;
+
+import androidx.preference.ListPreference;
+import androidx.preference.Preference;
+
+public final class AutofillResetOptionsPreferenceController
+ extends DeveloperOptionsPreferenceController
+ implements PreferenceControllerMixin {
+
+ private static final String AUTOFILL_RESET_OPTIONS_KEY = "autofill_reset_developer_options";
+
+ public AutofillResetOptionsPreferenceController(Context context) {
+ super(context);
+ }
+
+ @Override
+ public String getPreferenceKey() {
+ return AUTOFILL_RESET_OPTIONS_KEY;
+ }
+
+ @Override
+ public boolean handlePreferenceTreeClick(Preference preference) {
+ if (!TextUtils.equals(AUTOFILL_RESET_OPTIONS_KEY, preference.getKey())) {
+ return false;
+ }
+ final ContentResolver contentResolver = mContext.getContentResolver();
+ Settings.Global.putInt(contentResolver, Settings.Global.AUTOFILL_LOGGING_LEVEL,
+ AutofillManager.DEFAULT_LOGGING_LEVEL);
+ Settings.Global.putInt(contentResolver, Settings.Global.AUTOFILL_MAX_PARTITIONS_SIZE,
+ AutofillManager.DEFAULT_MAX_PARTITIONS_SIZE);
+ Settings.Global.putInt(contentResolver, Settings.Global.AUTOFILL_MAX_VISIBLE_DATASETS, 0);
+ Toast.makeText(mContext, R.string.autofill_reset_developer_options_complete,
+ Toast.LENGTH_SHORT).show();
+ return true;
+ }
+}
diff --git a/src/com/android/settings/development/autofill/AutofillVisibleDatasetsPreference.java b/src/com/android/settings/development/autofill/AutofillVisibleDatasetsPreference.java
new file mode 100644
index 0000000..2f0d15f
--- /dev/null
+++ b/src/com/android/settings/development/autofill/AutofillVisibleDatasetsPreference.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.settings.development.autofill;
+
+import android.content.Context;
+import android.provider.Settings;
+import android.util.AttributeSet;
+
+public final class AutofillVisibleDatasetsPreference extends AbstractGlobalSettingsPreference {
+
+ public AutofillVisibleDatasetsPreference(Context context, AttributeSet attrs) {
+ super(context, attrs, Settings.Global.AUTOFILL_MAX_VISIBLE_DATASETS, 0);
+ }
+}
diff --git a/src/com/android/settings/display/BatteryPercentagePreferenceController.java b/src/com/android/settings/display/BatteryPercentagePreferenceController.java
index 0bd4445..50fbc64 100644
--- a/src/com/android/settings/display/BatteryPercentagePreferenceController.java
+++ b/src/com/android/settings/display/BatteryPercentagePreferenceController.java
@@ -21,8 +21,8 @@
import android.provider.Settings;
import com.android.internal.R;
+import com.android.settings.core.BasePreferenceController;
import com.android.settings.core.PreferenceControllerMixin;
-import com.android.settingslib.core.AbstractPreferenceController;
import androidx.preference.Preference;
import androidx.preference.SwitchPreference;
@@ -31,24 +31,18 @@
* A controller to manage the switch for showing battery percentage in the status bar.
*/
-public class BatteryPercentagePreferenceController extends AbstractPreferenceController implements
+public class BatteryPercentagePreferenceController extends BasePreferenceController implements
PreferenceControllerMixin, Preference.OnPreferenceChangeListener {
- private static final String KEY_BATTERY_PERCENTAGE = "battery_percentage";
-
- public BatteryPercentagePreferenceController(Context context) {
- super(context);
+ public BatteryPercentagePreferenceController(Context context, String preferenceKey) {
+ super(context, preferenceKey);
}
@Override
- public boolean isAvailable() {
- return mContext.getResources()
- .getBoolean(R.bool.config_battery_percentage_setting_available);
- }
-
- @Override
- public String getPreferenceKey() {
- return KEY_BATTERY_PERCENTAGE;
+ public int getAvailabilityStatus() {
+ return mContext.getResources().getBoolean(
+ R.bool.config_battery_percentage_setting_available) ? AVAILABLE
+ : UNSUPPORTED_ON_DEVICE;
}
@Override
diff --git a/src/com/android/settings/fuelgauge/BatteryHeaderPreferenceController.java b/src/com/android/settings/fuelgauge/BatteryHeaderPreferenceController.java
index 71eb554..5b5f50a 100644
--- a/src/com/android/settings/fuelgauge/BatteryHeaderPreferenceController.java
+++ b/src/com/android/settings/fuelgauge/BatteryHeaderPreferenceController.java
@@ -27,6 +27,7 @@
import com.android.settings.R;
import com.android.settings.applications.LayoutPreference;
+import com.android.settings.core.BasePreferenceController;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settings.widget.EntityHeaderController;
import com.android.settingslib.Utils;
@@ -42,7 +43,7 @@
/**
* Controller that update the battery header view
*/
-public class BatteryHeaderPreferenceController extends AbstractPreferenceController
+public class BatteryHeaderPreferenceController extends BasePreferenceController
implements PreferenceControllerMixin, LifecycleObserver, OnStart {
@VisibleForTesting
static final String KEY_BATTERY_HEADER = "battery_header";
@@ -56,30 +57,35 @@
@VisibleForTesting
TextView mSummary2;
- private final Activity mActivity;
- private final PreferenceFragmentCompat mHost;
- private final Lifecycle mLifecycle;
+ private Activity mActivity;
+ private PreferenceFragmentCompat mHost;
+ private Lifecycle mLifecycle;
private final PowerManager mPowerManager;
private LayoutPreference mBatteryLayoutPref;
- public BatteryHeaderPreferenceController(Context context, Activity activity,
- PreferenceFragmentCompat host, Lifecycle lifecycle) {
- super(context);
- mActivity = activity;
- mHost = host;
- mLifecycle = lifecycle;
- if (mLifecycle != null) {
- mLifecycle.addObserver(this);
- }
+ public BatteryHeaderPreferenceController(Context context, String key) {
+ super(context, key);
mPowerManager = context.getSystemService(PowerManager.class);
}
+ public void setActivity(Activity activity) {
+ mActivity = activity;
+ }
+
+ public void setFragment(PreferenceFragmentCompat fragment) {
+ mHost = fragment;
+ }
+
+ public void setLifecycle(Lifecycle lifecycle) {
+ mLifecycle = lifecycle;
+ }
+
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
- mBatteryLayoutPref = (LayoutPreference) screen.findPreference(KEY_BATTERY_HEADER);
- mBatteryMeterView = (BatteryMeterView) mBatteryLayoutPref
+ mBatteryLayoutPref = (LayoutPreference) screen.findPreference(getPreferenceKey());
+ mBatteryMeterView = mBatteryLayoutPref
.findViewById(R.id.battery_header_icon);
mBatteryPercentText = mBatteryLayoutPref.findViewById(R.id.battery_percent);
mSummary1 = mBatteryLayoutPref.findViewById(R.id.summary1);
@@ -89,13 +95,8 @@
}
@Override
- public boolean isAvailable() {
- return true;
- }
-
- @Override
- public String getPreferenceKey() {
- return KEY_BATTERY_HEADER;
+ public int getAvailabilityStatus() {
+ return AVAILABLE_UNSEARCHABLE;
}
@Override
diff --git a/src/com/android/settings/fuelgauge/BatteryUtils.java b/src/com/android/settings/fuelgauge/BatteryUtils.java
index 9e920c4..3676761 100644
--- a/src/com/android/settings/fuelgauge/BatteryUtils.java
+++ b/src/com/android/settings/fuelgauge/BatteryUtils.java
@@ -38,11 +38,14 @@
import com.android.internal.os.BatteryStatsHelper;
import com.android.internal.util.ArrayUtils;
import com.android.settings.R;
+import com.android.settings.fuelgauge.batterytip.AnomalyDatabaseHelper;
import com.android.settings.fuelgauge.batterytip.AnomalyInfo;
+import com.android.settings.fuelgauge.batterytip.BatteryDatabaseManager;
import com.android.settings.fuelgauge.batterytip.StatsManagerConfig;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.fuelgauge.PowerWhitelistBackend;
import com.android.settingslib.utils.PowerUtil;
+import com.android.settingslib.utils.ThreadUtils;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -101,8 +104,8 @@
mContext = context;
mPackageManager = context.getPackageManager();
mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
- mPowerUsageFeatureProvider = FeatureFactory.getFactory(
- context).getPowerUsageFeatureProvider(context);
+ mPowerUsageFeatureProvider = FeatureFactory.getFactory(context)
+ .getPowerUsageFeatureProvider(context);
}
public long getProcessTimeMs(@StatusType int type, @Nullable BatteryStats.Uid uid,
@@ -400,6 +403,18 @@
}
// Control whether app could run jobs in the background
mAppOpsManager.setMode(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, uid, packageName, mode);
+
+ ThreadUtils.postOnBackgroundThread(() -> {
+ final BatteryDatabaseManager batteryDatabaseManager = BatteryDatabaseManager
+ .getInstance(mContext);
+ if (mode == AppOpsManager.MODE_IGNORED) {
+ batteryDatabaseManager.insertAction(AnomalyDatabaseHelper.ActionType.RESTRICTION,
+ uid, packageName, System.currentTimeMillis());
+ } else if (mode == AppOpsManager.MODE_ALLOWED) {
+ batteryDatabaseManager.deleteAction(AnomalyDatabaseHelper.ActionType.RESTRICTION,
+ uid, packageName);
+ }
+ });
}
public boolean isForceAppStandbyEnabled(int uid, String packageName) {
diff --git a/src/com/android/settings/fuelgauge/PowerUsageSummary.java b/src/com/android/settings/fuelgauge/PowerUsageSummary.java
index 843aeec..2ae5876 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageSummary.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageSummary.java
@@ -25,7 +25,6 @@
import android.provider.SearchIndexableResource;
import android.text.BidiFormatter;
import android.text.format.Formatter;
-import android.util.SparseArray;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
@@ -40,19 +39,15 @@
import com.android.settings.applications.LayoutPreference;
import com.android.settings.core.SubSettingLauncher;
import com.android.settings.dashboard.SummaryLoader;
-import com.android.settings.display.BatteryPercentagePreferenceController;
import com.android.settings.fuelgauge.batterytip.BatteryTipLoader;
import com.android.settings.fuelgauge.batterytip.BatteryTipPreferenceController;
import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.search.BaseSearchIndexProvider;
-import com.android.settingslib.core.AbstractPreferenceController;
-import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.search.SearchIndexable;
import com.android.settingslib.utils.PowerUtil;
import com.android.settingslib.utils.StringUtil;
-import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -198,6 +193,22 @@
};
@Override
+ public void onAttach(Context context) {
+ super.onAttach(context);
+ final SettingsActivity activity = (SettingsActivity) getActivity();
+
+ mBatteryHeaderPreferenceController = use(BatteryHeaderPreferenceController.class);
+ mBatteryHeaderPreferenceController.setActivity(activity);
+ mBatteryHeaderPreferenceController.setFragment(this);
+ mBatteryHeaderPreferenceController.setLifecycle(getSettingsLifecycle());
+
+ mBatteryTipPreferenceController = use(BatteryTipPreferenceController.class);
+ mBatteryTipPreferenceController.setActivity(activity);
+ mBatteryTipPreferenceController.setFragment(this);
+ mBatteryTipPreferenceController.setBatteryTipListener(this::onBatteryTipHandled);
+ }
+
+ @Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setAnimationAllowed(true);
@@ -232,22 +243,6 @@
}
@Override
- protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
- final Lifecycle lifecycle = getSettingsLifecycle();
- final SettingsActivity activity = (SettingsActivity) getActivity();
- final List<AbstractPreferenceController> controllers = new ArrayList<>();
- mBatteryHeaderPreferenceController = new BatteryHeaderPreferenceController(
- context, activity, this /* host */, lifecycle);
- controllers.add(mBatteryHeaderPreferenceController);
- mBatteryTipPreferenceController = new BatteryTipPreferenceController(context,
- KEY_BATTERY_TIP, (SettingsActivity) getActivity(), this /* fragment */, this /*
- BatteryTipListener */);
- controllers.add(mBatteryTipPreferenceController);
- controllers.add(new BatteryPercentagePreferenceController(context));
- return controllers;
- }
-
- @Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
if (DEBUG) {
menu.add(Menu.NONE, MENU_STATS_TYPE, Menu.NONE, R.string.menu_stats_total)
diff --git a/src/com/android/settings/fuelgauge/RestrictedAppDetails.java b/src/com/android/settings/fuelgauge/RestrictedAppDetails.java
index 4934bce..b64a707 100644
--- a/src/com/android/settings/fuelgauge/RestrictedAppDetails.java
+++ b/src/com/android/settings/fuelgauge/RestrictedAppDetails.java
@@ -22,6 +22,8 @@
import android.os.Bundle;
import android.os.UserHandle;
import android.util.IconDrawableFactory;
+import android.util.Log;
+import android.util.SparseLongArray;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
@@ -29,7 +31,9 @@
import com.android.settings.core.InstrumentedPreferenceFragment;
import com.android.settings.core.SubSettingLauncher;
import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.fuelgauge.batterytip.AnomalyDatabaseHelper;
import com.android.settings.fuelgauge.batterytip.AppInfo;
+import com.android.settings.fuelgauge.batterytip.BatteryDatabaseManager;
import com.android.settings.fuelgauge.batterytip.BatteryTipDialogFragment;
import com.android.settings.fuelgauge.batterytip.BatteryTipPreferenceController;
import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
@@ -37,6 +41,7 @@
import com.android.settings.fuelgauge.batterytip.tips.UnrestrictAppTip;
import com.android.settings.widget.AppCheckBoxPreference;
import com.android.settingslib.core.AbstractPreferenceController;
+import com.android.settingslib.utils.StringUtil;
import com.android.settingslib.widget.FooterPreferenceMixinCompat;
import java.util.List;
@@ -57,6 +62,7 @@
@VisibleForTesting
static final String EXTRA_APP_INFO_LIST = "app_info_list";
private static final String KEY_PREF_RESTRICTED_APP_LIST = "restrict_app_list";
+ private static final long TIME_NULL = -1;
@VisibleForTesting
List<AppInfo> mAppInfos;
@@ -68,6 +74,8 @@
BatteryUtils mBatteryUtils;
@VisibleForTesting
PackageManager mPackageManager;
+ @VisibleForTesting
+ BatteryDatabaseManager mBatteryDatabaseManager;
private final FooterPreferenceMixinCompat mFooterPreferenceMixin =
new FooterPreferenceMixinCompat(this, getSettingsLifecycle());
@@ -96,6 +104,7 @@
mPackageManager = context.getPackageManager();
mIconDrawableFactory = IconDrawableFactory.newInstance(context);
mBatteryUtils = BatteryUtils.getInstance(context);
+ mBatteryDatabaseManager = BatteryDatabaseManager.getInstance(context);
refreshUi();
}
@@ -135,6 +144,9 @@
void refreshUi() {
mRestrictedAppListGroup.removeAll();
final Context context = getPrefContext();
+ final SparseLongArray timestampArray = mBatteryDatabaseManager
+ .queryActionTime(AnomalyDatabaseHelper.ActionType.RESTRICTION);
+ final long now = System.currentTimeMillis();
for (int i = 0, size = mAppInfos.size(); i < size; i++) {
final CheckBoxPreference checkBoxPreference = new AppCheckBoxPreference(context);
@@ -158,9 +170,16 @@
return false;
});
+
+ final long timestamp = timestampArray.get(appInfo.uid, TIME_NULL);
+ if (timestamp != TIME_NULL) {
+ checkBoxPreference.setSummary(getString(R.string.restricted_app_time_summary,
+ StringUtil.formatRelativeTime(context, now - timestamp, false)));
+ }
+ final CharSequence test = checkBoxPreference.getSummaryOn();
mRestrictedAppListGroup.addPreference(checkBoxPreference);
} catch (PackageManager.NameNotFoundException e) {
- e.printStackTrace();
+ Log.e(TAG, "Can't find package: " + appInfo.packageName);
}
}
}
diff --git a/src/com/android/settings/fuelgauge/batterytip/AnomalyDatabaseHelper.java b/src/com/android/settings/fuelgauge/batterytip/AnomalyDatabaseHelper.java
index bc332b6..bd1633f 100644
--- a/src/com/android/settings/fuelgauge/batterytip/AnomalyDatabaseHelper.java
+++ b/src/com/android/settings/fuelgauge/batterytip/AnomalyDatabaseHelper.java
@@ -33,7 +33,7 @@
private static final String TAG = "BatteryDatabaseHelper";
private static final String DATABASE_NAME = "battery_settings.db";
- private static final int DATABASE_VERSION = 4;
+ private static final int DATABASE_VERSION = 5;
@Retention(RetentionPolicy.SOURCE)
@IntDef({State.NEW,
@@ -45,8 +45,15 @@
int AUTO_HANDLED = 2;
}
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({ActionType.RESTRICTION})
+ public @interface ActionType {
+ int RESTRICTION = 0;
+ }
+
public interface Tables {
String TABLE_ANOMALY = "anomaly";
+ String TABLE_ACTION = "action";
}
public interface AnomalyColumns {
@@ -91,6 +98,42 @@
+ AnomalyColumns.ANOMALY_STATE + "," + AnomalyColumns.TIME_STAMP_MS + ")"
+ ")";
+
+ public interface ActionColumns {
+ /**
+ * The package name of an app been performed an action
+ */
+ String PACKAGE_NAME = "package_name";
+ /**
+ * The uid of an app been performed an action
+ */
+ String UID = "uid";
+ /**
+ * The type of user action
+ * @see ActionType
+ */
+ String ACTION_TYPE = "action_type";
+ /**
+ * The time when action been performed
+ */
+ String TIME_STAMP_MS = "time_stamp_ms";
+ }
+
+ private static final String CREATE_ACTION_TABLE =
+ "CREATE TABLE " + Tables.TABLE_ACTION +
+ "(" +
+ ActionColumns.UID +
+ " INTEGER NOT NULL, " +
+ ActionColumns.PACKAGE_NAME +
+ " TEXT, " +
+ ActionColumns.ACTION_TYPE +
+ " INTEGER NOT NULL, " +
+ ActionColumns.TIME_STAMP_MS +
+ " INTEGER NOT NULL, " +
+ " PRIMARY KEY (" + ActionColumns.ACTION_TYPE + "," + ActionColumns.UID + ","
+ + ActionColumns.PACKAGE_NAME + ")"
+ + ")";
+
private static AnomalyDatabaseHelper sSingleton;
public static synchronized AnomalyDatabaseHelper getInstance(Context context) {
@@ -109,11 +152,6 @@
bootstrapDB(db);
}
- private void bootstrapDB(SQLiteDatabase db) {
- db.execSQL(CREATE_ANOMALY_TABLE);
- Log.i(TAG, "Bootstrapped database");
- }
-
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if (oldVersion < DATABASE_VERSION) {
@@ -137,7 +175,14 @@
bootstrapDB(db);
}
+ private void bootstrapDB(SQLiteDatabase db) {
+ db.execSQL(CREATE_ANOMALY_TABLE);
+ db.execSQL(CREATE_ACTION_TABLE);
+ Log.i(TAG, "Bootstrapped database");
+ }
+
private void dropTables(SQLiteDatabase db) {
db.execSQL("DROP TABLE IF EXISTS " + Tables.TABLE_ANOMALY);
+ db.execSQL("DROP TABLE IF EXISTS " + Tables.TABLE_ACTION);
}
}
diff --git a/src/com/android/settings/fuelgauge/batterytip/BatteryDatabaseManager.java b/src/com/android/settings/fuelgauge/batterytip/BatteryDatabaseManager.java
index 910b368..513244e 100644
--- a/src/com/android/settings/fuelgauge/batterytip/BatteryDatabaseManager.java
+++ b/src/com/android/settings/fuelgauge/batterytip/BatteryDatabaseManager.java
@@ -17,6 +17,8 @@
package com.android.settings.fuelgauge.batterytip;
import static android.database.sqlite.SQLiteDatabase.CONFLICT_IGNORE;
+import static android.database.sqlite.SQLiteDatabase.CONFLICT_REPLACE;
+
import static com.android.settings.fuelgauge.batterytip.AnomalyDatabaseHelper.AnomalyColumns
.ANOMALY_STATE;
import static com.android.settings.fuelgauge.batterytip.AnomalyDatabaseHelper.AnomalyColumns
@@ -26,6 +28,7 @@
import static com.android.settings.fuelgauge.batterytip.AnomalyDatabaseHelper.AnomalyColumns
.TIME_STAMP_MS;
import static com.android.settings.fuelgauge.batterytip.AnomalyDatabaseHelper.AnomalyColumns.UID;
+import static com.android.settings.fuelgauge.batterytip.AnomalyDatabaseHelper.Tables.TABLE_ACTION;
import static com.android.settings.fuelgauge.batterytip.AnomalyDatabaseHelper.Tables.TABLE_ANOMALY;
import android.content.ContentValues;
@@ -34,12 +37,15 @@
import android.database.sqlite.SQLiteDatabase;
import android.text.TextUtils;
import android.util.ArrayMap;
+import android.util.SparseLongArray;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
+import com.android.settings.fuelgauge.batterytip.AnomalyDatabaseHelper.ActionColumns;
+
import androidx.annotation.VisibleForTesting;
/**
@@ -158,4 +164,65 @@
}
}
}
+
+ /**
+ * Query latest timestamps when an app has been performed action {@code type}
+ *
+ * @param type of action been performed
+ * @return {@link SparseLongArray} where key is uid and value is timestamp
+ */
+ public synchronized SparseLongArray queryActionTime(
+ @AnomalyDatabaseHelper.ActionType int type) {
+ final SparseLongArray timeStamps = new SparseLongArray();
+ try (SQLiteDatabase db = mDatabaseHelper.getReadableDatabase()) {
+ final String[] projection = {ActionColumns.UID, ActionColumns.TIME_STAMP_MS};
+ final String selection = ActionColumns.ACTION_TYPE + " = ? ";
+ final String[] selectionArgs = new String[]{String.valueOf(type)};
+
+ try (Cursor cursor = db.query(TABLE_ACTION, projection, selection, selectionArgs,
+ null /* groupBy */, null /* having */, null /* orderBy */)) {
+ final int uidIndex = cursor.getColumnIndex(ActionColumns.UID);
+ final int timestampIndex = cursor.getColumnIndex(ActionColumns.TIME_STAMP_MS);
+
+ while (cursor.moveToNext()) {
+ final int uid = cursor.getInt(uidIndex);
+ final long timeStamp = cursor.getLong(timestampIndex);
+ timeStamps.append(uid, timeStamp);
+ }
+ }
+ }
+
+ return timeStamps;
+ }
+
+ /**
+ * Insert an action, or update it if already existed
+ */
+ public synchronized boolean insertAction(@AnomalyDatabaseHelper.ActionType int type,
+ int uid, String packageName, long timestampMs) {
+ try (SQLiteDatabase db = mDatabaseHelper.getWritableDatabase()) {
+ final ContentValues values = new ContentValues();
+ values.put(ActionColumns.UID, uid);
+ values.put(ActionColumns.PACKAGE_NAME, packageName);
+ values.put(ActionColumns.ACTION_TYPE, type);
+ values.put(ActionColumns.TIME_STAMP_MS, timestampMs);
+ return db.insertWithOnConflict(TABLE_ACTION, null, values, CONFLICT_REPLACE) != -1;
+ }
+ }
+
+ /**
+ * Remove an action
+ */
+ public synchronized boolean deleteAction(@AnomalyDatabaseHelper.ActionType int type,
+ int uid, String packageName) {
+ try (SQLiteDatabase db = mDatabaseHelper.getWritableDatabase()) {
+ final String where =
+ ActionColumns.ACTION_TYPE + " = ? AND " + ActionColumns.UID + " = ? AND "
+ + ActionColumns.PACKAGE_NAME + " = ? ";
+ final String[] whereArgs = new String[]{String.valueOf(type), String.valueOf(uid),
+ String.valueOf(packageName)};
+
+ return db.delete(TABLE_ACTION, where, whereArgs) != 0;
+ }
+ }
}
diff --git a/src/com/android/settings/fuelgauge/batterytip/BatteryTipPreferenceController.java b/src/com/android/settings/fuelgauge/batterytip/BatteryTipPreferenceController.java
index 0a9a4c7..158ffd4 100644
--- a/src/com/android/settings/fuelgauge/batterytip/BatteryTipPreferenceController.java
+++ b/src/com/android/settings/fuelgauge/batterytip/BatteryTipPreferenceController.java
@@ -59,24 +59,27 @@
InstrumentedPreferenceFragment mFragment;
public BatteryTipPreferenceController(Context context, String preferenceKey) {
- this(context, preferenceKey, null, null, null);
- }
-
- public BatteryTipPreferenceController(Context context, String preferenceKey,
- SettingsActivity settingsActivity, InstrumentedPreferenceFragment fragment,
- BatteryTipListener batteryTipListener) {
super(context, preferenceKey);
- mBatteryTipListener = batteryTipListener;
mBatteryTipMap = new HashMap<>();
- mFragment = fragment;
- mSettingsActivity = settingsActivity;
mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
mNeedUpdate = true;
}
+ public void setActivity(SettingsActivity activity) {
+ mSettingsActivity = activity;
+ }
+
+ public void setFragment(InstrumentedPreferenceFragment fragment) {
+ mFragment = fragment;
+ }
+
+ public void setBatteryTipListener(BatteryTipListener lsn) {
+ mBatteryTipListener = lsn;
+ }
+
@Override
public int getAvailabilityStatus() {
- return AVAILABLE;
+ return AVAILABLE_UNSEARCHABLE;
}
@Override
diff --git a/src/com/android/settings/widget/AppCheckBoxPreference.java b/src/com/android/settings/widget/AppCheckBoxPreference.java
index a0d95e9..bd643ba 100644
--- a/src/com/android/settings/widget/AppCheckBoxPreference.java
+++ b/src/com/android/settings/widget/AppCheckBoxPreference.java
@@ -17,11 +17,16 @@
package com.android.settings.widget;
import android.content.Context;
+import android.text.TextUtils;
import android.util.AttributeSet;
+import android.view.View;
+import android.widget.LinearLayout;
+import android.widget.TextView;
import com.android.settings.R;
import androidx.preference.CheckBoxPreference;
+import androidx.preference.PreferenceViewHolder;
/**
* {@link CheckBoxPreference} that used only to display app
@@ -36,4 +41,20 @@
super(context);
setLayoutResource(R.layout.preference_app);
}
+
+ @Override
+ public void onBindViewHolder(PreferenceViewHolder holder) {
+ super.onBindViewHolder(holder);
+
+ final TextView appendix = (TextView) holder.findViewById(R.id.appendix);
+ if (appendix != null) {
+ appendix.setVisibility(View.GONE);
+ }
+
+ final LinearLayout layout = (LinearLayout) holder.findViewById(R.id.summary_container);
+ if (layout != null) {
+ // If summary doesn't exist, make it gone
+ layout.setVisibility(TextUtils.isEmpty(getSummary()) ? View.GONE : View.VISIBLE);
+ }
+ }
}
diff --git a/src/com/android/settings/wifi/LinkablePreference.java b/src/com/android/settings/wifi/LinkablePreference.java
index 9c00ee2..9581e7a 100644
--- a/src/com/android/settings/wifi/LinkablePreference.java
+++ b/src/com/android/settings/wifi/LinkablePreference.java
@@ -23,12 +23,14 @@
import android.util.AttributeSet;
import android.widget.TextView;
-import com.android.settings.LinkifyUtils;
-
import androidx.annotation.Nullable;
+import androidx.core.content.res.TypedArrayUtils;
import androidx.preference.Preference;
import androidx.preference.PreferenceViewHolder;
+import com.android.settings.LinkifyUtils;
+import com.android.settingslib.R;
+
/**
* A preference with a title that can have linkable content on click.
*/
@@ -38,19 +40,20 @@
private CharSequence mContentTitle;
private CharSequence mContentDescription;
+
public LinkablePreference(Context ctx, AttributeSet attrs, int defStyle) {
super(ctx, attrs, defStyle);
+ setIcon(R.drawable.ic_info_outline_24dp);
setSelectable(false);
}
public LinkablePreference(Context ctx, AttributeSet attrs) {
- super(ctx, attrs);
- setSelectable(false);
+ this(ctx, attrs, TypedArrayUtils.getAttr(
+ ctx, R.attr.footerPreferenceStyle, android.R.attr.preferenceStyle));
}
public LinkablePreference(Context ctx) {
- super(ctx);
- setSelectable(false);
+ this(ctx, null);
}
@Override
@@ -75,21 +78,20 @@
boolean linked = LinkifyUtils.linkify(textView, contentBuilder, mClickListener);
if (linked && mContentTitle != null) {
- // Embolden and enlarge the title.
- Spannable boldSpan = (Spannable) textView.getText();
- boldSpan.setSpan(
- new TextAppearanceSpan(
- getContext(), android.R.style.TextAppearance_Medium),
+ Spannable spannableContent = (Spannable) textView.getText();
+ spannableContent.setSpan(
+ new TextAppearanceSpan(getContext(), android.R.style.TextAppearance_Small),
0,
mContentTitle.length(),
Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
- textView.setText(boldSpan);
+ textView.setText(spannableContent);
textView.setMovementMethod(new LinkMovementMethod());
}
}
/**
* Sets the linkable text for the Preference title.
+ *
* @param contentTitle text to set the Preference title.
* @param contentDescription description text to append underneath title, can be null.
* @param clickListener OnClickListener for the link portion of the text.
diff --git a/src/com/android/settings/wifi/WifiDialogActivity.java b/src/com/android/settings/wifi/WifiDialogActivity.java
index e5526c9..d864855 100644
--- a/src/com/android/settings/wifi/WifiDialogActivity.java
+++ b/src/com/android/settings/wifi/WifiDialogActivity.java
@@ -52,6 +52,8 @@
@VisibleForTesting
static final String KEY_CONNECT_FOR_CALLER = "connect_for_caller";
+ private WifiDialog mDialog;
+
@Override
protected void onCreate(Bundle savedInstanceState) {
final Intent intent = getIntent();
@@ -67,10 +69,10 @@
accessPoint = new AccessPoint(this, accessPointState);
}
- WifiDialog dialog = WifiDialog.createModal(
+ mDialog = WifiDialog.createModal(
this, this, accessPoint, WifiConfigUiBase.MODE_CONNECT);
- dialog.show();
- dialog.setOnDismissListener(this);
+ mDialog.show();
+ mDialog.setOnDismissListener(this);
}
@Override
@@ -80,6 +82,15 @@
}
@Override
+ public void onDestroy() {
+ super.onDestroy();
+ if (mDialog != null && mDialog.isShowing()) {
+ mDialog.dismiss();
+ mDialog = null;
+ }
+ }
+
+ @Override
public void onForget(WifiDialog dialog) {
final WifiManager wifiManager = getSystemService(WifiManager.class);
final AccessPoint accessPoint = dialog.getController().getAccessPoint();
@@ -147,6 +158,7 @@
@Override
public void onDismiss(DialogInterface dialogInterface) {
+ mDialog = null;
finish();
}
}
diff --git a/tests/robotests/assets/grandfather_not_sharing_pref_controllers_with_search_provider b/tests/robotests/assets/grandfather_not_sharing_pref_controllers_with_search_provider
index b329072..e69de29 100644
--- a/tests/robotests/assets/grandfather_not_sharing_pref_controllers_with_search_provider
+++ b/tests/robotests/assets/grandfather_not_sharing_pref_controllers_with_search_provider
@@ -1 +0,0 @@
-com.android.settings.fuelgauge.PowerUsageSummary
diff --git a/tests/robotests/src/com/android/settings/bluetooth/RemoteDeviceNameDialogFragmentTest.java b/tests/robotests/src/com/android/settings/bluetooth/RemoteDeviceNameDialogFragmentTest.java
index 0ecd295..c9edc00 100644
--- a/tests/robotests/src/com/android/settings/bluetooth/RemoteDeviceNameDialogFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/bluetooth/RemoteDeviceNameDialogFragmentTest.java
@@ -37,6 +37,7 @@
import com.android.settingslib.testutils.FragmentTestUtils;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Answers;
@@ -80,6 +81,7 @@
}
@Test
+ @Ignore
public void deviceNameDisplayIsCorrect() {
String deviceName = "ABC Corp Headphones";
AlertDialog dialog = startDialog(deviceName);
@@ -95,6 +97,7 @@
}
@Test
+ @Ignore
public void deviceNameEditSucceeds() {
String deviceNameInitial = "ABC Corp Headphones";
String deviceNameModified = "My Headphones";
@@ -117,6 +120,7 @@
}
@Test
+ @Ignore
public void deviceNameEditThenCancelDoesntRename() {
String deviceNameInitial = "ABC Corp Headphones";
String deviceNameModified = "My Headphones";
diff --git a/tests/robotests/src/com/android/settings/dashboard/DashboardAdapterTest.java b/tests/robotests/src/com/android/settings/dashboard/DashboardAdapterTest.java
index 79be6cf..c823433 100644
--- a/tests/robotests/src/com/android/settings/dashboard/DashboardAdapterTest.java
+++ b/tests/robotests/src/com/android/settings/dashboard/DashboardAdapterTest.java
@@ -203,9 +203,9 @@
new DashboardAdapter.DashboardItemHolder(view);
final Tile tile = spy(new Tile(mActivityInfo));
doReturn(Icon.createWithResource(context, R.drawable.ic_settings))
- .when(tile).getIcon();
+ .when(tile).getIcon(context);
final IconCache iconCache = mock(IconCache.class);
- when(iconCache.getIcon(tile.getIcon()))
+ when(iconCache.getIcon(tile.getIcon(context)))
.thenReturn(context.getDrawable(R.drawable.ic_settings));
mDashboardAdapter = new DashboardAdapter(context, null /* savedInstanceState */,
@@ -224,7 +224,7 @@
new DashboardAdapter.DashboardItemHolder(view);
final Tile tile = spy(new Tile(mActivityInfo));
final Icon icon = Icon.createWithResource(context, R.drawable.ic_settings);
- doReturn(icon).when(tile).getIcon();
+ doReturn(icon).when(tile).getIcon(context);
final IconCache iconCache = new IconCache(context);
@@ -235,7 +235,8 @@
doReturn("another.package").when(context).getPackageName();
mDashboardAdapter.onBindTile(holder, tile);
- assertThat(iconCache.getIcon(tile.getIcon())).isInstanceOf(RoundedHomepageIcon.class);
+ assertThat(iconCache.getIcon(tile.getIcon(context)))
+ .isInstanceOf(RoundedHomepageIcon.class);
}
@Test
@@ -249,7 +250,7 @@
tile.metaData.putInt(TileUtils.META_DATA_PREFERENCE_ICON_BACKGROUND_HINT,
R.color.memory_critical);
doReturn(Icon.createWithResource(context, R.drawable.ic_settings))
- .when(tile).getIcon();
+ .when(tile).getIcon(context);
final IconCache iconCache = new IconCache(context);
mDashboardAdapter = new DashboardAdapter(context, null /* savedInstanceState */,
null /* conditions */, null /* suggestionControllerMixin */, null /* lifecycle */);
@@ -259,7 +260,7 @@
mDashboardAdapter.onBindTile(holder, tile);
final RoundedHomepageIcon homepageIcon = (RoundedHomepageIcon) iconCache.getIcon(
- tile.getIcon());
+ tile.getIcon(context));
assertThat(homepageIcon.mBackgroundColor)
.isEqualTo(RuntimeEnvironment.application.getColor(R.color.memory_critical));
}
@@ -271,11 +272,11 @@
final DashboardAdapter.DashboardItemHolder holder =
new DashboardAdapter.DashboardItemHolder(view);
final Tile tile = spy(new Tile(mActivityInfo));
- doReturn(mock(Icon.class)).when(tile).getIcon();
- when(tile.getIcon().getResPackage()).thenReturn("another.package");
+ doReturn(mock(Icon.class)).when(tile).getIcon(context);
+ when(tile.getIcon(context).getResPackage()).thenReturn("another.package");
final IconCache iconCache = mock(IconCache.class);
- when(iconCache.getIcon(tile.getIcon())).thenReturn(mock(RoundedHomepageIcon.class));
+ when(iconCache.getIcon(tile.getIcon(context))).thenReturn(mock(RoundedHomepageIcon.class));
mDashboardAdapter = new DashboardAdapter(context, null /* savedInstanceState */,
null /* conditions */, null /* suggestionControllerMixin */, null /* lifecycle */);
@@ -283,7 +284,8 @@
mDashboardAdapter.onBindTile(holder, tile);
- verify(iconCache, never()).updateIcon(eq(tile.getIcon()), any(RoundedHomepageIcon.class));
+ verify(iconCache, never()).updateIcon(eq(tile.getIcon(context)),
+ any(RoundedHomepageIcon.class));
}
private List<Suggestion> makeSuggestionsV2(String... pkgNames) {
diff --git a/tests/robotests/src/com/android/settings/dashboard/DashboardFeatureProviderImplTest.java b/tests/robotests/src/com/android/settings/dashboard/DashboardFeatureProviderImplTest.java
index e677119..963411d 100644
--- a/tests/robotests/src/com/android/settings/dashboard/DashboardFeatureProviderImplTest.java
+++ b/tests/robotests/src/com/android/settings/dashboard/DashboardFeatureProviderImplTest.java
@@ -120,7 +120,7 @@
tile.title = "title";
tile.summary = "summary";
doReturn(Icon.createWithBitmap(Bitmap.createBitmap(1, 1, Bitmap.Config.RGB_565)))
- .when(tile).getIcon();
+ .when(tile).getIcon(any(Context.class));
tile.metaData = new Bundle();
tile.metaData.putString(SettingsActivity.META_DATA_KEY_FRAGMENT_CLASS, "HI");
tile.priority = 10;
diff --git a/tests/robotests/src/com/android/settings/dashboard/DashboardFragmentTest.java b/tests/robotests/src/com/android/settings/dashboard/DashboardFragmentTest.java
index e7453fa..8c1b99b 100644
--- a/tests/robotests/src/com/android/settings/dashboard/DashboardFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/dashboard/DashboardFragmentTest.java
@@ -17,6 +17,7 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
@@ -183,7 +184,7 @@
@Test
public void tintTileIcon_hasMetadata_shouldReturnIconTintableMetadata() {
final Tile tile = spy(new Tile(mActivityInfo));
- doReturn(mock(Icon.class)).when(tile).getIcon();
+ doReturn(mock(Icon.class)).when(tile).getIcon(any(Context.class));
final Bundle metaData = new Bundle();
tile.metaData = metaData;
@@ -205,7 +206,7 @@
@Test
public void tintTileIcon_noMetadata_shouldReturnPackageNameCheck() {
final Tile tile = spy(new Tile(mActivityInfo));
- doReturn(mock(Icon.class)).when(tile).getIcon();
+ doReturn(mock(Icon.class)).when(tile).getIcon(any(Context.class));
final Intent intent = new Intent();
tile.intent = intent;
intent.setComponent(
diff --git a/tests/robotests/src/com/android/settings/development/autofill/AutofillLoggingLevelPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/autofill/AutofillLoggingLevelPreferenceControllerTest.java
new file mode 100644
index 0000000..b9da71d
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/development/autofill/AutofillLoggingLevelPreferenceControllerTest.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.development.autofill;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.os.RemoteException;
+import android.view.autofill.AutofillManager;
+
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settings.R;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+
+import androidx.preference.PreferenceScreen;
+import androidx.preference.ListPreference;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class AutofillLoggingLevelPreferenceControllerTest {
+
+ private static final int IDX_OFF = 0;
+ private static final int IDX_DEBUG = 1;
+ private static final int IDX_VERBOSE = 2;
+
+ @Mock
+ private ListPreference mPreference;
+ @Mock
+ private PreferenceScreen mPreferenceScreen;
+
+ private Context mContext;
+ private AutofillLoggingLevelPreferenceController mController;
+ private AutofillTestingHelper mHelper;
+
+ private String[] mListValues;
+ private String[] mListSummaries;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this); // TODO: use @Rule
+ mContext = RuntimeEnvironment.application;
+ mHelper = new AutofillTestingHelper(mContext);
+ final Resources resources = mContext.getResources();
+ mListValues = resources.getStringArray(R.array.autofill_logging_level_values);
+ mListSummaries = resources.getStringArray(R.array.autofill_logging_level_entries);
+ mController = new AutofillLoggingLevelPreferenceController(mContext);
+ when(mPreferenceScreen.findPreference(mController.getPreferenceKey()))
+ .thenReturn(mPreference);
+ mController.displayPreference(mPreferenceScreen);
+ }
+
+ @Test
+ public void handlePreferenceTreeClick_differentPreferenceKey_shouldNotTrigger()
+ throws Exception {
+ when(mPreference.getKey()).thenReturn("SomeRandomKey");
+
+ mHelper.setLoggingLevel(108);
+
+ assertThat(mController.handlePreferenceTreeClick(mPreference)).isFalse();
+
+ assertThat(mHelper.getLoggingLevel()).isEqualTo(108);
+ }
+
+ @Test
+ public void onPreferenceChange_off() throws Exception {
+ mHelper.setLoggingLevel(108);
+
+ mController.onPreferenceChange(mPreference, mListValues[IDX_OFF]);
+
+ assertThat(mHelper.getLoggingLevel()).isEqualTo(AutofillManager.NO_LOGGING);
+ }
+
+ @Test
+ public void onPreferenceChange_debug() throws Exception {
+ mHelper.setLoggingLevel(108);
+
+ mController.onPreferenceChange(mPreference, mListValues[IDX_DEBUG]);
+
+ assertThat(mHelper.getLoggingLevel())
+ .isEqualTo(AutofillManager.FLAG_ADD_CLIENT_DEBUG);
+ }
+
+ @Test
+ public void onPreferenceChange_verbose() throws Exception {
+ mHelper.setLoggingLevel(108);
+
+ mController.onPreferenceChange(mPreference, mListValues[IDX_VERBOSE]);
+
+ assertThat(mHelper.getLoggingLevel())
+ .isEqualTo(AutofillManager.FLAG_ADD_CLIENT_VERBOSE);
+ }
+
+ @Test
+ public void onSettingsChange_off() throws Exception {
+ mHelper.setLoggingLevel(AutofillManager.NO_LOGGING);
+
+ mController.updateState(mPreference);
+
+ verify(mPreference).setValue(mListValues[IDX_OFF]);
+ verify(mPreference).setSummary(mListSummaries[IDX_OFF]);
+ }
+
+ @Test
+ public void onSettingsChange_debug() throws Exception {
+ mHelper.setLoggingLevel(AutofillManager.FLAG_ADD_CLIENT_DEBUG);
+
+ mController.updateState(mPreference);
+
+ verify(mPreference).setValue(mListValues[IDX_DEBUG]);
+ verify(mPreference).setSummary(mListSummaries[IDX_DEBUG]);
+ }
+
+ @Test
+ public void onSettingsChange_verbose() throws Exception {
+ mHelper.setLoggingLevel(AutofillManager.FLAG_ADD_CLIENT_VERBOSE);
+
+ mController.updateState(mPreference);
+
+ verify(mPreference).setValue(mListValues[IDX_VERBOSE]);
+ verify(mPreference).setSummary(mListSummaries[IDX_VERBOSE]);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/development/autofill/AutofillResetOptionsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/autofill/AutofillResetOptionsPreferenceControllerTest.java
new file mode 100644
index 0000000..e560a83
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/development/autofill/AutofillResetOptionsPreferenceControllerTest.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.development.autofill;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.os.RemoteException;
+import android.view.autofill.AutofillManager;
+
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+
+import androidx.preference.PreferenceScreen;
+import androidx.preference.SwitchPreference;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class AutofillResetOptionsPreferenceControllerTest {
+
+ @Mock
+ private SwitchPreference mPreference;
+ @Mock
+ private PreferenceScreen mPreferenceScreen;
+
+ private Context mContext;
+ private AutofillResetOptionsPreferenceController mController;
+ private AutofillTestingHelper mHelper;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this); // TODO: use @Rule
+ mContext = RuntimeEnvironment.application;
+ mHelper = new AutofillTestingHelper(mContext);
+ mController = new AutofillResetOptionsPreferenceController(mContext);
+ when(mPreferenceScreen.findPreference(mController.getPreferenceKey()))
+ .thenReturn(mPreference);
+ mController.displayPreference(mPreferenceScreen);
+ }
+
+ @Test
+ public void handlePreferenceTreeClick_differentPreferenceKey_shouldNotReset() throws Exception {
+ when(mPreference.getKey()).thenReturn("SomeRandomKey");
+
+ mHelper.setLoggingLevel(4);
+ mHelper.setMaxPartitionsSize(8);
+ mHelper.setMaxVisibleDatasets(15);
+
+ assertThat(mController.handlePreferenceTreeClick(mPreference)).isFalse();
+
+ assertThat(mHelper.getLoggingLevel()).isEqualTo(4);
+ assertThat(mHelper.getMaxPartitionsSize()).isEqualTo(8);
+ assertThat(mHelper.getMaxVisibleDatasets()).isEqualTo(15);
+ }
+
+ @Test
+ public void handlePreferenceTreeClick_correctPreferenceKey_shouldReset() throws Exception {
+ when(mPreference.getKey()).thenReturn(mController.getPreferenceKey());
+
+ mHelper.setMaxPartitionsSize(16);
+ mHelper.setMaxVisibleDatasets(23);
+ mHelper.setLoggingLevel(42);
+
+ assertThat(mController.handlePreferenceTreeClick(mPreference)).isTrue();
+
+ assertThat(mHelper.getLoggingLevel())
+ .isEqualTo(AutofillManager.DEFAULT_LOGGING_LEVEL);
+ assertThat(mHelper.getMaxPartitionsSize())
+ .isEqualTo(AutofillManager.DEFAULT_MAX_PARTITIONS_SIZE);
+ assertThat(mHelper.getMaxVisibleDatasets())
+ .isEqualTo(0);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/development/autofill/AutofillTestingHelper.java b/tests/robotests/src/com/android/settings/development/autofill/AutofillTestingHelper.java
new file mode 100644
index 0000000..59090bc
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/development/autofill/AutofillTestingHelper.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.development.autofill;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.provider.Settings;
+import android.provider.Settings.SettingNotFoundException;
+
+final class AutofillTestingHelper {
+ private final ContentResolver mResolver;
+
+ public AutofillTestingHelper(Context context) {
+ mResolver = context.getContentResolver();
+ }
+
+ public void setLoggingLevel(int max) {
+ setGlobal(Settings.Global.AUTOFILL_LOGGING_LEVEL, max);
+ }
+
+ public void setMaxPartitionsSize(int max) {
+ setGlobal(Settings.Global.AUTOFILL_MAX_PARTITIONS_SIZE, max);
+ }
+
+ public void setMaxVisibleDatasets(int level) {
+ setGlobal(Settings.Global.AUTOFILL_MAX_VISIBLE_DATASETS, level);
+ }
+
+ public int getLoggingLevel() throws SettingNotFoundException {
+ return getGlobal(Settings.Global.AUTOFILL_LOGGING_LEVEL);
+ }
+
+ public int getMaxPartitionsSize() throws SettingNotFoundException {
+ return getGlobal(Settings.Global.AUTOFILL_MAX_PARTITIONS_SIZE);
+ }
+
+ public int getMaxVisibleDatasets() throws SettingNotFoundException {
+ return getGlobal(Settings.Global.AUTOFILL_MAX_VISIBLE_DATASETS);
+ }
+
+ private void setGlobal(String key, int value) {
+ Settings.Global.putInt(mResolver, key, value);
+ }
+
+ private int getGlobal(String key) throws SettingNotFoundException {
+ return Settings.Global.getInt(mResolver, key);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/display/BatteryPercentagePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/display/BatteryPercentagePreferenceControllerTest.java
index 673abb0..140fc5c 100644
--- a/tests/robotests/src/com/android/settings/display/BatteryPercentagePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/display/BatteryPercentagePreferenceControllerTest.java
@@ -32,13 +32,15 @@
@RunWith(SettingsRobolectricTestRunner.class)
public class BatteryPercentagePreferenceControllerTest {
+ private static final String PREF_KEY = "battery_percentage";
+
private Context mContext;
private BatteryPercentagePreferenceController mController;
@Before
public void setup() {
mContext = RuntimeEnvironment.application;
- mController = new BatteryPercentagePreferenceController(mContext);
+ mController = new BatteryPercentagePreferenceController(mContext, PREF_KEY);
}
private int getPercentageSetting() {
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryDatabaseManagerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryDatabaseManagerTest.java
index 58bfe0e..41e77e9 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryDatabaseManagerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryDatabaseManagerTest.java
@@ -22,6 +22,7 @@
import android.content.Context;
import android.text.format.DateUtils;
+import android.util.SparseLongArray;
import com.android.settings.fuelgauge.batterytip.AnomalyDatabaseHelper;
import com.android.settings.fuelgauge.batterytip.AppInfo;
@@ -88,7 +89,7 @@
}
@Test
- public void testAllFunctions() {
+ public void allAnomalyFunctions() {
mBatteryDatabaseManager.insertAnomaly(UID_NEW, PACKAGE_NAME_NEW, TYPE_NEW,
AnomalyDatabaseHelper.State.NEW, NOW);
mBatteryDatabaseManager.insertAnomaly(UID_OLD, PACKAGE_NAME_OLD, TYPE_OLD,
@@ -113,7 +114,7 @@
}
@Test
- public void testUpdateAnomalies_updateSuccessfully() {
+ public void updateAnomalies_updateSuccessfully() {
mBatteryDatabaseManager.insertAnomaly(UID_NEW, PACKAGE_NAME_NEW, TYPE_NEW,
AnomalyDatabaseHelper.State.NEW, NOW);
mBatteryDatabaseManager.insertAnomaly(UID_OLD, PACKAGE_NAME_OLD, TYPE_OLD,
@@ -138,7 +139,7 @@
}
@Test
- public void testQueryAnomalies_removeDuplicateByUid() {
+ public void queryAnomalies_removeDuplicateByUid() {
mBatteryDatabaseManager.insertAnomaly(UID_NEW, PACKAGE_NAME_NEW, TYPE_NEW,
AnomalyDatabaseHelper.State.NEW, NOW);
mBatteryDatabaseManager.insertAnomaly(UID_NEW, PACKAGE_NAME_NEW, TYPE_OLD,
@@ -149,4 +150,28 @@
AnomalyDatabaseHelper.State.NEW);
assertThat(newAppInfos).containsExactly(mCombinedAppInfo);
}
+
+ @Test
+ public void allActionFunctions() {
+ final long timestamp = System.currentTimeMillis();
+ mBatteryDatabaseManager.insertAction(AnomalyDatabaseHelper.ActionType.RESTRICTION, UID_OLD,
+ PACKAGE_NAME_OLD, 0);
+ mBatteryDatabaseManager.insertAction(AnomalyDatabaseHelper.ActionType.RESTRICTION, UID_OLD,
+ PACKAGE_NAME_OLD, 1);
+ mBatteryDatabaseManager.insertAction(AnomalyDatabaseHelper.ActionType.RESTRICTION, UID_NEW,
+ PACKAGE_NAME_NEW, timestamp);
+
+ final SparseLongArray timeArray = mBatteryDatabaseManager.queryActionTime(
+ AnomalyDatabaseHelper.ActionType.RESTRICTION);
+ assertThat(timeArray.size()).isEqualTo(2);
+ assertThat(timeArray.get(UID_OLD)).isEqualTo(1);
+ assertThat(timeArray.get(UID_NEW)).isEqualTo(timestamp);
+
+ mBatteryDatabaseManager.deleteAction(AnomalyDatabaseHelper.ActionType.RESTRICTION, UID_NEW,
+ PACKAGE_NAME_NEW);
+ final SparseLongArray recentTimeArray = mBatteryDatabaseManager.queryActionTime(
+ AnomalyDatabaseHelper.ActionType.RESTRICTION);
+ assertThat(recentTimeArray.size()).isEqualTo(1);
+ assertThat(timeArray.get(UID_OLD)).isEqualTo(1);
+ }
}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryHeaderPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryHeaderPreferenceControllerTest.java
index 91cb078..337b950 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryHeaderPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryHeaderPreferenceControllerTest.java
@@ -36,6 +36,7 @@
import com.android.settings.R;
import com.android.settings.applications.LayoutPreference;
+import com.android.settings.core.BasePreferenceController;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.shadow.SettingsShadowResources;
import com.android.settings.testutils.shadow.SettingsShadowResourcesImpl;
@@ -68,6 +69,7 @@
})
public class BatteryHeaderPreferenceControllerTest {
+ private static final String PREF_KEY = "battery_header";
private static final int BATTERY_LEVEL = 60;
private static final String TIME_LEFT = "2h30min";
private static final String BATTERY_STATUS = "Charging";
@@ -121,8 +123,11 @@
mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
- mController = new BatteryHeaderPreferenceController(
- mContext, mActivity, mPreferenceFragment, mLifecycle);
+ mController = new BatteryHeaderPreferenceController(mContext, PREF_KEY);
+ mLifecycle.addObserver(mController);
+ mController.setActivity(mActivity);
+ mController.setFragment(mPreferenceFragment);
+ mController.setLifecycle(mLifecycle);
mController.mBatteryMeterView = mBatteryMeterView;
mController.mBatteryPercentText = mBatteryPercentText;
mController.mSummary1 = mSummary;
@@ -207,4 +212,10 @@
assertThat(mBatteryMeterView.getPowerSave()).isEqualTo(value);
}
}
+
+ @Test
+ public void getAvailabilityStatus_returnAvailableUnsearchable() {
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(
+ BasePreferenceController.AVAILABLE_UNSEARCHABLE);
+ }
}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryUtilsTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryUtilsTest.java
index df34b78..b274492 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryUtilsTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryUtilsTest.java
@@ -51,9 +51,12 @@
import com.android.internal.os.BatterySipper;
import com.android.internal.os.BatteryStatsHelper;
+import com.android.settings.fuelgauge.batterytip.AnomalyDatabaseHelper;
import com.android.settings.fuelgauge.batterytip.AnomalyInfo;
+import com.android.settings.fuelgauge.batterytip.BatteryDatabaseManager;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settings.testutils.shadow.ShadowThreadUtils;
import com.android.settingslib.fuelgauge.PowerWhitelistBackend;
import org.junit.Before;
@@ -148,6 +151,8 @@
private ApplicationInfo mLowApplicationInfo;
@Mock
private PowerWhitelistBackend mPowerWhitelistBackend;
+ @Mock
+ private BatteryDatabaseManager mBatteryDatabaseManager;
private AnomalyInfo mAnomalyInfo;
private BatteryUtils mBatteryUtils;
private FakeFeatureFactory mFeatureFactory;
@@ -225,6 +230,8 @@
.thenReturn(TOTAL_BATTERY_USAGE + BATTERY_SCREEN_USAGE);
when(mBatteryStatsHelper.getStats().getDischargeAmount(anyInt()))
.thenReturn(DISCHARGE_AMOUNT);
+ BatteryDatabaseManager.setUpForTest(mBatteryDatabaseManager);
+ ShadowThreadUtils.setIsMainThread(true);
}
@Test
@@ -570,6 +577,23 @@
}
@Test
+ public void testSetForceAppStandby_restrictApp_recordTime() {
+ mBatteryUtils.setForceAppStandby(UID, HIGH_SDK_PACKAGE, AppOpsManager.MODE_IGNORED);
+
+ verify(mBatteryDatabaseManager).insertAction(
+ eq(AnomalyDatabaseHelper.ActionType.RESTRICTION), eq(UID),
+ eq(HIGH_SDK_PACKAGE), anyLong());
+ }
+
+ @Test
+ public void testSetForceAppStandby_unrestrictApp_deleteTime() {
+ mBatteryUtils.setForceAppStandby(UID, HIGH_SDK_PACKAGE, AppOpsManager.MODE_ALLOWED);
+
+ verify(mBatteryDatabaseManager).deleteAction(AnomalyDatabaseHelper.ActionType.RESTRICTION,
+ UID, HIGH_SDK_PACKAGE);
+ }
+
+ @Test
public void testIsForceAppStandbyEnabled_enabled_returnTrue() {
when(mAppOpsManager.checkOpNoThrow(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, UID,
PACKAGE_NAME)).thenReturn(AppOpsManager.MODE_IGNORED);
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java
index 97e272b..68d9994 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java
@@ -223,21 +223,6 @@
}
@Test
- public void preferenceControllers_getPreferenceKeys_existInPreferenceScreen() {
- final Context context = RuntimeEnvironment.application;
- final PowerUsageSummary fragment = new PowerUsageSummary();
- final List<String> preferenceScreenKeys =
- XmlTestUtils.getKeysFromPreferenceXml(context, fragment.getPreferenceScreenResId());
- final List<String> preferenceKeys = new ArrayList<>();
-
- for (AbstractPreferenceController controller : fragment.createPreferenceControllers(context)) {
- preferenceKeys.add(controller.getPreferenceKey());
- }
-
- assertThat(preferenceScreenKeys).containsAllIn(preferenceKeys);
- }
-
- @Test
public void restartBatteryTipLoader() {
//TODO: add policy logic here when BatteryTipPolicy is implemented
doReturn(mLoaderManager).when(mFragment).getLoaderManager();
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/RestrictedAppDetailsTest.java b/tests/robotests/src/com/android/settings/fuelgauge/RestrictedAppDetailsTest.java
index b9ed509..7219f18 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/RestrictedAppDetailsTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/RestrictedAppDetailsTest.java
@@ -28,10 +28,13 @@
import android.os.Bundle;
import android.os.UserHandle;
import android.util.IconDrawableFactory;
+import android.util.SparseLongArray;
import com.android.settings.SettingsActivity;
import com.android.settings.core.InstrumentedPreferenceFragment;
+import com.android.settings.fuelgauge.batterytip.AnomalyDatabaseHelper;
import com.android.settings.fuelgauge.batterytip.AppInfo;
+import com.android.settings.fuelgauge.batterytip.BatteryDatabaseManager;
import com.android.settings.fuelgauge.batterytip.BatteryTipDialogFragment;
import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
import com.android.settings.fuelgauge.batterytip.tips.RestrictAppTip;
@@ -52,6 +55,7 @@
import java.util.ArrayList;
import java.util.List;
+import java.util.concurrent.TimeUnit;
import androidx.appcompat.app.AlertDialog;
import androidx.preference.CheckBoxPreference;
@@ -76,6 +80,8 @@
private IconDrawableFactory mIconDrawableFactory;
@Mock
private InstrumentedPreferenceFragment mFragment;
+ @Mock
+ private BatteryDatabaseManager mBatteryDatabaseManager;
private PreferenceManager mPreferenceManager;
private RestrictedAppDetails mRestrictedAppDetails;
private Context mContext;
@@ -98,12 +104,14 @@
doReturn(mPreferenceManager).when(mRestrictedAppDetails).getPreferenceManager();
doReturn(mContext).when(mFragment).getContext();
+ doReturn(mContext).when(mRestrictedAppDetails).getContext();
mRestrictedAppDetails.mPackageManager = mPackageManager;
mRestrictedAppDetails.mIconDrawableFactory = mIconDrawableFactory;
mRestrictedAppDetails.mAppInfos = new ArrayList<>();
mRestrictedAppDetails.mAppInfos.add(mAppInfo);
mRestrictedAppDetails.mRestrictedAppListGroup = spy(new PreferenceCategory(mContext));
mRestrictedAppDetails.mBatteryUtils = spy(new BatteryUtils(mContext));
+ mRestrictedAppDetails.mBatteryDatabaseManager = mBatteryDatabaseManager;
doReturn(mPreferenceManager).when(
mRestrictedAppDetails.mRestrictedAppListGroup).getPreferenceManager();
@@ -118,6 +126,10 @@
doReturn(APP_NAME).when(mPackageManager).getApplicationLabel(mApplicationInfo);
doReturn(true).when(mRestrictedAppDetails.mBatteryUtils).isForceAppStandbyEnabled(UID,
PACKAGE_NAME);
+ final SparseLongArray timestampArray = new SparseLongArray();
+ timestampArray.put(UID, System.currentTimeMillis() - TimeUnit.HOURS.toMillis(5));
+ doReturn(timestampArray).when(mBatteryDatabaseManager)
+ .queryActionTime(AnomalyDatabaseHelper.ActionType.RESTRICTION);
mRestrictedAppDetails.refreshUi();
@@ -126,6 +138,7 @@
(CheckBoxPreference) mRestrictedAppDetails.mRestrictedAppListGroup.getPreference(0);
assertThat(preference.getTitle()).isEqualTo(APP_NAME);
assertThat(preference.isChecked()).isTrue();
+ assertThat(preference.getSummary()).isEqualTo("Restricted 5 hours ago");
}
@Test
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipPreferenceControllerTest.java
index 7e9ffeb..e7aafef 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipPreferenceControllerTest.java
@@ -31,6 +31,7 @@
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
+import com.android.settings.core.BasePreferenceController;
import com.android.settings.core.InstrumentedPreferenceFragment;
import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
import com.android.settings.fuelgauge.batterytip.tips.SummaryTip;
@@ -100,8 +101,7 @@
mNewBatteryTips = new ArrayList<>();
mNewBatteryTips.add(new SummaryTip(BatteryTip.StateType.INVISIBLE, AVERAGE_TIME_MS));
- mBatteryTipPreferenceController = new BatteryTipPreferenceController(mContext, KEY_PREF,
- mSettingsActivity, mFragment, mBatteryTipListener);
+ mBatteryTipPreferenceController = buildBatteryTipPreferenceController();
mBatteryTipPreferenceController.mPreferenceGroup = mPreferenceGroup;
mBatteryTipPreferenceController.mPrefContext = mContext;
}
@@ -139,8 +139,7 @@
final Bundle bundle = new Bundle();
mBatteryTipPreferenceController.saveInstanceState(bundle);
- final BatteryTipPreferenceController controller = new BatteryTipPreferenceController(
- mContext, KEY_PREF, mSettingsActivity, mFragment, mBatteryTipListener);
+ final BatteryTipPreferenceController controller = buildBatteryTipPreferenceController();
controller.mPreferenceGroup = mPreferenceGroup;
controller.mPrefContext = mContext;
controller.restoreInstanceState(bundle);
@@ -154,8 +153,7 @@
// Battery tip list is null at this time
mBatteryTipPreferenceController.saveInstanceState(bundle);
- final BatteryTipPreferenceController controller = new BatteryTipPreferenceController(
- mContext, KEY_PREF, mSettingsActivity, mFragment, mBatteryTipListener);
+ final BatteryTipPreferenceController controller = buildBatteryTipPreferenceController();
// Should not crash
controller.restoreInstanceState(bundle);
@@ -176,6 +174,12 @@
verify(mBatteryTipListener).onBatteryTipHandled(mBatteryTip);
}
+ @Test
+ public void getAvailabilityStatus_returnAvailableUnsearchable() {
+ assertThat(mBatteryTipPreferenceController.getAvailabilityStatus()).isEqualTo(
+ BasePreferenceController.AVAILABLE_UNSEARCHABLE);
+ }
+
private void assertOnlyContainsSummaryTip(final PreferenceGroup preferenceGroup) {
assertThat(preferenceGroup.getPreferenceCount()).isEqualTo(1);
@@ -185,4 +189,14 @@
assertThat(preference.getSummary()).isEqualTo(
mContext.getString(R.string.battery_tip_summary_summary));
}
+
+ private BatteryTipPreferenceController buildBatteryTipPreferenceController() {
+ final BatteryTipPreferenceController controller = new BatteryTipPreferenceController(
+ mContext, KEY_PREF);
+ controller.setActivity(mSettingsActivity);
+ controller.setFragment(mFragment);
+ controller.setBatteryTipListener(mBatteryTipListener);
+
+ return controller;
+ }
}
diff --git a/tests/robotests/src/com/android/settings/wallpaper/FallbackHomeActivityTest.java b/tests/robotests/src/com/android/settings/wallpaper/FallbackHomeActivityTest.java
new file mode 100644
index 0000000..57d7798
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/wallpaper/FallbackHomeActivityTest.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.wallpaper;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.when;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.WallpaperColors;
+import android.app.WallpaperManager;
+import android.app.WallpaperManager.OnColorsChangedListener;
+import android.os.Handler;
+
+import com.android.settings.FallbackHome;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.Robolectric;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.android.controller.ActivityController;
+import org.robolectric.annotation.Config;
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+import org.robolectric.shadow.api.Shadow;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Build/Install/Run:
+ * make RunSettingsRoboTests -j40 ROBOTEST_FILTER=FallbackHomeActivityTest
+ */
+@RunWith(SettingsRobolectricTestRunner.class)
+public class FallbackHomeActivityTest {
+
+ private ActivityController<FallbackHome> mController;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mController = Robolectric.buildActivity(FallbackHome.class);
+ }
+
+ @Test
+ @Config(shadows = ShadowWallpaperManager.class)
+ public void wallpaperColorsChangedListener_ensured_removed() {
+ // onCreate adds the first color listener by WallpaperManager returning null colors
+ ActivityController controller = mController.setup();
+ ShadowWallpaperManager shadowManager = Shadow.extract(RuntimeEnvironment.application
+ .getSystemService(WallpaperManager.class));
+ assertThat(shadowManager.size()).isEqualTo(1);
+
+ // Assert onDestroy will remove the original listener
+ controller.destroy();
+ assertThat(shadowManager.size()).isEqualTo(0);
+ }
+
+ @Implements(WallpaperManager.class)
+ public static class ShadowWallpaperManager {
+
+ private final List<OnColorsChangedListener> mListener = new ArrayList<>();
+
+ public int size() {
+ return mListener.size();
+ }
+
+ @Implementation
+ public boolean isWallpaperServiceEnabled() {
+ return true;
+ }
+
+ @Implementation
+ public @Nullable WallpaperColors getWallpaperColors(int which) {
+ return null;
+ }
+
+ @Implementation
+ public void addOnColorsChangedListener(@NonNull OnColorsChangedListener listener,
+ @NonNull Handler handler) {
+ mListener.add(listener);
+ }
+
+ @Implementation
+ public void removeOnColorsChangedListener(@NonNull OnColorsChangedListener listener) {
+ mListener.remove(listener);
+ }
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/widget/AppCheckBoxPreferenceTest.java b/tests/robotests/src/com/android/settings/widget/AppCheckBoxPreferenceTest.java
index af867e6..e20520f 100644
--- a/tests/robotests/src/com/android/settings/widget/AppCheckBoxPreferenceTest.java
+++ b/tests/robotests/src/com/android/settings/widget/AppCheckBoxPreferenceTest.java
@@ -19,6 +19,8 @@
import static com.google.common.truth.Truth.assertThat;
import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
import com.android.settings.R;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
@@ -28,18 +30,25 @@
import org.junit.runner.RunWith;
import org.robolectric.RuntimeEnvironment;
+import androidx.preference.PreferenceViewHolder;
+
@RunWith(SettingsRobolectricTestRunner.class)
public class AppCheckBoxPreferenceTest {
+ private static final String SUMMARY = "summary info";
+
private Context mContext;
private AppCheckBoxPreference mPreference;
private AppCheckBoxPreference mAttrPreference;
+ private PreferenceViewHolder mPreferenceViewHolder;
@Before
public void setUp() {
mContext = RuntimeEnvironment.application;
mPreference = new AppCheckBoxPreference(mContext);
mAttrPreference = new AppCheckBoxPreference(mContext, null /* attrs */);
+ mPreferenceViewHolder = PreferenceViewHolder.createInstanceForTests(
+ LayoutInflater.from(mContext).inflate(R.layout.preference_app, null));
}
@Test
@@ -47,4 +56,32 @@
assertThat(mPreference.getLayoutResource()).isEqualTo(R.layout.preference_app);
assertThat(mAttrPreference.getLayoutResource()).isEqualTo(R.layout.preference_app);
}
+
+ @Test
+ public void onBindViewHolder_noSummary_layoutGone() {
+ mPreference.setSummary("");
+
+ mPreference.onBindViewHolder(mPreferenceViewHolder);
+
+ assertThat(mPreferenceViewHolder.findViewById(R.id.summary_container).getVisibility())
+ .isEqualTo(View.GONE);
+ }
+
+ @Test
+ public void onBindViewHolder_hasSummary_layoutVisible() {
+ mPreference.setSummary(SUMMARY);
+
+ mPreference.onBindViewHolder(mPreferenceViewHolder);
+
+ assertThat(mPreferenceViewHolder.findViewById(R.id.summary_container).getVisibility())
+ .isEqualTo(View.VISIBLE);
+ }
+
+ @Test
+ public void onBindViewHolder_appendixGone() {
+ mPreference.onBindViewHolder(mPreferenceViewHolder);
+
+ assertThat(mPreferenceViewHolder.findViewById(R.id.appendix).getVisibility())
+ .isEqualTo(View.GONE);
+ }
}
diff --git a/tests/unit/src/com/android/settings/core/PreferenceControllerContractTest.java b/tests/unit/src/com/android/settings/core/PreferenceControllerContractTest.java
index 176d3c4..59f22db 100644
--- a/tests/unit/src/com/android/settings/core/PreferenceControllerContractTest.java
+++ b/tests/unit/src/com/android/settings/core/PreferenceControllerContractTest.java
@@ -19,6 +19,7 @@
import static junit.framework.Assert.fail;
import android.content.Context;
+import android.os.Looper;
import android.platform.test.annotations.Presubmit;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.MediumTest;
@@ -52,6 +53,7 @@
@Test
@Presubmit
public void controllersInSearchShouldImplementPreferenceControllerMixin() {
+ Looper.prepare(); // Required by AutofillLoggingLevelPreferenceController
final Set<String> errorClasses = new ArraySet<>();
final SearchIndexableResources resources =