Snap for 4587185 from 99fc2a7ea4 to pi-release

Change-Id: I0e3a4949b189ea71a7b1e1305f27dc1b25c019f4
This commit is contained in:
android-build-team Robot
2018-02-06 08:23:11 +00:00
54 changed files with 1411 additions and 295 deletions

View File

@@ -22,7 +22,7 @@
<dimen name="action_bar_switch_padding">16dip</dimen>
<dimen name="app_icon_size">40dip</dimen>
<dimen name="secondary_app_icon_size">24dp</dimen>
<dimen name="secondary_app_icon_size">32dp</dimen>
<dimen name="min_tap_target_size">48dp</dimen>
<dimen name="screen_margin_sides">64dip</dimen>
<dimen name="screen_margin_top">72dip</dimen>

View File

@@ -2259,9 +2259,9 @@
<!-- Wireless networks, item title to go into the WFC settings [CHAR LIMIT=30] -->
<string name="wifi_calling_settings_title">Wi-Fi calling</string>
<!-- Title of suggestion to turn on wifi calling [CHAR LIMIT=30] -->
<string name="wifi_calling_suggestion_title">Turn on Wi-Fi Calling</string>
<string name="wifi_calling_suggestion_title">Extend call coverage with Wi\u2011Fi</string>
<!-- Summary of suggestion to turn on wifi calling [CHAR LIMIT=60] -->
<string name="wifi_calling_suggestion_summary">Extend coverage by calling over Wi-Fi</string>
<string name="wifi_calling_suggestion_summary">Turn on Wi\u2011Fi calling</string>
<!-- Title of WFC preference item [CHAR LIMIT=30] -->
<string name="wifi_calling_mode_title">Calling preference</string>
<!-- Title of WFC preference selection dialog [CHAR LIMIT=30] -->
@@ -4842,6 +4842,41 @@
<string name="battery_tip_dialog_message" product="tablet">Your tablet was used heavily and this consumed a lot of battery. Your battery is behaving normally.\n\n Your tablet was used for about <xliff:g id="hour">%1$s</xliff:g> since last full charge.\n\n Total usage:</string>
<!-- Message for battery tip dialog to show the status about the battery [CHAR LIMIT=NONE] -->
<string name="battery_tip_dialog_message" product="device">Your device was used heavily and this consumed a lot of battery. Your battery is behaving normally.\n\n Your device was used for about <xliff:g id="hour">%1$s</xliff:g> since last full charge.\n\n Total usage:</string>
<!-- Title for restricted app preference, showing how many app need to be restricted [CHAR LIMIT=NONE] -->
<plurals name="battery_tip_restrict_title">
<item quantity="one">Restrict %1$d app</item>
<item quantity="other">Restrict %1$d apps</item>
</plurals>
<!-- Title for restricted app preference, showing how many app been restricted [CHAR LIMIT=NONE] -->
<plurals name="battery_tip_restrict_handled_title">
<item quantity="one">%1$d recently restricted</item>
<item quantity="other">%1$d apps recently restricted</item>
</plurals>
<!-- Summary for restricted app preference, showing the impact of the apps [CHAR LIMIT=NONE] -->
<plurals name="battery_tip_restrict_summary">
<item quantity="one">%1$s has high battery usage</item>
<item quantity="other">%2$d apps have high battery usage</item>
</plurals>
<!-- Summary for restricted app preference, showing the impact of the apps [CHAR LIMIT=NONE] -->
<string name="battery_tip_restrict_handled_summary">App changes are in progress</string>
<!-- Title for dialog to restrict the app [CHAR LIMIT=NONE] -->
<plurals name="battery_tip_restrict_app_dialog_title">
<item quantity="one">Restrict app?</item>
<item quantity="other">Restrict %1$d apps?</item>
</plurals>
<!-- Message for battery tip dialog to show the restrict app list [CHAR LIMIT=NONE] -->
<string name="battery_tip_restrict_app_dialog_message">To save battery, you can stop this app from running in the background when its not being used.</string>
<!-- OK button for battery tip dialog to show the restrict app list [CHAR LIMIT=NONE] -->
<string name="battery_tip_restrict_app_dialog_ok">Restrict</string>
<!-- Title for dialog to remove restriction for the app [CHAR LIMIT=NONE] -->
<string name="battery_tip_unrestrict_app_dialog_title">Remove restriction for <xliff:g id="app">%1$s</xliff:g>?</string>
<!-- Message for dialog to show the impact if remove restriction for app [CHAR LIMIT=NONE] -->
<string name="battery_tip_unrestrict_app_dialog_message">This app will be able to use battery in the background. This may cause your battery to be used up faster.</string>
<!-- OK button for dialog to remove restriction for app [CHAR LIMIT=NONE] -->
<string name="battery_tip_unrestrict_app_dialog_ok">Remove</string>
<!-- CANCEL button for dialog to remove restriction for app [CHAR LIMIT=NONE] -->
<string name="battery_tip_unrestrict_app_dialog_cancel">Not now</string>
<!-- Title for the smart battery manager preference [CHAR LIMIT=NONE] -->
<string name="smart_battery_manager_title">Smart battery manager</string>

View File

@@ -49,5 +49,9 @@
<PreferenceCategory
android:key="location_services"
android:title="@string/location_category_location_services" />
android:title="@string/location_category_location_services"/>
<PreferenceCategory
android:key="location_footer"
settings:allowDividerAbove="false"/>
</PreferenceScreen>

View File

@@ -16,6 +16,7 @@
package com.android.settings;
import android.annotation.Nullable;
import android.app.Activity;
import android.app.StatusBarManager;
import android.content.Context;
@@ -35,11 +36,11 @@ import android.widget.Button;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.widget.LockPatternUtils;
import com.android.settings.core.InstrumentedPreferenceFragment;
import com.android.settings.core.InstrumentedFragment;
import java.util.Locale;
public class CryptKeeperConfirm extends InstrumentedPreferenceFragment {
public class CryptKeeperConfirm extends InstrumentedFragment {
private static final String TAG = "CryptKeeperConfirm";
@@ -153,6 +154,12 @@ public class CryptKeeperConfirm extends InstrumentedPreferenceFragment {
mFinalButton.setOnClickListener(mFinalClickListener);
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getActivity().setTitle(R.string.crypt_keeper_confirm_title);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {

View File

@@ -55,7 +55,7 @@ import android.widget.ScrollView;
import android.widget.TextView;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.core.InstrumentedPreferenceFragment;
import com.android.settings.core.InstrumentedFragment;
import com.android.settings.password.ChooseLockSettingsHelper;
import com.android.settings.password.ConfirmLockPattern;
import com.android.settingslib.RestrictedLockUtils;
@@ -72,7 +72,7 @@ import java.util.List;
*
* This is the initial screen.
*/
public class MasterClear extends InstrumentedPreferenceFragment {
public class MasterClear extends InstrumentedFragment {
private static final String TAG = "MasterClear";
@VisibleForTesting static final int KEYGUARD_REQUEST = 55;

View File

@@ -33,7 +33,7 @@ import android.widget.Button;
import android.widget.TextView;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.core.InstrumentedPreferenceFragment;
import com.android.settings.core.InstrumentedFragment;
import com.android.settingslib.RestrictedLockUtils;
import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
@@ -48,7 +48,7 @@ import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
*
* This is the confirmation screen.
*/
public class MasterClearConfirm extends InstrumentedPreferenceFragment {
public class MasterClearConfirm extends InstrumentedFragment {
private View mContentView;
private boolean mEraseSdCard;

View File

@@ -41,9 +41,9 @@ import android.widget.TextView;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.SettingsPreferenceFragment.SettingsDialogFragment;
import com.android.settings.core.InstrumentedPreferenceFragment;
import com.android.settings.core.InstrumentedFragment;
public class ProxySelector extends InstrumentedPreferenceFragment implements DialogCreatable {
public class ProxySelector extends InstrumentedFragment implements DialogCreatable {
private static final String TAG = "ProxySelector";
EditText mHostnameField;
@@ -58,11 +58,6 @@ public class ProxySelector extends InstrumentedPreferenceFragment implements Dia
private SettingsDialogFragment mDialogFragment;
private View mView;
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
@@ -179,6 +174,8 @@ public class ProxySelector extends InstrumentedPreferenceFragment implements Dia
String title = intent.getStringExtra("title");
if (!TextUtils.isEmpty(title)) {
activity.setTitle(title);
} else {
activity.setTitle(R.string.proxy_settings_title);
}
}

View File

@@ -43,7 +43,7 @@ import android.widget.TextView;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.telephony.PhoneConstants;
import com.android.settings.core.InstrumentedPreferenceFragment;
import com.android.settings.core.InstrumentedFragment;
import com.android.settings.password.ChooseLockSettingsHelper;
import com.android.settings.password.ConfirmLockPattern;
import com.android.settingslib.RestrictedLockUtils;
@@ -61,7 +61,7 @@ import java.util.List;
*
* This is the initial screen.
*/
public class ResetNetwork extends InstrumentedPreferenceFragment {
public class ResetNetwork extends InstrumentedFragment {
private static final String TAG = "ResetNetwork";
// Arbitrary to avoid conficts

View File

@@ -42,8 +42,8 @@ import android.widget.Toast;
import com.android.ims.ImsManager;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.telephony.PhoneConstants;
import com.android.settings.core.InstrumentedPreferenceFragment;
import com.android.settings.wrapper.RecoverySystemWrapper;
import com.android.settings.core.InstrumentedFragment;
import com.android.settingslib.RestrictedLockUtils;
import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
@@ -58,7 +58,7 @@ import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
*
* This is the confirmation screen.
*/
public class ResetNetworkConfirm extends InstrumentedPreferenceFragment {
public class ResetNetworkConfirm extends InstrumentedFragment {
private View mContentView;
private int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;

View File

@@ -65,7 +65,7 @@ import com.android.internal.annotations.GuardedBy;
import com.android.internal.app.UnlaunchableAppActivity;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.widget.LockPatternUtils;
import com.android.settings.core.InstrumentedPreferenceFragment;
import com.android.settings.core.InstrumentedFragment;
import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;
@@ -75,7 +75,7 @@ import java.util.List;
import java.util.Set;
import java.util.function.IntConsumer;
public class TrustedCredentialsSettings extends InstrumentedPreferenceFragment
public class TrustedCredentialsSettings extends InstrumentedFragment
implements TrustedCredentialsDialogBuilder.DelegateInterface {
public static final String ARG_SHOW_NEW_FOR_USER = "ARG_SHOW_NEW_FOR_USER";
@@ -117,7 +117,8 @@ public class TrustedCredentialsSettings extends InstrumentedPreferenceFragment
private final int mContentView;
private final boolean mSwitch;
private Tab(String tag, int label, int view, int progress, int contentView, boolean withSwitch) {
private Tab(String tag, int label, int view, int progress, int contentView,
boolean withSwitch) {
mTag = tag;
mLabel = label;
mView = view;

View File

@@ -34,7 +34,7 @@ import android.widget.TextView;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.core.InstrumentedPreferenceFragment;
import com.android.settings.core.InstrumentedFragment;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
import com.android.settingslib.utils.ThreadUtils;
@@ -45,7 +45,7 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
public class RunningServiceDetails extends InstrumentedPreferenceFragment
public class RunningServiceDetails extends InstrumentedFragment
implements RunningState.OnRefreshUiListener {
static final String TAG = "RunningServicesDetails";

View File

@@ -251,16 +251,16 @@ public class DefaultAutofillPicker extends DefaultAppPickerFragment {
static final class AutofillSettingIntentProvider implements SettingIntentProvider {
private final String mSelectedKey;
private final PackageManager mPackageManager;
private final Context mContext;
public AutofillSettingIntentProvider(PackageManager packageManager, String key) {
public AutofillSettingIntentProvider(Context context, String key) {
mSelectedKey = key;
mPackageManager = packageManager;
mContext = context;
}
@Override
public Intent getIntent() {
final List<ResolveInfo> resolveInfos = mPackageManager.queryIntentServices(
final List<ResolveInfo> resolveInfos = mContext.getPackageManager().queryIntentServices(
AUTOFILL_PROBE, PackageManager.GET_META_DATA);
for (ResolveInfo resolveInfo : resolveInfos) {
@@ -270,7 +270,7 @@ public class DefaultAutofillPicker extends DefaultAppPickerFragment {
if (TextUtils.equals(mSelectedKey, flattenKey)) {
final String settingsActivity;
try {
settingsActivity = new AutofillServiceInfo(mPackageManager, serviceInfo)
settingsActivity = new AutofillServiceInfo(mContext, serviceInfo)
.getSettingsActivity();
} catch (SecurityException e) {
// Service does not declare the proper permission, ignore it.

View File

@@ -53,7 +53,7 @@ public class DefaultAutofillPreferenceController extends DefaultAppPreferenceCon
}
final DefaultAutofillPicker.AutofillSettingIntentProvider intentProvider =
new DefaultAutofillPicker.AutofillSettingIntentProvider(
mPackageManager.getPackageManager(), info.getKey());
mContext, info.getKey());
return intentProvider.getIntent();
}

View File

@@ -268,6 +268,7 @@ public class DashboardSummary extends InstrumentedFragment
mSummaryLoader.updateSummaryToCache(category);
mStagingCategory = category;
if (mSuggestionControllerMixin == null) {
mAdapter.setCategory(mStagingCategory);
return;
}
if (mSuggestionControllerMixin.isSuggestionLoaded()) {

View File

@@ -21,12 +21,12 @@ import android.hardware.fingerprint.FingerprintManager.AuthenticationResult;
import android.os.CancellationSignal;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.core.InstrumentedPreferenceFragment;
import com.android.settings.core.InstrumentedFragment;
/**
* Sidecar fragment to handle the state around fingerprint authentication
*/
public class FingerprintAuthenticateSidecar extends InstrumentedPreferenceFragment {
public class FingerprintAuthenticateSidecar extends InstrumentedFragment {
private static final String TAG = "FingerprintAuthenticateSidecar";

View File

@@ -21,7 +21,7 @@ import android.content.Context;
import android.hardware.fingerprint.Fingerprint;
import android.hardware.fingerprint.FingerprintManager;
import android.os.Bundle;
import com.android.settings.core.InstrumentedPreferenceFragment;
import com.android.settings.core.InstrumentedFragment;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import android.os.UserHandle;
import java.util.Queue;
@@ -31,7 +31,7 @@ import android.util.Log;
/**
* Sidecar fragment to handle the state around fingerprint removal.
*/
public class FingerprintRemoveSidecar extends InstrumentedPreferenceFragment {
public class FingerprintRemoveSidecar extends InstrumentedFragment {
private static final String TAG = "FingerprintRemoveSidecar";
private Listener mListener;
@@ -99,20 +99,6 @@ public class FingerprintRemoveSidecar extends InstrumentedPreferenceFragment {
setRetainInstance(true);
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
}
@Override
public void onResume() {
super.onResume();
}
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
}
public void setListener(Listener listener) {
if (mListener == null && listener != null) {
while (!mFingerprintsRemoved.isEmpty()) {

View File

@@ -46,6 +46,8 @@ import com.android.settings.Utils;
import com.android.settings.applications.LayoutPreference;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.fuelgauge.anomaly.AnomalyUtils;
import com.android.settings.fuelgauge.batterytip.BatteryTipPreferenceController;
import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
import com.android.settings.wrapper.DevicePolicyManagerWrapper;
import com.android.settings.fuelgauge.anomaly.Anomaly;
import com.android.settings.fuelgauge.anomaly.AnomalyDialogFragment;
@@ -69,7 +71,7 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements
ButtonActionDialogFragment.AppButtonsDialogListener,
AnomalyDialogFragment.AnomalyDialogListener,
LoaderManager.LoaderCallbacks<List<Anomaly>>,
BackgroundActivityPreferenceController.WarningConfirmationListener {
BatteryTipPreferenceController.BatteryTipListener {
public static final String TAG = "AdvancedPowerUsageDetail";
public static final String EXTRA_UID = "extra_uid";
@@ -373,8 +375,8 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements
}
@Override
public void onLimitBackgroundActivity() {
mBackgroundActivityPreferenceController.setRestricted(
public void onBatteryTipHandled(BatteryTip batteryTip) {
mBackgroundActivityPreferenceController.updateSummary(
findPreference(mBackgroundActivityPreferenceController.getPreferenceKey()));
}
}

View File

@@ -14,27 +14,22 @@
package com.android.settings.fuelgauge;
import android.app.AlertDialog;
import android.app.AppOpsManager;
import android.app.Dialog;
import android.app.Fragment;
import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.content.DialogInterface;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.os.UserManager;
import android.support.annotation.VisibleForTesting;
import android.support.v14.preference.SwitchPreference;
import android.support.v7.preference.Preference;
import android.util.Log;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
import com.android.settings.fuelgauge.batterytip.AppInfo;
import com.android.settings.fuelgauge.batterytip.BatteryTipDialogFragment;
import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
import com.android.settings.fuelgauge.batterytip.tips.RestrictAppTip;
import com.android.settings.fuelgauge.batterytip.tips.UnrestrictAppTip;
import com.android.settings.wrapper.DevicePolicyManagerWrapper;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.fuelgauge.PowerWhitelistBackend;
@@ -99,15 +94,6 @@ public class BackgroundActivityPreferenceController extends AbstractPreferenceCo
return mTargetPackage != null;
}
/**
* Called from the warning dialog, if the user decides to go ahead and disable background
* activity for this package
*/
public void setRestricted(Preference preference) {
mBatteryUtils.setForceAppStandby(mUid, mTargetPackage, AppOpsManager.MODE_IGNORED);
updateSummary(preference);
}
@Override
public String getPreferenceKey() {
return KEY_BACKGROUND_ACTIVITY;
@@ -119,20 +105,13 @@ public class BackgroundActivityPreferenceController extends AbstractPreferenceCo
final int mode = mAppOpsManager
.checkOpNoThrow(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, mUid, mTargetPackage);
final boolean restricted = mode == AppOpsManager.MODE_IGNORED;
if (!restricted) {
showDialog();
return false;
}
mBatteryUtils.setForceAppStandby(mUid, mTargetPackage, AppOpsManager.MODE_ALLOWED);
updateSummary(preference);
return true;
showDialog(restricted);
}
return false;
}
@VisibleForTesting
void updateSummary(Preference preference) {
public void updateSummary(Preference preference) {
if (mPowerWhitelistBackend.isWhitelisted(mTargetPackage)) {
preference.setSummary(R.string.background_activity_summary_whitelisted);
return;
@@ -150,42 +129,16 @@ public class BackgroundActivityPreferenceController extends AbstractPreferenceCo
}
@VisibleForTesting
void showDialog() {
final WarningDialogFragment dialogFragment = new WarningDialogFragment();
void showDialog(boolean restricted) {
final AppInfo appInfo = new AppInfo.Builder()
.setPackageName(mTargetPackage)
.build();
BatteryTip tip = restricted
? new UnrestrictAppTip(BatteryTip.StateType.NEW, appInfo)
: new RestrictAppTip(BatteryTip.StateType.NEW, appInfo);
final BatteryTipDialogFragment dialogFragment = BatteryTipDialogFragment.newInstance(tip);
dialogFragment.setTargetFragment(mFragment, 0 /* requestCode */);
dialogFragment.show(mFragment.getFragmentManager(), TAG);
}
interface WarningConfirmationListener {
void onLimitBackgroundActivity();
}
/**
* Warning dialog to show to the user as turning off background activity can lead to
* apps misbehaving as their background task scheduling guarantees will no longer be honored.
*/
public static class WarningDialogFragment extends InstrumentedDialogFragment {
@Override
public int getMetricsCategory() {
// TODO (b/65494831): add metric id
return 0;
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final WarningConfirmationListener listener =
(WarningConfirmationListener) getTargetFragment();
return new AlertDialog.Builder(getContext())
.setTitle(R.string.background_activity_warning_dialog_title)
.setMessage(R.string.background_activity_warning_dialog_text)
.setPositiveButton(R.string.dlg_ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
listener.onLimitBackgroundActivity();
}
})
.setNegativeButton(R.string.dlg_cancel, null)
.create();
}
}
}

View File

@@ -34,6 +34,10 @@ import com.android.settings.fuelgauge.batterytip.BatteryTipPreferenceController.
import com.android.settings.fuelgauge.batterytip.actions.BatteryTipAction;
import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
import com.android.settings.fuelgauge.batterytip.tips.HighUsageTip;
import com.android.settings.fuelgauge.batterytip.tips.RestrictAppTip;
import com.android.settings.fuelgauge.batterytip.tips.UnrestrictAppTip;
import java.util.List;
/**
* Dialog Fragment to show action dialog for each anomaly
@@ -84,6 +88,39 @@ public class BatteryTipDialogFragment extends InstrumentedDialogFragment impleme
.setView(view)
.setPositiveButton(android.R.string.ok, null)
.create();
case BatteryTip.TipType.APP_RESTRICTION:
final RestrictAppTip restrictAppTip = (RestrictAppTip) mBatteryTip;
final List<AppInfo> restrictedAppList = restrictAppTip.getRestrictAppList();
final int num = restrictedAppList.size();
final AlertDialog.Builder builder = new AlertDialog.Builder(context)
.setTitle(context.getResources().getQuantityString(
R.plurals.battery_tip_restrict_app_dialog_title, num, num))
.setMessage(getString(R.string.battery_tip_restrict_app_dialog_message))
.setPositiveButton(R.string.battery_tip_restrict_app_dialog_ok, this)
.setNegativeButton(android.R.string.cancel, null);
// TODO(b/72385333): consider building dialog with 5+ apps when strings are done
if (num > 1) {
final RecyclerView restrictionView = (RecyclerView) LayoutInflater.from(
context).inflate(R.layout.recycler_view, null);
restrictionView.setLayoutManager(new LinearLayoutManager(context));
restrictionView.setAdapter(new HighUsageAdapter(context, restrictedAppList));
builder.setView(restrictionView);
}
return builder.create();
case BatteryTip.TipType.REMOVE_APP_RESTRICTION:
final UnrestrictAppTip unrestrictAppTip = (UnrestrictAppTip) mBatteryTip;
final CharSequence name = Utils.getApplicationLabel(context,
unrestrictAppTip.getPackageName());
return new AlertDialog.Builder(context)
.setTitle(getString(R.string.battery_tip_unrestrict_app_dialog_title, name))
.setMessage(R.string.battery_tip_unrestrict_app_dialog_message)
.setPositiveButton(R.string.battery_tip_unrestrict_app_dialog_ok, this)
.setNegativeButton(R.string.battery_tip_unrestrict_app_dialog_cancel, null)
.create();
default:
throw new IllegalArgumentException("unknown type " + mBatteryTip.getType());
}

View File

@@ -26,6 +26,7 @@ import com.android.settings.fuelgauge.batterytip.detectors.EarlyWarningDetector;
import com.android.settings.fuelgauge.batterytip.detectors.HighUsageDetector;
import com.android.settings.fuelgauge.batterytip.detectors.LowBatteryDetector;
import com.android.settings.fuelgauge.batterytip.detectors.SmartBatteryDetector;
import com.android.settings.fuelgauge.batterytip.detectors.RestrictAppDetector;
import com.android.settings.fuelgauge.batterytip.detectors.SummaryDetector;
import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
import com.android.settings.fuelgauge.batterytip.tips.LowBatteryTip;
@@ -70,6 +71,7 @@ public class BatteryTipLoader extends AsyncLoader<List<BatteryTip>> {
tips.add(new SmartBatteryDetector(policy, context.getContentResolver()).detect());
tips.add(new EarlyWarningDetector(policy, context).detect());
tips.add(new SummaryDetector(policy).detect());
tips.add(new RestrictAppDetector(policy).detect());
Collections.sort(tips);
return tips;

View File

@@ -17,12 +17,17 @@
package com.android.settings.fuelgauge.batterytip;
import android.app.Fragment;
import android.content.Context;
import com.android.settings.SettingsActivity;
import com.android.settings.fuelgauge.batterytip.actions.BatterySaverAction;
import com.android.settings.fuelgauge.batterytip.actions.BatteryTipAction;
import com.android.settings.fuelgauge.batterytip.actions.RestrictAppAction;
import com.android.settings.fuelgauge.batterytip.actions.SmartBatteryAction;
import com.android.settings.fuelgauge.batterytip.actions.UnrestrictAppAction;
import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
import com.android.settings.fuelgauge.batterytip.tips.RestrictAppTip;
import com.android.settings.fuelgauge.batterytip.tips.UnrestrictAppTip;
/**
* Utility class for {@link BatteryTip}
@@ -42,7 +47,11 @@ public class BatteryTipUtils {
case BatteryTip.TipType.SMART_BATTERY_MANAGER:
return new SmartBatteryAction(settingsActivity, fragment);
case BatteryTip.TipType.BATTERY_SAVER:
return new BatterySaverAction(settingsActivity.getApplicationContext());
return new BatterySaverAction(settingsActivity);
case BatteryTip.TipType.APP_RESTRICTION:
return new RestrictAppAction(settingsActivity, (RestrictAppTip) batteryTip);
case BatteryTip.TipType.REMOVE_APP_RESTRICTION:
return new UnrestrictAppAction(settingsActivity, (UnrestrictAppTip) batteryTip);
default:
return null;
}

View File

@@ -77,7 +77,9 @@ public class HighUsageAdapter extends RecyclerView.Adapter<HighUsageAdapter.View
Utils.getBadgedIcon(mIconDrawableFactory, mPackageManager, app.packageName,
UserHandle.myUserId()));
holder.appName.setText(Utils.getApplicationLabel(mContext, app.packageName));
holder.appTime.setText(Utils.formatElapsedTime(mContext, app.screenOnTimeMs, false));
if (app.screenOnTimeMs != 0) {
holder.appTime.setText(Utils.formatElapsedTime(mContext, app.screenOnTimeMs, false));
}
}
@Override

View File

@@ -0,0 +1,57 @@
/*
* 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.fuelgauge.batterytip.actions;
import android.app.AppOpsManager;
import android.content.Context;
import android.support.annotation.VisibleForTesting;
import com.android.settings.fuelgauge.BatteryUtils;
import com.android.settings.fuelgauge.batterytip.AppInfo;
import com.android.settings.fuelgauge.batterytip.tips.RestrictAppTip;
import java.util.List;
/**
* Action to restrict the apps, then app is not allowed to run in the background.
*/
public class RestrictAppAction extends BatteryTipAction {
private RestrictAppTip mRestrictAppTip;
@VisibleForTesting
BatteryUtils mBatteryUtils;
public RestrictAppAction(Context context, RestrictAppTip tip) {
super(context);
mRestrictAppTip = tip;
mBatteryUtils = BatteryUtils.getInstance(context);
}
/**
* Handle the action when user clicks positive button
*/
@Override
public void handlePositiveAction() {
final List<AppInfo> appInfos = mRestrictAppTip.getRestrictAppList();
for (int i = 0, size = appInfos.size(); i < size; i++) {
final String packageName = appInfos.get(i).packageName;
// Force app standby, then app can't run in the background
mBatteryUtils.setForceAppStandby(mBatteryUtils.getPackageUid(packageName), packageName,
AppOpsManager.MODE_IGNORED);
}
}
}

View File

@@ -0,0 +1,48 @@
/*
* 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.fuelgauge.batterytip.actions;
import android.app.AppOpsManager;
import android.content.Context;
import com.android.settings.fuelgauge.BatteryUtils;
import com.android.settings.fuelgauge.batterytip.tips.UnrestrictAppTip;
/**
* Action to clear the restriction to the app
*/
public class UnrestrictAppAction extends BatteryTipAction {
private UnrestrictAppTip mUnRestrictAppTip;
private BatteryUtils mBatteryUtils;
public UnrestrictAppAction(Context context, UnrestrictAppTip tip) {
super(context);
mUnRestrictAppTip = tip;
mBatteryUtils = BatteryUtils.getInstance(context);
}
/**
* Handle the action when user clicks positive button
*/
@Override
public void handlePositiveAction() {
final String packageName = mUnRestrictAppTip.getPackageName();
// Clear force app standby, then app can run in the background
mBatteryUtils.setForceAppStandby(mBatteryUtils.getPackageUid(packageName), packageName,
AppOpsManager.MODE_ALLOWED);
}
}

View File

@@ -0,0 +1,46 @@
/*
* 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.fuelgauge.batterytip.detectors;
import com.android.settings.fuelgauge.batterytip.AppInfo;
import com.android.settings.fuelgauge.batterytip.BatteryTipPolicy;
import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
import com.android.settings.fuelgauge.batterytip.tips.RestrictAppTip;
import java.util.ArrayList;
import java.util.List;
/**
* Detector whether to show summary tip. This detector should be executed as the last
* {@link BatteryTipDetector} since it need the most up-to-date {@code visibleTips}
*/
public class RestrictAppDetector implements BatteryTipDetector {
private BatteryTipPolicy mPolicy;
public RestrictAppDetector(BatteryTipPolicy policy) {
mPolicy = policy;
}
@Override
public BatteryTip detect() {
// TODO(b/70570352): Detect restrict apps here, get data from database
final List<AppInfo> highUsageApps = new ArrayList<>();
return new RestrictAppTip(
highUsageApps.isEmpty() ? BatteryTip.StateType.INVISIBLE : BatteryTip.StateType.NEW,
highUsageApps);
}
}

View File

@@ -50,7 +50,8 @@ public abstract class BatteryTip implements Comparable<BatteryTip>, Parcelable {
TipType.SMART_BATTERY_MANAGER,
TipType.APP_RESTRICTION,
TipType.REDUCED_BATTERY,
TipType.LOW_BATTERY})
TipType.LOW_BATTERY,
TipType.REMOVE_APP_RESTRICTION})
public @interface TipType {
int SMART_BATTERY_MANAGER = 0;
int APP_RESTRICTION = 1;
@@ -59,6 +60,7 @@ public abstract class BatteryTip implements Comparable<BatteryTip>, Parcelable {
int REDUCED_BATTERY = 4;
int LOW_BATTERY = 5;
int SUMMARY = 6;
int REMOVE_APP_RESTRICTION = 7;
}
private static final String KEY_PREFIX = "key_battery_tip";

View File

@@ -0,0 +1,106 @@
/*
* 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.fuelgauge.batterytip.tips;
import android.content.Context;
import android.content.res.Resources;
import android.os.Parcel;
import com.android.internal.annotations.VisibleForTesting;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.fuelgauge.batterytip.AppInfo;
import java.util.ArrayList;
import java.util.List;
/**
* Tip to suggest user to restrict some bad apps
*/
public class RestrictAppTip extends BatteryTip {
private List<AppInfo> mRestrictAppList;
public RestrictAppTip(@StateType int state, List<AppInfo> restrictApps) {
super(TipType.APP_RESTRICTION, state, true /* showDialog */);
mRestrictAppList = restrictApps;
}
public RestrictAppTip(@StateType int state, AppInfo appInfo) {
super(TipType.APP_RESTRICTION, state, true /* showDialog */);
mRestrictAppList = new ArrayList<>();
mRestrictAppList.add(appInfo);
}
@VisibleForTesting
RestrictAppTip(Parcel in) {
super(in);
mRestrictAppList = in.createTypedArrayList(AppInfo.CREATOR);
}
@Override
public CharSequence getTitle(Context context) {
final int num = mRestrictAppList.size();
return context.getResources().getQuantityString(
mState == StateType.HANDLED
? R.plurals.battery_tip_restrict_handled_title
: R.plurals.battery_tip_restrict_title,
num, num);
}
@Override
public CharSequence getSummary(Context context) {
final int num = mRestrictAppList.size();
final CharSequence appLabel = num > 0 ? Utils.getApplicationLabel(context,
mRestrictAppList.get(0).packageName) : "";
return mState == StateType.HANDLED
? context.getString(R.string.battery_tip_restrict_handled_summary)
: context.getResources().getQuantityString(R.plurals.battery_tip_restrict_summary,
num, appLabel, num);
}
@Override
public int getIconId() {
return mState == StateType.HANDLED
? R.drawable.ic_perm_device_information_green_24dp
: R.drawable.ic_battery_alert_24dp;
}
@Override
public void updateState(BatteryTip tip) {
mState = tip.mState;
}
public List<AppInfo> getRestrictAppList() {
return mRestrictAppList;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeTypedList(mRestrictAppList);
}
public static final Creator CREATOR = new Creator() {
public BatteryTip createFromParcel(Parcel in) {
return new RestrictAppTip(in);
}
public BatteryTip[] newArray(int size) {
return new RestrictAppTip[size];
}
};
}

View File

@@ -0,0 +1,84 @@
/*
* 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.fuelgauge.batterytip.tips;
import android.content.Context;
import android.os.Parcel;
import com.android.internal.annotations.VisibleForTesting;
import com.android.settings.fuelgauge.batterytip.AppInfo;
/**
* Tip to suggest user to remove app restriction. This is the empty tip and it is only used in
* {@link com.android.settings.fuelgauge.AdvancedPowerUsageDetail} to create dialog.
*/
public class UnrestrictAppTip extends BatteryTip {
private AppInfo mAppInfo;
public UnrestrictAppTip(@StateType int state, AppInfo appInfo) {
super(TipType.REMOVE_APP_RESTRICTION, state, true /* showDialog */);
mAppInfo = appInfo;
}
@VisibleForTesting
UnrestrictAppTip(Parcel in) {
super(in);
mAppInfo = in.readParcelable(getClass().getClassLoader());
}
@Override
public CharSequence getTitle(Context context) {
// Don't need title since this is an empty tip
return null;
}
@Override
public CharSequence getSummary(Context context) {
// Don't need summary since this is an empty tip
return null;
}
@Override
public int getIconId() {
return 0;
}
public String getPackageName() {
return mAppInfo.packageName;
}
@Override
public void updateState(BatteryTip tip) {
mState = tip.mState;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeParcelable(mAppInfo, flags);
}
public static final Creator CREATOR = new Creator() {
public BatteryTip createFromParcel(Parcel in) {
return new UnrestrictAppTip(in);
}
public BatteryTip[] newArray(int size) {
return new UnrestrictAppTip[size];
}
};
}

View File

@@ -27,7 +27,7 @@ import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.core.InstrumentedPreferenceFragment;
import com.android.settings.core.InstrumentedFragment;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.inputmethod.UserDictionaryAddWordContents.LocaleRenderer;
@@ -41,7 +41,7 @@ import java.util.Locale;
* As opposed to the UserDictionaryActivity, this is only invoked within Settings
* from the UserDictionarySettings.
*/
public class UserDictionaryAddWordFragment extends InstrumentedPreferenceFragment
public class UserDictionaryAddWordFragment extends InstrumentedFragment
implements AdapterView.OnItemSelectedListener,
com.android.internal.app.LocalePicker.LocaleSelectionListener {
@@ -55,7 +55,6 @@ public class UserDictionaryAddWordFragment extends InstrumentedPreferenceFragmen
public void onActivityCreated(final Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setHasOptionsMenu(true);
getActivity().getActionBar().setTitle(R.string.user_dict_settings_title);
// Keep the instance so that we remember mContents when configuration changes (eg rotation)
setRetainInstance(true);
}

View File

@@ -0,0 +1,223 @@
/*
* 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.location;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.location.LocationManager;
import android.support.annotation.VisibleForTesting;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceCategory;
import android.util.Log;
import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnPause;
import com.android.settingslib.widget.FooterPreference;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
/**
* Preference controller for location footer preference category
*/
public class LocationFooterPreferenceController extends LocationBasePreferenceController
implements LifecycleObserver, OnPause {
private static final String TAG = "LocationFooter";
private static final String KEY_LOCATION_FOOTER = "location_footer";
private static final Intent INJECT_INTENT =
new Intent(LocationManager.SETTINGS_FOOTER_DISPLAYED_ACTION);
private final Context mContext;
private final PackageManager mPackageManager;
private Collection<ComponentName> mFooterInjectors;
public LocationFooterPreferenceController(Context context, Lifecycle lifecycle) {
super(context, lifecycle);
mContext = context;
mPackageManager = mContext.getPackageManager();
mFooterInjectors = new ArrayList<>();
if (lifecycle != null) {
lifecycle.addObserver(this);
}
}
@Override
public String getPreferenceKey() {
return KEY_LOCATION_FOOTER;
}
/**
* Insert footer preferences. Send a {@link LocationManager#SETTINGS_FOOTER_DISPLAYED_ACTION}
* broadcast to receivers who have injected a footer
*/
@Override
public void updateState(Preference preference) {
PreferenceCategory category = (PreferenceCategory) preference;
category.removeAll();
mFooterInjectors.clear();
Collection<FooterData> footerData = getFooterData();
for (FooterData data : footerData) {
// Generate a footer preference with the given text
FooterPreference footerPreference = new FooterPreference(preference.getContext());
String footerString;
try {
footerString =
mPackageManager
.getResourcesForApplication(data.applicationInfo)
.getString(data.footerStringRes);
} catch (NameNotFoundException exception) {
if (Log.isLoggable(TAG, Log.WARN)) {
Log.w(
TAG,
"Resources not found for application "
+ data.applicationInfo.packageName);
}
continue;
}
footerPreference.setTitle(footerString);
// Inject the footer
category.addPreference(footerPreference);
// Send broadcast to the injector announcing a footer has been injected
sendBroadcastFooterDisplayed(data.componentName);
mFooterInjectors.add(data.componentName);
}
}
/**
* Do nothing on location mode changes.
*/
@Override
public void onLocationModeChanged(int mode, boolean restricted) {}
/**
* Location footer preference group should be displayed if there is at least one footer to
* inject.
*/
@Override
public boolean isAvailable() {
return !getFooterData().isEmpty();
}
/**
* Send a {@link LocationManager#SETTINGS_FOOTER_REMOVED_ACTION} broadcast to footer injectors
* when LocationFragment is on pause
*/
@Override
public void onPause() {
// Send broadcast to the footer injectors. Notify them the footer is not visible.
for (ComponentName componentName : mFooterInjectors) {
final Intent intent = new Intent(LocationManager.SETTINGS_FOOTER_REMOVED_ACTION);
intent.setComponent(componentName);
mContext.sendBroadcast(intent);
}
}
/**
* Send a {@link LocationManager#SETTINGS_FOOTER_DISPLAYED_ACTION} broadcast to a footer
* injector.
*/
@VisibleForTesting
void sendBroadcastFooterDisplayed(ComponentName componentName) {
Intent intent = new Intent(LocationManager.SETTINGS_FOOTER_DISPLAYED_ACTION);
intent.setComponent(componentName);
mContext.sendBroadcast(intent);
}
/**
* Return a list of strings with text provided by ACTION_INJECT_FOOTER broadcast receivers.
*/
private Collection<FooterData> getFooterData() {
// Fetch footer text from system apps
final List<ResolveInfo> resolveInfos =
mPackageManager.queryBroadcastReceivers(
INJECT_INTENT, PackageManager.GET_META_DATA);
if (resolveInfos == null) {
if (Log.isLoggable(TAG, Log.ERROR)) {
Log.e(TAG, "Unable to resolve intent " + INJECT_INTENT);
return Collections.emptyList();
}
} else if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "Found broadcast receivers: " + resolveInfos);
}
final Collection<FooterData> footerDataList = new ArrayList<>(resolveInfos.size());
for (ResolveInfo resolveInfo : resolveInfos) {
final ActivityInfo activityInfo = resolveInfo.activityInfo;
final ApplicationInfo appInfo = activityInfo.applicationInfo;
// If a non-system app tries to inject footer, ignore it
if ((appInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
if (Log.isLoggable(TAG, Log.WARN)) {
Log.w(TAG, "Ignoring attempt to inject footer from app not in system image: "
+ resolveInfo);
continue;
}
}
// Get the footer text resource id from broadcast receiver's metadata
if (activityInfo.metaData == null) {
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "No METADATA in broadcast receiver " + activityInfo.name);
continue;
}
}
final int footerTextRes =
activityInfo.metaData.getInt(LocationManager.METADATA_SETTINGS_FOOTER_STRING);
if (footerTextRes == 0) {
if (Log.isLoggable(TAG, Log.WARN)) {
Log.w(
TAG,
"No mapping of integer exists for "
+ LocationManager.METADATA_SETTINGS_FOOTER_STRING);
}
continue;
}
footerDataList.add(
new FooterData(
footerTextRes,
appInfo,
new ComponentName(activityInfo.packageName, activityInfo.name)));
}
return footerDataList;
}
/**
* Contains information related to a footer.
*/
private static class FooterData {
// The string resource of the footer
final int footerStringRes;
// Application info of receiver injecting this footer
final ApplicationInfo applicationInfo;
// The component that injected the footer. It must be a receiver of broadcast
// LocationManager.SETTINGS_FOOTER_DISPLAYED_ACTION
final ComponentName componentName;
FooterData(int footerRes, ApplicationInfo appInfo, ComponentName componentName) {
this.footerStringRes = footerRes;
this.applicationInfo = appInfo;
this.componentName = componentName;
}
}
}

View File

@@ -131,9 +131,10 @@ public class LocationSettings extends DashboardFragment {
controllers.add(new LocationForWorkPreferenceController(context, lifecycle));
controllers.add(
new RecentLocationRequestPreferenceController(context, fragment, lifecycle));
controllers.add(new LocationScanningPreferenceController(context));
controllers.add(
new LocationServicePreferenceController(context, fragment, lifecycle));
controllers.add(new LocationScanningPreferenceController(context));
controllers.add(new LocationFooterPreferenceController(context, lifecycle));
return controllers;
}

View File

@@ -50,7 +50,6 @@ public class NetworkScorerPicker extends InstrumentedPreferenceFragment implemen
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
super.onCreatePreferences(savedInstanceState, rootKey);
addPreferencesFromResource(R.xml.network_scorer_picker_prefs);
updateCandidates();
}
@@ -69,6 +68,11 @@ public class NetworkScorerPicker extends InstrumentedPreferenceFragment implemen
return view;
}
@Override
protected int getPreferenceScreenResId() {
return R.xml.network_scorer_picker_prefs;
}
@VisibleForTesting
public void updateCandidates() {
final PreferenceScreen screen = getPreferenceScreen();

View File

@@ -29,7 +29,7 @@ import android.widget.Switch;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settingslib.HelpUtils;
import com.android.settings.core.InstrumentedPreferenceFragment;
import com.android.settings.core.InstrumentedFragment;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.ShowAdminSupportDetailsDialog;
@@ -38,7 +38,7 @@ import com.android.settingslib.RestrictedLockUtils;
import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
public class AndroidBeam extends InstrumentedPreferenceFragment
public class AndroidBeam extends InstrumentedFragment
implements SwitchBar.OnSwitchChangeListener {
private View mView;
private NfcAdapter mNfcAdapter;

View File

@@ -64,7 +64,7 @@ import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.SetupWizardUtils;
import com.android.settings.Utils;
import com.android.settings.core.InstrumentedPreferenceFragment;
import com.android.settings.core.InstrumentedFragment;
import com.android.settings.notification.RedactionInterstitial;
import com.android.settings.widget.ImeAwareEditText;
import com.android.setupwizardlib.GlifLayout;
@@ -168,7 +168,7 @@ public class ChooseLockPassword extends SettingsActivity {
layout.setFitsSystemWindows(false);
}
public static class ChooseLockPasswordFragment extends InstrumentedPreferenceFragment
public static class ChooseLockPasswordFragment extends InstrumentedFragment
implements OnClickListener, OnEditorActionListener, TextWatcher,
SaveAndFinishWorker.Listener {
private static final String KEY_FIRST_PIN = "first_pin";

View File

@@ -43,7 +43,7 @@ import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.SetupWizardUtils;
import com.android.settings.Utils;
import com.android.settings.core.InstrumentedPreferenceFragment;
import com.android.settings.core.InstrumentedFragment;
import com.android.settings.notification.RedactionInterstitial;
import com.android.setupwizardlib.GlifLayout;
@@ -153,7 +153,7 @@ public class ChooseLockPattern extends SettingsActivity {
return super.onKeyDown(keyCode, event);
}
public static class ChooseLockPatternFragment extends InstrumentedPreferenceFragment
public static class ChooseLockPatternFragment extends InstrumentedFragment
implements View.OnClickListener, SaveAndFinishWorker.Listener {
public static final int CONFIRM_EXISTING_REQUEST = 55;

View File

@@ -52,13 +52,13 @@ import android.widget.TextView;
import com.android.internal.widget.LockPatternUtils;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.core.InstrumentedPreferenceFragment;
import com.android.settings.core.InstrumentedFragment;
import com.android.settings.fingerprint.FingerprintUiHelper;
/**
* Base fragment to be shared for PIN/Pattern/Password confirmation fragments.
*/
public abstract class ConfirmDeviceCredentialBaseFragment extends InstrumentedPreferenceFragment
public abstract class ConfirmDeviceCredentialBaseFragment extends InstrumentedFragment
implements FingerprintUiHelper.Callback {
public static final String PACKAGE = "com.android.settings";

View File

@@ -113,11 +113,6 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity {
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {

View File

@@ -104,11 +104,6 @@ public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity {
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {

View File

@@ -157,6 +157,7 @@ public class CryptKeeperSettings extends InstrumentedPreferenceFragment {
}
}
}
activity.setTitle(R.string.crypt_keeper_encrypt_title);
}
/**

View File

@@ -39,13 +39,12 @@ import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnStart;
import com.android.settingslib.core.lifecycle.events.OnStop;
import java.util.List;
public class WifiTetherPreferenceController extends AbstractPreferenceController
implements PreferenceControllerMixin, LifecycleObserver, OnStart, OnStop {
public static final IntentFilter WIFI_TETHER_INTENT_FILTER;
private static final String WIFI_TETHER_SETTINGS = "wifi_tether";
private static final IntentFilter AIRPLANE_INTENT_FILTER = new IntentFilter(
Intent.ACTION_AIRPLANE_MODE_CHANGED);
private final ConnectivityManager mConnectivityManager;
private final String[] mWifiRegexs;
@@ -58,12 +57,6 @@ public class WifiTetherPreferenceController extends AbstractPreferenceController
@VisibleForTesting
WifiTetherSoftApManager mWifiTetherSoftApManager;
static {
WIFI_TETHER_INTENT_FILTER = new IntentFilter(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
WIFI_TETHER_INTENT_FILTER.addAction(ConnectivityManager.ACTION_TETHER_STATE_CHANGED);
WIFI_TETHER_INTENT_FILTER.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
}
public WifiTetherPreferenceController(Context context, Lifecycle lifecycle) {
this(context, lifecycle, true /* initSoftApManager */);
}
@@ -113,7 +106,7 @@ public class WifiTetherPreferenceController extends AbstractPreferenceController
@Override
public void onStart() {
if (mPreference != null) {
mContext.registerReceiver(mReceiver, WIFI_TETHER_INTENT_FILTER);
mContext.registerReceiver(mReceiver, AIRPLANE_INTENT_FILTER);
clearSummaryForAirplaneMode();
if (mWifiTetherSoftApManager != null) {
mWifiTetherSoftApManager.registerSoftApCallback();
@@ -140,6 +133,7 @@ public class WifiTetherPreferenceController extends AbstractPreferenceController
@Override
public void onStateChanged(int state, int failureReason) {
mSoftApState = state;
handleWifiApStateChanged(state, failureReason);
}
@Override
@@ -162,34 +156,21 @@ public class WifiTetherPreferenceController extends AbstractPreferenceController
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (WifiManager.WIFI_AP_STATE_CHANGED_ACTION.equals(action)) {
int state = intent.getIntExtra(
WifiManager.EXTRA_WIFI_AP_STATE, WifiManager.WIFI_AP_STATE_FAILED);
int reason = intent.getIntExtra(WifiManager.EXTRA_WIFI_AP_FAILURE_REASON,
WifiManager.SAP_START_FAILURE_GENERAL);
handleWifiApStateChanged(state, reason);
} else if (ConnectivityManager.ACTION_TETHER_STATE_CHANGED.equals(action)) {
List<String> active = intent.getStringArrayListExtra(
ConnectivityManager.EXTRA_ACTIVE_TETHER);
List<String> errored = intent.getStringArrayListExtra(
ConnectivityManager.EXTRA_ERRORED_TETHER);
updateTetherState(active.toArray(), errored.toArray());
} else if (Intent.ACTION_AIRPLANE_MODE_CHANGED.equals(action)) {
if (Intent.ACTION_AIRPLANE_MODE_CHANGED.equals(action)) {
clearSummaryForAirplaneMode();
}
}
};
private void handleWifiApStateChanged(int state, int reason) {
@VisibleForTesting
void handleWifiApStateChanged(int state, int reason) {
switch (state) {
case WifiManager.WIFI_AP_STATE_ENABLING:
mPreference.setSummary(R.string.wifi_tether_starting);
break;
case WifiManager.WIFI_AP_STATE_ENABLED:
/**
* Summary on enable is handled by tether
* broadcast notice
*/
WifiConfiguration wifiConfig = mWifiManager.getWifiApConfiguration();
updateConfigSummary(wifiConfig);
break;
case WifiManager.WIFI_AP_STATE_DISABLING:
mPreference.setSummary(R.string.wifi_tether_stopping);
@@ -208,32 +189,6 @@ public class WifiTetherPreferenceController extends AbstractPreferenceController
}
}
private void updateTetherState(Object[] tethered, Object[] errored) {
boolean wifiTethered = matchRegex(tethered);
boolean wifiErrored = matchRegex(errored);
if (wifiTethered) {
WifiConfiguration wifiConfig = mWifiManager.getWifiApConfiguration();
updateConfigSummary(wifiConfig);
} else if (wifiErrored) {
mPreference.setSummary(R.string.wifi_error);
} else {
mPreference.setSummary(R.string.wifi_hotspot_off_subtext);
}
}
private boolean matchRegex(Object[] tethers) {
for (Object o : tethers) {
String s = (String) o;
for (String regex : mWifiRegexs) {
if (s.matches(regex)) {
return true;
}
}
}
return false;
}
private void updateConfigSummary(WifiConfiguration wifiConfig) {
final String s = mContext.getString(
com.android.internal.R.string.wifi_tether_configure_ssid_default);

View File

@@ -21,6 +21,7 @@ import static android.net.ConnectivityManager.TETHERING_WIFI;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.wifi.WifiManager;
import android.os.Handler;
@@ -36,12 +37,19 @@ import com.android.settingslib.core.lifecycle.events.OnStop;
public class WifiTetherSwitchBarController implements SwitchWidgetController.OnSwitchChangeListener,
LifecycleObserver, OnStart, OnStop {
private static final IntentFilter WIFI_INTENT_FILTER;
private final Context mContext;
private final SwitchWidgetController mSwitchBar;
private final ConnectivityManager mConnectivityManager;
private final DataSaverBackend mDataSaverBackend;
private final WifiManager mWifiManager;
static {
WIFI_INTENT_FILTER = new IntentFilter(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
WIFI_INTENT_FILTER.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
}
WifiTetherSwitchBarController(Context context, SwitchWidgetController switchBar) {
mContext = context;
mSwitchBar = switchBar;
@@ -56,8 +64,7 @@ public class WifiTetherSwitchBarController implements SwitchWidgetController.OnS
@Override
public void onStart() {
mSwitchBar.startListening();
mContext.registerReceiver(mReceiver,
WifiTetherPreferenceController.WIFI_TETHER_INTENT_FILTER);
mContext.registerReceiver(mReceiver, WIFI_INTENT_FILTER);
}
@Override

View File

@@ -104,10 +104,5 @@ public class DefaultAutofillPreferenceControllerTest {
final DefaultAppInfo info = mController.getDefaultAppInfo();
assertThat(info).isNotNull();
mController.getSettingIntent(info);
verify(mPackageManager.getPackageManager()).queryIntentServices(
DefaultAutofillPicker.AUTOFILL_PROBE, PackageManager.GET_META_DATA);
}
}

View File

@@ -67,6 +67,8 @@ public class DashboardSummaryTest {
private ConditionManager mConditionManager;
@Mock
private SummaryLoader mSummaryLoader;
@Mock
private SuggestionControllerMixin mSuggestionControllerMixin;
private Context mContext;
private DashboardSummary mSummary;
@@ -111,12 +113,31 @@ public class DashboardSummaryTest {
@Test
public void updateCategory_shouldGetCategoryFromFeatureProvider() {
ReflectionHelpers.setField(mSummary, "mSuggestionControllerMixin",
mSuggestionControllerMixin);
when(mSuggestionControllerMixin.isSuggestionLoaded()).thenReturn(true);
doReturn(mock(Activity.class)).when(mSummary).getActivity();
mSummary.onAttach(mContext);
mSummary.updateCategory();
verify(mSummaryLoader).updateSummaryToCache(nullable(DashboardCategory.class));
verify(mDashboardFeatureProvider).getTilesForCategory(CategoryKey.CATEGORY_HOMEPAGE);
verify(mAdapter).setCategory(any());
}
@Test
public void updateCategory_shouldGetCategoryFromFeatureProvider_evenIfSuggestionDisabled() {
when(mFeatureFactory.suggestionsFeatureProvider.isSuggestionEnabled(any(Context.class)))
.thenReturn(false);
doReturn(mock(Activity.class)).when(mSummary).getActivity();
mSummary.onAttach(mContext);
mSummary.updateCategory();
verify(mSummaryLoader).updateSummaryToCache(nullable(DashboardCategory.class));
verify(mDashboardFeatureProvider).getTilesForCategory(CategoryKey.CATEGORY_HOMEPAGE);
verify(mAdapter).setCategory(any());
}
@Test

View File

@@ -142,18 +142,17 @@ public class BackgroundActivityPreferenceControllerTest {
mController.handlePreferenceTreeClick(mPreference);
verify(mController).showDialog();
verify(mController).showDialog(false /* restrict */);
}
@Test
public void testHandlePreferenceTreeClick_unRestrictApp_setModeAllowed() {
public void testHandlePreferenceTreeClick_unRestrictApp_showDialog() {
doReturn(AppOpsManager.MODE_IGNORED).when(mAppOpsManager).checkOpNoThrow(anyInt(),
anyInt(), anyString());
mController.handlePreferenceTreeClick(mPreference);
verify(mBatteryUtils).setForceAppStandby(UID_LOW_SDK, LOW_SDK_PACKAGE,
AppOpsManager.MODE_ALLOWED);
verify(mController).showDialog(true /* restrict */);
}
@Test
@@ -211,17 +210,4 @@ public class BackgroundActivityPreferenceControllerTest {
public void testIsAvailable_ReturnTrue() {
assertThat(mController.isAvailable()).isTrue();
}
@Test
public void testWarningDialog() {
BackgroundActivityPreferenceController.WarningDialogFragment dialogFragment =
new BackgroundActivityPreferenceController.WarningDialogFragment();
dialogFragment.setTargetFragment(mFragment, 0);
FragmentTestUtil.startFragment(dialogFragment);
final AlertDialog dialog = (AlertDialog) ShadowDialog.getLatestDialog();
ShadowAlertDialog shadowDialog = shadowOf(dialog);
final Button okButton = dialog.getButton(DialogInterface.BUTTON_POSITIVE);
shadowDialog.clickOn(okButton.getId());
verify(mFragment).onLimitBackgroundActivity();
}
}

View File

@@ -32,6 +32,7 @@ import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -523,4 +524,27 @@ public class BatteryUtilsTest {
public void testIsLegacyApp_SdkLargerOrEqualThanO_ReturnFalse() {
assertThat(mBatteryUtils.isLegacyApp(HIGH_SDK_PACKAGE)).isFalse();
}
@Test
public void testSetForceAppStandby_forcePreOApp_forceTwoRestrictions() {
mBatteryUtils.setForceAppStandby(UID, LOW_SDK_PACKAGE, AppOpsManager.MODE_IGNORED);
// Restrict both OP_RUN_IN_BACKGROUND and OP_RUN_ANY_IN_BACKGROUND
verify(mAppOpsManager).setMode(AppOpsManager.OP_RUN_IN_BACKGROUND, UID, LOW_SDK_PACKAGE,
AppOpsManager.MODE_IGNORED);
verify(mAppOpsManager).setMode(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, UID, LOW_SDK_PACKAGE,
AppOpsManager.MODE_IGNORED);
}
@Test
public void testSetForceAppStandby_forceOApp_forceOneRestriction() {
mBatteryUtils.setForceAppStandby(UID, HIGH_SDK_PACKAGE, AppOpsManager.MODE_IGNORED);
// Don't restrict OP_RUN_IN_BACKGROUND because it is already been restricted for O app
verify(mAppOpsManager, never()).setMode(AppOpsManager.OP_RUN_IN_BACKGROUND, UID,
HIGH_SDK_PACKAGE, AppOpsManager.MODE_IGNORED);
// Restrict OP_RUN_ANY_IN_BACKGROUND
verify(mAppOpsManager).setMode(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, UID,
HIGH_SDK_PACKAGE, AppOpsManager.MODE_IGNORED);
}
}

View File

@@ -27,10 +27,13 @@ import android.text.format.DateUtils;
import com.android.settings.R;
import com.android.settings.TestConfig;
import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
import com.android.settings.fuelgauge.batterytip.tips.HighUsageTip;
import com.android.settings.fuelgauge.batterytip.tips.RestrictAppTip;
import com.android.settings.fuelgauge.batterytip.tips.UnrestrictAppTip;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.shadow.ShadowRuntimePermissionPresenter;
import com.android.settings.testutils.shadow.ShadowUtils;
import org.junit.Before;
import org.junit.Test;
@@ -47,14 +50,18 @@ import java.util.List;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION,
shadows = ShadowRuntimePermissionPresenter.class)
shadows = ShadowUtils.class)
public class BatteryTipDialogFragmentTest {
private static final String PACKAGE_NAME = "com.android.app";
private static final String DISPLAY_NAME = "app";
private static final long SCREEN_TIME_MS = DateUtils.HOUR_IN_MILLIS;
private BatteryTipDialogFragment mDialogFragment;
private Context mContext;
private HighUsageTip mHighUsageTip;
private RestrictAppTip mRestrictedOneAppTip;
private RestrictAppTip mRestrictAppsTip;
private UnrestrictAppTip mUnrestrictAppTip;
@Before
public void setUp() {
@@ -64,9 +71,22 @@ public class BatteryTipDialogFragmentTest {
FakeFeatureFactory.setupForTest();
List<AppInfo> highUsageTips = new ArrayList<>();
highUsageTips.add(new AppInfo.Builder().setScreenOnTimeMs(SCREEN_TIME_MS).setPackageName(
PACKAGE_NAME).build());
final AppInfo appInfo = new AppInfo.Builder()
.setScreenOnTimeMs(SCREEN_TIME_MS)
.setPackageName(PACKAGE_NAME)
.build();
highUsageTips.add(appInfo);
mHighUsageTip = new HighUsageTip(SCREEN_TIME_MS, highUsageTips);
final List<AppInfo> restrictApps = new ArrayList<>();
restrictApps.add(appInfo);
mRestrictedOneAppTip = new RestrictAppTip(BatteryTip.StateType.NEW,
new ArrayList<>(restrictApps));
restrictApps.add(appInfo);
mRestrictAppsTip = new RestrictAppTip(BatteryTip.StateType.NEW,
new ArrayList<>(restrictApps));
mUnrestrictAppTip = new UnrestrictAppTip(BatteryTip.StateType.NEW, appInfo);
}
@Test
@@ -82,5 +102,49 @@ public class BatteryTipDialogFragmentTest {
mContext.getString(R.string.battery_tip_dialog_message, "1h"));
}
@Test
public void testOnCreateDialog_restrictOneAppTip_fireRestrictOneAppDialog() {
mDialogFragment = BatteryTipDialogFragment.newInstance(mRestrictedOneAppTip);
FragmentTestUtil.startFragment(mDialogFragment);
final AlertDialog dialog = (AlertDialog) ShadowDialog.getLatestDialog();
ShadowAlertDialog shadowDialog = shadowOf(dialog);
assertThat(shadowDialog.getTitle()).isEqualTo("Restrict app?");
assertThat(shadowDialog.getMessage()).isEqualTo(
mContext.getString(R.string.battery_tip_restrict_app_dialog_message));
}
@Test
public void testOnCreateDialog_restrictAppsTip_fireRestrictAppsDialog() {
mDialogFragment = BatteryTipDialogFragment.newInstance(mRestrictAppsTip);
FragmentTestUtil.startFragment(mDialogFragment);
final AlertDialog dialog = (AlertDialog) ShadowDialog.getLatestDialog();
ShadowAlertDialog shadowDialog = shadowOf(dialog);
assertThat(shadowDialog.getTitle()).isEqualTo("Restrict 2 apps?");
assertThat(shadowDialog.getMessage()).isEqualTo(
mContext.getString(R.string.battery_tip_restrict_app_dialog_message));
assertThat(shadowDialog.getView()).isNotNull();
}
@Test
public void testOnCreateDialog_unRestrictAppTip_fireUnRestrictDialog() {
mDialogFragment = BatteryTipDialogFragment.newInstance(mUnrestrictAppTip);
ShadowUtils.setApplicationLabel(PACKAGE_NAME, DISPLAY_NAME);
FragmentTestUtil.startFragment(mDialogFragment);
final AlertDialog dialog = (AlertDialog) ShadowDialog.getLatestDialog();
ShadowAlertDialog shadowDialog = shadowOf(dialog);
assertThat(shadowDialog.getTitle()).isEqualTo("Remove restriction for app?");
assertThat(shadowDialog.getMessage()).isEqualTo(
mContext.getString(R.string.battery_tip_unrestrict_app_dialog_message));
}
}

View File

@@ -51,6 +51,7 @@ import java.util.List;
public class BatteryTipLoaderTest {
private static final int[] TIP_ORDER = {
BatteryTip.TipType.SMART_BATTERY_MANAGER,
BatteryTip.TipType.APP_RESTRICTION,
BatteryTip.TipType.HIGH_DEVICE_USAGE,
BatteryTip.TipType.BATTERY_SAVER,
BatteryTip.TipType.LOW_BATTERY,

View File

@@ -0,0 +1,83 @@
/*
* 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.fuelgauge.batterytip.actions;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.verify;
import android.app.AppOpsManager;
import android.content.Context;
import com.android.settings.TestConfig;
import com.android.settings.fuelgauge.BatteryUtils;
import com.android.settings.fuelgauge.batterytip.AppInfo;
import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
import com.android.settings.fuelgauge.batterytip.tips.RestrictAppTip;
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 org.robolectric.annotation.Config;
import java.util.ArrayList;
import java.util.List;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class RestrictAppActionTest {
private static final String PACKAGE_NAME_1 = "com.android.app1";
private static final String PACKAGE_NAME_2 = "com.android.app2";
@Mock
private BatteryUtils mBatteryUtils;
private Context mContext;
private RestrictAppAction mRestrictAppAction;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
final List<AppInfo> mAppInfos = new ArrayList<>();
mAppInfos.add(new AppInfo.Builder()
.setPackageName(PACKAGE_NAME_1)
.build());
mAppInfos.add(new AppInfo.Builder()
.setPackageName(PACKAGE_NAME_2)
.build());
mRestrictAppAction = new RestrictAppAction(mContext, new RestrictAppTip(
BatteryTip.StateType.NEW, mAppInfos));
mRestrictAppAction.mBatteryUtils = mBatteryUtils;
}
@Test
public void testHandlePositiveAction() {
mRestrictAppAction.handlePositiveAction();
verify(mBatteryUtils).setForceAppStandby(anyInt(), eq(PACKAGE_NAME_1),
eq(AppOpsManager.MODE_IGNORED));
verify(mBatteryUtils).setForceAppStandby(anyInt(), eq(PACKAGE_NAME_2),
eq(AppOpsManager.MODE_IGNORED));
}
}

View File

@@ -0,0 +1,111 @@
/*
* 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.fuelgauge.batterytip.tips;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.Parcel;
import com.android.settings.TestConfig;
import com.android.settings.fuelgauge.batterytip.AppInfo;
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 org.robolectric.annotation.Config;
import java.util.ArrayList;
import java.util.List;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class RestrictAppTipTest {
private static final String PACKAGE_NAME = "com.android.app";
private static final String DISPLAY_NAME = "app";
private Context mContext;
private RestrictAppTip mNewBatteryTip;
private RestrictAppTip mHandledBatteryTip;
private List<AppInfo> mUsageAppList;
@Mock
private ApplicationInfo mApplicationInfo;
@Mock
private PackageManager mPackageManager;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application);
doReturn(mPackageManager).when(mContext).getPackageManager();
doReturn(mApplicationInfo).when(mPackageManager).getApplicationInfo(PACKAGE_NAME,
PackageManager.MATCH_DISABLED_COMPONENTS | PackageManager.MATCH_ANY_USER);
doReturn(DISPLAY_NAME).when(mApplicationInfo).loadLabel(mPackageManager);
mUsageAppList = new ArrayList<>();
mUsageAppList.add(new AppInfo.Builder()
.setPackageName(PACKAGE_NAME)
.build());
mNewBatteryTip = new RestrictAppTip(BatteryTip.StateType.NEW, mUsageAppList);
mHandledBatteryTip = new RestrictAppTip(BatteryTip.StateType.HANDLED, mUsageAppList);
}
@Test
public void testParcelable() {
Parcel parcel = Parcel.obtain();
mNewBatteryTip.writeToParcel(parcel, mNewBatteryTip.describeContents());
parcel.setDataPosition(0);
final RestrictAppTip parcelTip = new RestrictAppTip(parcel);
assertThat(parcelTip.getType()).isEqualTo(BatteryTip.TipType.APP_RESTRICTION);
assertThat(parcelTip.getState()).isEqualTo(BatteryTip.StateType.NEW);
final AppInfo app = parcelTip.getRestrictAppList().get(0);
assertThat(app.packageName).isEqualTo(PACKAGE_NAME);
}
@Test
public void testGetTitle_stateNew_showRestrictTitle() {
assertThat(mNewBatteryTip.getTitle(mContext)).isEqualTo("Restrict 1 app");
}
@Test
public void testGetTitle_stateHandled_showHandledTitle() {
assertThat(mHandledBatteryTip.getTitle(mContext)).isEqualTo("1 recently restricted");
}
@Test
public void testGetSummary_stateNew_showRestrictSummary() {
assertThat(mNewBatteryTip.getSummary(mContext)).isEqualTo(
"app has high battery usage");
}
@Test
public void testGetSummary_stateHandled_showHandledSummary() {
assertThat(mHandledBatteryTip.getSummary(mContext)).isEqualTo(
"App changes are in progress");
}
}

View File

@@ -0,0 +1,61 @@
/*
* 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.fuelgauge.batterytip.tips;
import static com.google.common.truth.Truth.assertThat;
import android.os.Parcel;
import com.android.settings.TestConfig;
import com.android.settings.fuelgauge.batterytip.AppInfo;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.MockitoAnnotations;
import org.robolectric.annotation.Config;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class UnrestrictAppTipTest {
private static final String PACKAGE_NAME = "com.android.app";
private UnrestrictAppTip mBatteryTip;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
AppInfo appInfo = new AppInfo.Builder()
.setPackageName(PACKAGE_NAME)
.build();
mBatteryTip = new UnrestrictAppTip(BatteryTip.StateType.NEW, appInfo);
}
@Test
public void testParcelable() {
Parcel parcel = Parcel.obtain();
mBatteryTip.writeToParcel(parcel, mBatteryTip.describeContents());
parcel.setDataPosition(0);
final UnrestrictAppTip parcelTip = new UnrestrictAppTip(parcel);
assertThat(parcelTip.getType()).isEqualTo(BatteryTip.TipType.REMOVE_APP_RESTRICTION);
assertThat(parcelTip.getState()).isEqualTo(BatteryTip.StateType.NEW);
assertThat(parcelTip.getPackageName()).isEqualTo(PACKAGE_NAME);
}
}

View File

@@ -0,0 +1,220 @@
/*
* 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.location;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.arch.lifecycle.LifecycleOwner;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
import android.location.LocationManager;
import android.os.Bundle;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceCategory;
import com.android.settings.TestConfig;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settingslib.core.lifecycle.Lifecycle;
import java.util.ArrayList;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
/** Unit tests for {@link LocationFooterPreferenceController} */
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class LocationFooterPreferenceControllerTest {
@Mock
private PreferenceCategory mPreferenceCategory;
@Mock
private PackageManager mPackageManager;
@Mock
private Resources mResources;
private Context mContext;
private LocationFooterPreferenceController mController;
private LifecycleOwner mLifecycleOwner;
private Lifecycle mLifecycle;
private static final int TEST_RES_ID = 1234;
private static final String TEST_TEXT = "text";
@Before
public void setUp() throws NameNotFoundException {
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application);
when(mContext.getPackageManager()).thenReturn(mPackageManager);
mLifecycleOwner = () -> mLifecycle;
mLifecycle = new Lifecycle(mLifecycleOwner);
when(mPreferenceCategory.getContext()).thenReturn(mContext);
mController = spy(new LocationFooterPreferenceController(mContext, mLifecycle));
when(mPackageManager.getResourcesForApplication(any(ApplicationInfo.class)))
.thenReturn(mResources);
when(mResources.getString(TEST_RES_ID)).thenReturn(TEST_TEXT);
doNothing().when(mPreferenceCategory).removeAll();
}
@Test
public void isAvailable_hasValidFooter_returnsTrue() throws NameNotFoundException {
final List<ResolveInfo> testResolveInfos = new ArrayList<>();
testResolveInfos.add(
getTestResolveInfo(/*isSystemApp*/ true, /*hasRequiredMetadata*/ true));
when(mPackageManager.queryBroadcastReceivers(any(Intent.class), anyInt()))
.thenReturn(testResolveInfos);
assertThat(mController.isAvailable()).isTrue();
}
@Test
public void isAvailable_noSystemApp_returnsFalse() throws NameNotFoundException {
final List<ResolveInfo> testResolveInfos = new ArrayList<>();
testResolveInfos.add(
getTestResolveInfo(/*isSystemApp*/ false, /*hasRequiredMetadata*/ true));
when(mPackageManager.queryBroadcastReceivers(any(Intent.class), anyInt()))
.thenReturn(testResolveInfos);
assertThat(mController.isAvailable()).isFalse();
}
@Test
public void isAvailable_noRequiredMetadata_returnsFalse() throws NameNotFoundException {
final List<ResolveInfo> testResolveInfos = new ArrayList<>();
testResolveInfos.add(
getTestResolveInfo(/*isSystemApp*/ true, /*hasRequiredMetadata*/ false));
when(mPackageManager.queryBroadcastReceivers(any(Intent.class), anyInt()))
.thenReturn(testResolveInfos);
assertThat(mController.isAvailable()).isFalse();
}
@Test
public void sendBroadcastFooterInject() {
ArgumentCaptor<Intent> intent = ArgumentCaptor.forClass(Intent.class);
final ActivityInfo activityInfo =
getTestResolveInfo(/*isSystemApp*/ true, /*hasRequiredMetadata*/ true).activityInfo;
mController.sendBroadcastFooterDisplayed(
new ComponentName(activityInfo.packageName, activityInfo.name));
verify(mContext).sendBroadcast(intent.capture());
assertThat(intent.getValue().getAction())
.isEqualTo(LocationManager.SETTINGS_FOOTER_DISPLAYED_ACTION);
}
@Test
public void updateState_sendBroadcast() throws NameNotFoundException {
final List<ResolveInfo> testResolveInfos = new ArrayList<>();
testResolveInfos.add(
getTestResolveInfo(/*isSystemApp*/ true, /*hasRequiredMetadata*/ true));
when(mPackageManager.queryBroadcastReceivers(any(), anyInt()))
.thenReturn(testResolveInfos);
mController.updateState(mPreferenceCategory);
ArgumentCaptor<Intent> intent = ArgumentCaptor.forClass(Intent.class);
verify(mContext).sendBroadcast(intent.capture());
assertThat(intent.getValue().getAction())
.isEqualTo(LocationManager.SETTINGS_FOOTER_DISPLAYED_ACTION);
}
@Test
public void updateState_addPreferences() throws NameNotFoundException {
final List<ResolveInfo> testResolveInfos = new ArrayList<>();
testResolveInfos.add(
getTestResolveInfo(/*isSystemApp*/ true, /*hasRequiredMetadata*/ true));
when(mPackageManager.queryBroadcastReceivers(any(Intent.class), anyInt()))
.thenReturn(testResolveInfos);
mController.updateState(mPreferenceCategory);
ArgumentCaptor<Preference> pref = ArgumentCaptor.forClass(Preference.class);
verify(mPreferenceCategory).addPreference(pref.capture());
assertThat(pref.getValue().getTitle()).isEqualTo(TEST_TEXT);
}
@Test
public void updateState_notSystemApp_ignore() throws NameNotFoundException {
final List<ResolveInfo> testResolveInfos = new ArrayList<>();
testResolveInfos.add(
getTestResolveInfo(/*isSystemApp*/ false, /*hasRequiredMetadata*/ true));
when(mPackageManager.queryBroadcastReceivers(any(Intent.class), anyInt()))
.thenReturn(testResolveInfos);
mController.updateState(mPreferenceCategory);
verify(mPreferenceCategory, never()).addPreference(any(Preference.class));
verify(mContext, never()).sendBroadcast(any(Intent.class));
}
@Test
public void updateState_thenOnPause_sendBroadcasts() throws NameNotFoundException {
final List<ResolveInfo> testResolveInfos = new ArrayList<>();
testResolveInfos.add(
getTestResolveInfo(/*isSystemApp*/ true, /*hasRequiredMetadata*/ true));
when(mPackageManager.queryBroadcastReceivers(any(Intent.class), anyInt()))
.thenReturn(testResolveInfos);
mController.updateState(mPreferenceCategory);
ArgumentCaptor<Intent> intent = ArgumentCaptor.forClass(Intent.class);
verify(mContext).sendBroadcast(intent.capture());
assertThat(intent.getValue().getAction())
.isEqualTo(LocationManager.SETTINGS_FOOTER_DISPLAYED_ACTION);
mController.onPause();
verify(mContext, times(2)).sendBroadcast(intent.capture());
assertThat(intent.getValue().getAction())
.isEqualTo(LocationManager.SETTINGS_FOOTER_REMOVED_ACTION);
}
@Test
public void onPause_doNotSendBroadcast() {
mController.onPause();
verify(mContext, never()).sendBroadcast(any(Intent.class));
}
/**
* Returns a ResolveInfo object for testing
* @param isSystemApp If true, the application is a system app.
* @param hasRequiredMetaData If true, the broadcast receiver has a valid value for
* {@link LocationManager#METADATA_SETTINGS_FOOTER_STRING}
*/
private ResolveInfo getTestResolveInfo(boolean isSystemApp, boolean hasRequiredMetaData) {
ResolveInfo testResolveInfo = new ResolveInfo();
ApplicationInfo testAppInfo = new ApplicationInfo();
if (isSystemApp) {
testAppInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
}
ActivityInfo testActivityInfo = new ActivityInfo();
testActivityInfo.name = "TestActivityName";
testActivityInfo.packageName = "TestPackageName";
testActivityInfo.applicationInfo = testAppInfo;
if (hasRequiredMetaData) {
testActivityInfo.metaData = new Bundle();
testActivityInfo.metaData.putInt(
LocationManager.METADATA_SETTINGS_FOOTER_STRING, TEST_RES_ID);
}
testResolveInfo.activityInfo = testActivityInfo;
return testResolveInfo;
}
}

View File

@@ -27,6 +27,9 @@ import com.android.settings.wrapper.FingerprintManagerWrapper;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import java.util.HashMap;
import java.util.Map;
@Implements(Utils.class)
public class ShadowUtils {
@@ -34,6 +37,7 @@ public class ShadowUtils {
private static boolean sIsUserAMonkey;
private static boolean sIsDemoUser;
private static ComponentName sDeviceOwnerComponentName;
private static Map<String, String> sAppNameMap;
@Implementation
public static int enforceSameOwner(Context context, int userId) {
@@ -89,4 +93,19 @@ public class ShadowUtils {
public static int getManagedProfileId(UserManager um, int parentUserId) {
return UserHandle.USER_NULL;
}
@Implementation
public static CharSequence getApplicationLabel(Context context, String packageName) {
if (sAppNameMap != null) {
return sAppNameMap.get(packageName);
}
return null;
}
public static void setApplicationLabel(String packageName, String appLabel) {
if (sAppNameMap == null) {
sAppNameMap = new HashMap<>();
}
sAppNameMap.put(packageName, appLabel);
}
}

View File

@@ -36,6 +36,8 @@ import org.robolectric.annotation.Config;
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class AppPreferenceTest {
private static final int EXPECTED_APP_ICON_SIZE_DP = 32;
private Context mContext;
private View mRootView;
private AppPreference mPref;
@@ -75,4 +77,12 @@ public class AppPreferenceTest {
assertThat(mHolder.findViewById(R.id.summary_container).getVisibility())
.isEqualTo(View.GONE);
}
@Test
public void foobar_testName() {
// Can't use isEquals() to compare float. Use isWithIn().of() instead.
assertThat(mContext.getResources().getDimension(R.dimen.secondary_app_icon_size))
.isWithin(0.01f)
.of(EXPECTED_APP_ICON_SIZE_DP);
}
}

View File

@@ -73,7 +73,8 @@ import java.util.ArrayList;
})
public class WifiTetherPreferenceControllerTest {
@Mock
private static final String SSID = "Pixel";
private Context mContext;
@Mock
private ConnectivityManager mConnectivityManager;
@@ -81,6 +82,8 @@ public class WifiTetherPreferenceControllerTest {
private WifiManager mWifiManager;
@Mock
private PreferenceScreen mScreen;
@Mock
private WifiConfiguration mWifiConfiguration;
private WifiTetherPreferenceController mController;
private Lifecycle mLifecycle;
@@ -90,6 +93,8 @@ public class WifiTetherPreferenceControllerTest {
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application);
mLifecycleOwner = () -> mLifecycle;
mLifecycle = new Lifecycle(mLifecycleOwner);
FakeFeatureFactory.setupForTest();
@@ -98,10 +103,13 @@ public class WifiTetherPreferenceControllerTest {
.thenReturn(mConnectivityManager);
when(mContext.getSystemService(Context.WIFI_SERVICE)).thenReturn(mWifiManager);
when(mScreen.findPreference(anyString())).thenReturn(mPreference);
when(mWifiManager.getWifiApConfiguration()).thenReturn(mWifiConfiguration);
mWifiConfiguration.SSID = SSID;
when(mConnectivityManager.getTetherableWifiRegexs()).thenReturn(new String[]{"1", "2"});
mController = new WifiTetherPreferenceController(mContext, mLifecycle,
false /* initSoftApManager */);
mController.displayPreference(mScreen);
}
@After
@@ -127,7 +135,6 @@ public class WifiTetherPreferenceControllerTest {
public void startAndStop_shouldRegisterUnregisterReceiver() {
final BroadcastReceiver receiver = ReflectionHelpers.getField(mController, "mReceiver");
mController.displayPreference(mScreen);
mLifecycle.handleLifecycleEvent(ON_START);
mLifecycle.handleLifecycleEvent(ON_STOP);
@@ -166,48 +173,6 @@ public class WifiTetherPreferenceControllerTest {
verify(pref).setChecked(true);
}
@Test
public void testReceiver_apStateChangedToDisabled_shouldUpdatePreferenceSummary() {
mController.displayPreference(mScreen);
receiveApStateChangedBroadcast(WifiManager.WIFI_AP_STATE_DISABLED);
assertThat(mPreference.getSummary().toString()).isEqualTo(
RuntimeEnvironment.application.getString(R.string.wifi_hotspot_off_subtext));
}
@Test
public void testReceiver_apStateChangedToDisabling_shouldUpdatePreferenceSummary() {
mController.displayPreference(mScreen);
receiveApStateChangedBroadcast(WifiManager.WIFI_AP_STATE_DISABLING);
assertThat(mPreference.getSummary().toString()).isEqualTo(
RuntimeEnvironment.application.getString(R.string.wifi_tether_stopping));
}
@Test
public void testReceiver_apStateChangedToEnabling_shouldUpdatePreferenceSummary() {
mController.displayPreference(mScreen);
receiveApStateChangedBroadcast(WifiManager.WIFI_AP_STATE_ENABLING);
assertThat(mPreference.getSummary().toString()).isEqualTo(
RuntimeEnvironment.application.getString(R.string.wifi_tether_starting));
}
@Test
public void testReceiver_apStateChangedToEnabled_shouldNotUpdatePreferenceSummary() {
mController.displayPreference(mScreen);
receiveApStateChangedBroadcast(WifiManager.WIFI_AP_STATE_DISABLED);
assertThat(mPreference.getSummary().toString()).isEqualTo(
RuntimeEnvironment.application.getString(R.string.wifi_hotspot_off_subtext));
// When turning on the hotspot, we receive STATE_ENABLING followed by STATE_ENABLED. The
// first should change the status to wifi_tether_starting, and the second should not change
// this.
receiveApStateChangedBroadcast(WifiManager.WIFI_AP_STATE_ENABLING);
assertThat(mPreference.getSummary().toString()).isEqualTo(
RuntimeEnvironment.application.getString(R.string.wifi_tether_starting));
receiveApStateChangedBroadcast(WifiManager.WIFI_AP_STATE_ENABLED);
assertThat(mPreference.getSummary().toString()).isEqualTo(
RuntimeEnvironment.application.getString(R.string.wifi_tether_starting));
}
@Test
public void testReceiver_goingToAirplaneMode_shouldClearPreferenceSummary() {
final ContentResolver cr = mock(ContentResolver.class);
@@ -224,22 +189,32 @@ public class WifiTetherPreferenceControllerTest {
}
@Test
public void testReceiver_tetherEnabled_shouldUpdatePreferenceSummary() {
mController.displayPreference(mScreen);
final BroadcastReceiver receiver = ReflectionHelpers.getField(mController, "mReceiver");
final Intent broadcast = new Intent(ConnectivityManager.ACTION_TETHER_STATE_CHANGED);
final ArrayList<String> activeTethers = new ArrayList<>();
activeTethers.add("1");
broadcast.putStringArrayListExtra(ConnectivityManager.EXTRA_ACTIVE_TETHER, activeTethers);
broadcast.putStringArrayListExtra(ConnectivityManager.EXTRA_ERRORED_TETHER,
new ArrayList<>());
final WifiConfiguration configuration = new WifiConfiguration();
configuration.SSID = "test-ap";
when(mWifiManager.getWifiApConfiguration()).thenReturn(configuration);
public void testHandleWifiApStateChanged_stateEnabling_showEnablingSummary() {
mController.handleWifiApStateChanged(WifiManager.WIFI_AP_STATE_ENABLING, 0 /* reason */);
receiver.onReceive(RuntimeEnvironment.application, broadcast);
assertThat(mPreference.getSummary()).isEqualTo("Turning hotspot on\u2026");
}
verify(mContext).getString(eq(R.string.wifi_tether_enabled_subtext), any());
@Test
public void testHandleWifiApStateChanged_stateEnabled_showEnabledSummary() {
mController.handleWifiApStateChanged(WifiManager.WIFI_AP_STATE_ENABLED, 0 /* reason */);
assertThat(mPreference.getSummary()).isEqualTo("Pixel is active");
}
@Test
public void testHandleWifiApStateChanged_stateDisabling_showDisablingSummary() {
mController.handleWifiApStateChanged(WifiManager.WIFI_AP_STATE_DISABLING, 0 /* reason */);
assertThat(mPreference.getSummary()).isEqualTo("Turning off hotspot\u2026");
}
@Test
public void testHandleWifiApStateChanged_stateDisabled_showDisabledSummary() {
mController.handleWifiApStateChanged(WifiManager.WIFI_AP_STATE_DISABLED, 0 /* reason */);
assertThat(mPreference.getSummary()).isEqualTo(
"Not sharing internet or content with other devices");
}
@Implements(WifiTetherSettings.class)
@@ -285,17 +260,4 @@ public class WifiTetherPreferenceControllerTest {
onStopCalled = true;
}
}
/**
* Helper to cause the controller to receive a WIFI_AP_STATE_CHANGED_ACTION with a specific
* state.
*
* @param state - the state, as specified by one of the WifiManager.WIFI_AP_STATE_* values
*/
private void receiveApStateChangedBroadcast(int state) {
final BroadcastReceiver receiver = ReflectionHelpers.getField(mController, "mReceiver");
final Intent broadcast = new Intent(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
broadcast.putExtra(WifiManager.EXTRA_WIFI_AP_STATE, state);
receiver.onReceive(RuntimeEnvironment.application, broadcast);
}
}