Snap for 4919674 from 64771b5382 to qt-release
Change-Id: I04b220d2e6fdf20d3ed455d0d7789c9b964a0737
This commit is contained in:
@@ -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" />
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -32,6 +32,9 @@
|
||||
Can be overridden for specific product builds. -->
|
||||
<bool name="auto_confirm_bluetooth_activation_dialog">false</bool>
|
||||
|
||||
<!-- Whether the device name is shown in About device or not -->
|
||||
<bool name="config_show_device_name">true</bool>
|
||||
|
||||
<!-- Whether to show a preference item for the manual in About phone -->
|
||||
<bool name="config_show_manual">false</bool>
|
||||
<!-- Whether to show a preference item for regulatory information in About phone -->
|
||||
|
||||
@@ -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] -->
|
||||
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -19,6 +19,7 @@ package com.android.settings;
|
||||
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 @@ public class FallbackHome extends Activity {
|
||||
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 @@ public class FallbackHome extends Activity {
|
||||
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 @@ public class FallbackHome extends Activity {
|
||||
}
|
||||
|
||||
// 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 @@ public class FallbackHome extends Activity {
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
unregisterReceiver(mReceiver);
|
||||
if (mWallManager != null) {
|
||||
mWallManager.removeOnColorsChangedListener(mColorsChangedListener);
|
||||
}
|
||||
}
|
||||
|
||||
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
|
||||
@@ -141,6 +162,15 @@ public class FallbackHome extends Activity {
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
|
||||
@@ -315,7 +315,7 @@ public class DashboardAdapter extends RecyclerView.Adapter<DashboardAdapter.Dash
|
||||
|
||||
@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)) {
|
||||
|
||||
@@ -34,6 +34,9 @@ import android.util.ArrayMap;
|
||||
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.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.preference.Preference;
|
||||
|
||||
/**
|
||||
* Impl for {@code DashboardFeatureProvider}.
|
||||
*/
|
||||
@@ -238,7 +238,7 @@ public class DashboardFeatureProviderImpl implements DashboardFeatureProvider {
|
||||
|
||||
@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
|
||||
|
||||
@@ -24,6 +24,11 @@ import android.util.ArrayMap;
|
||||
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.List;
|
||||
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 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment
|
||||
|
||||
@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 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment
|
||||
&& 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 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment
|
||||
continue;
|
||||
}
|
||||
if (tintTileIcon(tile)) {
|
||||
tile.getIcon().setTint(tintColor);
|
||||
tile.getIcon(context).setTint(tintColor);
|
||||
}
|
||||
if (mDashboardTilePrefKeys.contains(key)) {
|
||||
// Have the key already, will rebind.
|
||||
|
||||
@@ -39,6 +39,8 @@ import com.android.settings.R;
|
||||
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 @@ public class DevelopmentSettingsDashboardFragment extends RestrictedDashboardFra
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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!
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,7 @@ import android.text.SpannedString;
|
||||
|
||||
import com.android.settings.bluetooth.BluetoothLengthDeviceNameFilter;
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.widget.ValidatedEditTextPreference;
|
||||
import com.android.settings.wifi.tether.WifiDeviceNameTextValidator;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothAdapter;
|
||||
@@ -90,7 +91,9 @@ public class DeviceNamePreferenceController extends BasePreferenceController
|
||||
|
||||
@Override
|
||||
public int getAvailabilityStatus() {
|
||||
return AVAILABLE;
|
||||
return mContext.getResources().getBoolean(R.bool.config_show_device_name)
|
||||
? AVAILABLE
|
||||
: UNSUPPORTED_ON_DEVICE;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -21,8 +21,8 @@ import android.content.Context;
|
||||
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 @@ import androidx.preference.SwitchPreference;
|
||||
* 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
|
||||
|
||||
@@ -27,6 +27,7 @@ import android.widget.TextView;
|
||||
|
||||
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 @@ import androidx.preference.PreferenceScreen;
|
||||
/**
|
||||
* 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 @@ public class BatteryHeaderPreferenceController extends AbstractPreferenceControl
|
||||
@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 @@ public class BatteryHeaderPreferenceController extends AbstractPreferenceControl
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPreferenceKey() {
|
||||
return KEY_BATTERY_HEADER;
|
||||
public int getAvailabilityStatus() {
|
||||
return AVAILABLE_UNSEARCHABLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -38,11 +38,14 @@ import com.android.internal.os.BatterySipper;
|
||||
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 @@ public class BatteryUtils {
|
||||
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 @@ public class BatteryUtils {
|
||||
}
|
||||
// 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) {
|
||||
|
||||
@@ -25,7 +25,6 @@ import android.os.Bundle;
|
||||
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.Utils;
|
||||
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;
|
||||
|
||||
@@ -197,6 +192,22 @@ public class PowerUsageSummary extends PowerUsageBase implements OnLongClickList
|
||||
}
|
||||
};
|
||||
|
||||
@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);
|
||||
@@ -231,22 +242,6 @@ public class PowerUsageSummary extends PowerUsageBase implements OnLongClickList
|
||||
return R.xml.power_usage_summary;
|
||||
}
|
||||
|
||||
@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) {
|
||||
|
||||
@@ -22,6 +22,8 @@ import android.content.pm.PackageManager;
|
||||
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.Utils;
|
||||
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.RestrictAppTip;
|
||||
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 @@ public class RestrictedAppDetails extends DashboardFragment implements
|
||||
@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 @@ public class RestrictedAppDetails extends DashboardFragment implements
|
||||
BatteryUtils mBatteryUtils;
|
||||
@VisibleForTesting
|
||||
PackageManager mPackageManager;
|
||||
@VisibleForTesting
|
||||
BatteryDatabaseManager mBatteryDatabaseManager;
|
||||
private final FooterPreferenceMixinCompat mFooterPreferenceMixin =
|
||||
new FooterPreferenceMixinCompat(this, getSettingsLifecycle());
|
||||
|
||||
@@ -96,6 +104,7 @@ public class RestrictedAppDetails extends DashboardFragment implements
|
||||
mPackageManager = context.getPackageManager();
|
||||
mIconDrawableFactory = IconDrawableFactory.newInstance(context);
|
||||
mBatteryUtils = BatteryUtils.getInstance(context);
|
||||
mBatteryDatabaseManager = BatteryDatabaseManager.getInstance(context);
|
||||
|
||||
refreshUi();
|
||||
}
|
||||
@@ -135,6 +144,9 @@ public class RestrictedAppDetails extends DashboardFragment implements
|
||||
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 @@ public class RestrictedAppDetails extends DashboardFragment implements
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ public class AnomalyDatabaseHelper extends SQLiteOpenHelper {
|
||||
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 @@ public class AnomalyDatabaseHelper extends SQLiteOpenHelper {
|
||||
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 @@ public class AnomalyDatabaseHelper extends SQLiteOpenHelper {
|
||||
+ 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 @@ public class AnomalyDatabaseHelper extends SQLiteOpenHelper {
|
||||
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 @@ public class AnomalyDatabaseHelper extends SQLiteOpenHelper {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.An
|
||||
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.Cursor;
|
||||
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 @@ public class BatteryDatabaseManager {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,24 +59,27 @@ public class BatteryTipPreferenceController extends BasePreferenceController {
|
||||
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
|
||||
|
||||
@@ -84,8 +84,7 @@ public class ChangeScreenLockPreferenceController extends AbstractPreferenceCont
|
||||
@Override
|
||||
public void updateState(Preference preference) {
|
||||
if (mPreference != null && mPreference instanceof GearPreference) {
|
||||
if (mLockPatternUtils.isSecure(mUserId)
|
||||
|| !mLockPatternUtils.isLockScreenDisabled(mUserId)) {
|
||||
if (mLockPatternUtils.isSecure(mUserId)) {
|
||||
((GearPreference) mPreference).setOnGearClickListener(this);
|
||||
} else {
|
||||
((GearPreference) mPreference).setOnGearClickListener(null);
|
||||
|
||||
@@ -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 @@ public class AppCheckBoxPreference extends CheckBoxPreference {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,12 +23,14 @@ import android.text.style.TextAppearanceSpan;
|
||||
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 @@ public class LinkablePreference extends Preference {
|
||||
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 @@ public class LinkablePreference extends Preference {
|
||||
|
||||
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.
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
com.android.settings.fuelgauge.PowerUsageSummary
|
||||
|
||||
@@ -61,6 +61,7 @@
|
||||
<bool name="config_show_wifi_ip_address">false</bool>
|
||||
<bool name="config_show_wifi_mac_address">false</bool>
|
||||
<bool name="config_disable_uninstall_update">true</bool>
|
||||
<bool name="config_show_device_name">false</bool>
|
||||
|
||||
<!-- List of a11y components on the device allowed to be enabled by Settings Slices -->
|
||||
<string-array name="config_settings_slices_accessibility_components" translatable="false">
|
||||
|
||||
@@ -37,6 +37,7 @@ import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||
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 @@ public class RemoteDeviceNameDialogFragmentTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void deviceNameDisplayIsCorrect() {
|
||||
String deviceName = "ABC Corp Headphones";
|
||||
AlertDialog dialog = startDialog(deviceName);
|
||||
@@ -95,6 +97,7 @@ public class RemoteDeviceNameDialogFragmentTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void deviceNameEditSucceeds() {
|
||||
String deviceNameInitial = "ABC Corp Headphones";
|
||||
String deviceNameModified = "My Headphones";
|
||||
@@ -117,6 +120,7 @@ public class RemoteDeviceNameDialogFragmentTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void deviceNameEditThenCancelDoesntRename() {
|
||||
String deviceNameInitial = "ABC Corp Headphones";
|
||||
String deviceNameModified = "My Headphones";
|
||||
|
||||
@@ -203,9 +203,9 @@ public class DashboardAdapterTest {
|
||||
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 @@ public class DashboardAdapterTest {
|
||||
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 @@ public class DashboardAdapterTest {
|
||||
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 @@ public class DashboardAdapterTest {
|
||||
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 @@ public class DashboardAdapterTest {
|
||||
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 @@ public class DashboardAdapterTest {
|
||||
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 @@ public class DashboardAdapterTest {
|
||||
|
||||
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) {
|
||||
|
||||
@@ -120,7 +120,7 @@ public class DashboardFeatureProviderImplTest {
|
||||
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;
|
||||
|
||||
@@ -17,6 +17,7 @@ package com.android.settings.dashboard;
|
||||
|
||||
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 @@ public class DashboardFragmentTest {
|
||||
@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 @@ public class DashboardFragmentTest {
|
||||
@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(
|
||||
|
||||
@@ -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]);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.android.settings.deviceinfo;
|
||||
|
||||
import static com.android.settings.core.BasePreferenceController.AVAILABLE;
|
||||
import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
@@ -41,6 +43,7 @@ import org.mockito.Answers;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.shadows.ShadowApplication;
|
||||
|
||||
import androidx.preference.PreferenceScreen;
|
||||
@@ -79,6 +82,17 @@ public class DeviceNamePreferenceControllerTest {
|
||||
mController.setLocalBluetoothManager(mBluetoothManager);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailibilityStatus_availableByDefault() {
|
||||
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Config(qualifiers = "mcc999")
|
||||
public void getAvailabilityStatus_unsupportedWhenSet() {
|
||||
assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void constructor_defaultDeviceNameIsModelName() {
|
||||
assertThat(mController.getSummary()).isEqualTo(Build.MODEL);
|
||||
|
||||
@@ -32,13 +32,15 @@ import org.robolectric.RuntimeEnvironment;
|
||||
@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() {
|
||||
|
||||
@@ -22,6 +22,7 @@ import static org.mockito.Mockito.spy;
|
||||
|
||||
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 @@ public class BatteryDatabaseManagerTest {
|
||||
}
|
||||
|
||||
@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 @@ public class BatteryDatabaseManagerTest {
|
||||
}
|
||||
|
||||
@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 @@ public class BatteryDatabaseManagerTest {
|
||||
}
|
||||
|
||||
@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 @@ public class BatteryDatabaseManagerTest {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ import android.widget.TextView;
|
||||
|
||||
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 @@ import androidx.recyclerview.widget.RecyclerView;
|
||||
})
|
||||
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 @@ public class BatteryHeaderPreferenceControllerTest {
|
||||
|
||||
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 @@ public class BatteryHeaderPreferenceControllerTest {
|
||||
assertThat(mBatteryMeterView.getPowerSave()).isEqualTo(value);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_returnAvailableUnsearchable() {
|
||||
assertThat(mController.getAvailabilityStatus()).isEqualTo(
|
||||
BasePreferenceController.AVAILABLE_UNSEARCHABLE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,9 +51,12 @@ import android.text.format.DateUtils;
|
||||
|
||||
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 @@ public class BatteryUtilsTest {
|
||||
private ApplicationInfo mLowApplicationInfo;
|
||||
@Mock
|
||||
private PowerWhitelistBackend mPowerWhitelistBackend;
|
||||
@Mock
|
||||
private BatteryDatabaseManager mBatteryDatabaseManager;
|
||||
private AnomalyInfo mAnomalyInfo;
|
||||
private BatteryUtils mBatteryUtils;
|
||||
private FakeFeatureFactory mFeatureFactory;
|
||||
@@ -225,6 +230,8 @@ public class BatteryUtilsTest {
|
||||
.thenReturn(TOTAL_BATTERY_USAGE + BATTERY_SCREEN_USAGE);
|
||||
when(mBatteryStatsHelper.getStats().getDischargeAmount(anyInt()))
|
||||
.thenReturn(DISCHARGE_AMOUNT);
|
||||
BatteryDatabaseManager.setUpForTest(mBatteryDatabaseManager);
|
||||
ShadowThreadUtils.setIsMainThread(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -569,6 +576,23 @@ public class BatteryUtilsTest {
|
||||
HIGH_SDK_PACKAGE, AppOpsManager.MODE_IGNORED);
|
||||
}
|
||||
|
||||
@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,
|
||||
|
||||
@@ -222,21 +222,6 @@ public class PowerUsageSummaryTest {
|
||||
assertThat(keys).containsAllIn(niks);
|
||||
}
|
||||
|
||||
@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
|
||||
|
||||
@@ -28,10 +28,13 @@ import android.content.pm.PackageManager;
|
||||
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 org.robolectric.annotation.Config;
|
||||
|
||||
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 @@ public class RestrictedAppDetailsTest {
|
||||
private IconDrawableFactory mIconDrawableFactory;
|
||||
@Mock
|
||||
private InstrumentedPreferenceFragment mFragment;
|
||||
@Mock
|
||||
private BatteryDatabaseManager mBatteryDatabaseManager;
|
||||
private PreferenceManager mPreferenceManager;
|
||||
private RestrictedAppDetails mRestrictedAppDetails;
|
||||
private Context mContext;
|
||||
@@ -98,12 +104,14 @@ public class RestrictedAppDetailsTest {
|
||||
|
||||
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 @@ public class RestrictedAppDetailsTest {
|
||||
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 @@ public class RestrictedAppDetailsTest {
|
||||
(CheckBoxPreference) mRestrictedAppDetails.mRestrictedAppListGroup.getPreference(0);
|
||||
assertThat(preference.getTitle()).isEqualTo(APP_NAME);
|
||||
assertThat(preference.isChecked()).isTrue();
|
||||
assertThat(preference.getSummary()).isEqualTo("Restricted 5 hours ago");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -31,6 +31,7 @@ import android.text.format.DateUtils;
|
||||
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 @@ public class BatteryTipPreferenceControllerTest {
|
||||
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 @@ public class BatteryTipPreferenceControllerTest {
|
||||
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 @@ public class BatteryTipPreferenceControllerTest {
|
||||
// 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 @@ public class BatteryTipPreferenceControllerTest {
|
||||
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 @@ public class BatteryTipPreferenceControllerTest {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,17 +17,28 @@
|
||||
package com.android.settings.security;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.app.admin.DevicePolicyManager;
|
||||
import android.content.Context;
|
||||
import android.os.UserManager;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.preference.PreferenceScreen;
|
||||
import androidx.preference.PreferenceViewHolder;
|
||||
|
||||
import com.android.internal.widget.LockPatternUtils;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.testutils.FakeFeatureFactory;
|
||||
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
||||
import com.android.settings.testutils.shadow.ShadowUtils;
|
||||
import com.android.settings.widget.GearPreference;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -47,10 +58,15 @@ public class ChangeScreenLockPreferenceControllerTest {
|
||||
private UserManager mUserManager;
|
||||
@Mock
|
||||
private DevicePolicyManager mDevicePolicyManager;
|
||||
@Mock
|
||||
private PreferenceScreen mPreferenceScreen;
|
||||
|
||||
private Context mContext;
|
||||
private FakeFeatureFactory mFeatureFactory;
|
||||
private ChangeScreenLockPreferenceController mController;
|
||||
private View mGearView;
|
||||
private GearPreference mGearPreference;
|
||||
private PreferenceViewHolder mPreferenceViewHolder;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
@@ -75,4 +91,149 @@ public class ChangeScreenLockPreferenceControllerTest {
|
||||
public void testDeviceAdministrators_ifDisabled_shouldNotBeShown() {
|
||||
assertThat(mController.isAvailable()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateState_notSecureDisableKeyguard_shouldNotShowGear() {
|
||||
when(mLockPatternUtils.isSecure(anyInt())).thenReturn(false);
|
||||
when(mLockPatternUtils.isLockScreenDisabled(anyInt())).thenReturn(true);
|
||||
mockGearPreferenceAndViewHolder();
|
||||
|
||||
showPreference();
|
||||
|
||||
assertThat(mGearView.getVisibility()).isEqualTo(View.GONE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateState_notSecureDisableKeyguard_summaryShouldShowOff() {
|
||||
when(mLockPatternUtils.isSecure(anyInt())).thenReturn(false);
|
||||
when(mLockPatternUtils.isLockScreenDisabled(anyInt())).thenReturn(true);
|
||||
mockGearPreferenceAndViewHolder();
|
||||
|
||||
showPreference();
|
||||
|
||||
assertThat(mGearPreference.getSummary())
|
||||
.isEqualTo(mContext.getString(R.string.unlock_set_unlock_mode_off));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateState_notSecureWithSwipeKeyguard_shouldNotShowGear() {
|
||||
when(mLockPatternUtils.isSecure(anyInt())).thenReturn(false);
|
||||
when(mLockPatternUtils.isLockScreenDisabled(anyInt())).thenReturn(false);
|
||||
mockGearPreferenceAndViewHolder();
|
||||
|
||||
showPreference();
|
||||
|
||||
assertThat(mGearView.getVisibility()).isEqualTo(View.GONE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateState_notSecureWithSwipeKeyguard_summaryShouldShowSwipe() {
|
||||
when(mLockPatternUtils.isSecure(anyInt())).thenReturn(false);
|
||||
when(mLockPatternUtils.isLockScreenDisabled(anyInt())).thenReturn(false);
|
||||
mockGearPreferenceAndViewHolder();
|
||||
|
||||
showPreference();
|
||||
|
||||
assertThat(mGearPreference.getSummary())
|
||||
.isEqualTo(mContext.getString(R.string.unlock_set_unlock_mode_none));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateState_secureWithPinKeyguard_shouldShowGear() {
|
||||
when(mLockPatternUtils.isSecure(anyInt())).thenReturn(true);
|
||||
when(mLockPatternUtils.isLockScreenDisabled(anyInt())).thenReturn(false);
|
||||
doReturn(DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX).when(mLockPatternUtils)
|
||||
.getKeyguardStoredPasswordQuality(anyInt());
|
||||
mockGearPreferenceAndViewHolder();
|
||||
|
||||
showPreference();
|
||||
|
||||
assertThat(mGearView.getVisibility()).isEqualTo(View.VISIBLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateState_secureWithPinKeyguard_summaryShouldShowPin() {
|
||||
when(mLockPatternUtils.isSecure(anyInt())).thenReturn(true);
|
||||
when(mLockPatternUtils.isLockScreenDisabled(anyInt())).thenReturn(false);
|
||||
doReturn(DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX).when(mLockPatternUtils)
|
||||
.getKeyguardStoredPasswordQuality(anyInt());
|
||||
|
||||
mockGearPreferenceAndViewHolder();
|
||||
|
||||
showPreference();
|
||||
|
||||
assertThat(mGearPreference.getSummary())
|
||||
.isEqualTo(mContext.getString(R.string.unlock_set_unlock_mode_pin));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateState_secureWithPasswordKeyguard_shouldShowGear() {
|
||||
when(mLockPatternUtils.isSecure(anyInt())).thenReturn(true);
|
||||
when(mLockPatternUtils.isLockScreenDisabled(anyInt())).thenReturn(false);
|
||||
doReturn(DevicePolicyManager.PASSWORD_QUALITY_COMPLEX).when(mLockPatternUtils)
|
||||
.getKeyguardStoredPasswordQuality(anyInt());
|
||||
mockGearPreferenceAndViewHolder();
|
||||
|
||||
showPreference();
|
||||
|
||||
assertThat(mGearView.getVisibility()).isEqualTo(View.VISIBLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateState_secureWithPasswordKeyguard_summaryShouldShowPassword() {
|
||||
when(mLockPatternUtils.isSecure(anyInt())).thenReturn(true);
|
||||
when(mLockPatternUtils.isLockScreenDisabled(anyInt())).thenReturn(false);
|
||||
doReturn(DevicePolicyManager.PASSWORD_QUALITY_COMPLEX).when(mLockPatternUtils)
|
||||
.getKeyguardStoredPasswordQuality(anyInt());
|
||||
mockGearPreferenceAndViewHolder();
|
||||
|
||||
showPreference();
|
||||
|
||||
assertThat(mGearPreference.getSummary())
|
||||
.isEqualTo(mContext.getString(R.string.unlock_set_unlock_mode_password));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateState_secureWithPatternKeyguard_shouldShowGear() {
|
||||
when(mLockPatternUtils.isSecure(anyInt())).thenReturn(true);
|
||||
when(mLockPatternUtils.isLockScreenDisabled(anyInt())).thenReturn(false);
|
||||
doReturn(DevicePolicyManager.PASSWORD_QUALITY_SOMETHING).when(mLockPatternUtils)
|
||||
.getKeyguardStoredPasswordQuality(anyInt());
|
||||
mockGearPreferenceAndViewHolder();
|
||||
|
||||
showPreference();
|
||||
|
||||
assertThat(mGearView.getVisibility()).isEqualTo(View.VISIBLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateState_secureWithPatternKeyguard_summaryShouldShowPattern() {
|
||||
when(mLockPatternUtils.isSecure(anyInt())).thenReturn(true);
|
||||
when(mLockPatternUtils.isLockScreenDisabled(anyInt())).thenReturn(false);
|
||||
doReturn(DevicePolicyManager.PASSWORD_QUALITY_SOMETHING).when(mLockPatternUtils)
|
||||
.getKeyguardStoredPasswordQuality(anyInt());
|
||||
mockGearPreferenceAndViewHolder();
|
||||
|
||||
showPreference();
|
||||
|
||||
assertThat(mGearPreference.getSummary())
|
||||
.isEqualTo(mContext.getString(R.string.unlock_set_unlock_mode_pattern));
|
||||
}
|
||||
|
||||
private void mockGearPreferenceAndViewHolder() {
|
||||
mGearPreference = new GearPreference(mContext, null);
|
||||
mGearView = new View(mContext);
|
||||
PreferenceViewHolder viewHolder = PreferenceViewHolder.createInstanceForTests(
|
||||
LayoutInflater.from(mContext).inflate(
|
||||
mGearPreference.getLayoutResource(), null, false));
|
||||
mPreferenceViewHolder = spy(viewHolder);
|
||||
doReturn(mGearView).when(mPreferenceViewHolder).findViewById(R.id.settings_button);
|
||||
when(mPreferenceScreen.findPreference(anyString())).thenReturn(mGearPreference);
|
||||
}
|
||||
|
||||
private void showPreference() {
|
||||
mController.displayPreference(mPreferenceScreen);
|
||||
mController.updateState(mGearPreference);
|
||||
mGearPreference.onBindViewHolder(mPreferenceViewHolder);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,8 @@ package com.android.settings.widget;
|
||||
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.Test;
|
||||
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 @@ public class AppCheckBoxPreferenceTest {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ package com.android.settings.core;
|
||||
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 @@ public class PreferenceControllerContractTest {
|
||||
@Test
|
||||
@Presubmit
|
||||
public void controllersInSearchShouldImplementPreferenceControllerMixin() {
|
||||
Looper.prepare(); // Required by AutofillLoggingLevelPreferenceController
|
||||
final Set<String> errorClasses = new ArraySet<>();
|
||||
|
||||
final SearchIndexableResources resources =
|
||||
|
||||
Reference in New Issue
Block a user