Snap for 4919674 from 64771b5382 to qt-release

Change-Id: I04b220d2e6fdf20d3ed455d0d7789c9b964a0737
This commit is contained in:
android-build-team Robot
2018-07-29 03:12:03 +00:00
52 changed files with 1626 additions and 171 deletions

View File

@@ -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" />

View File

@@ -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>

View File

@@ -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 -->

View File

@@ -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] -->

View File

@@ -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>

View File

@@ -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>

View File

@@ -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

View File

@@ -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) {

View File

@@ -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)) {

View File

@@ -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

View File

@@ -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.

View File

@@ -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;
}

View File

@@ -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);
}
}
}

View File

@@ -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!
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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) {

View File

@@ -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) {

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}
}

View File

@@ -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

View File

@@ -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);

View File

@@ -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);
}
}
}

View File

@@ -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.

View File

@@ -1 +0,0 @@
com.android.settings.fuelgauge.PowerUsageSummary

View File

@@ -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">

View File

@@ -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";

View File

@@ -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) {

View File

@@ -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;

View File

@@ -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(

View File

@@ -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]);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);

View File

@@ -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() {

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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,

View File

@@ -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

View File

@@ -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

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}

View File

@@ -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 =